From 3a8e6e8dd5f237b507b9b9c0881b0321584b97d3 Mon Sep 17 00:00:00 2001 From: qian-o <1324771795@qq.com> Date: Wed, 16 Sep 2026 15:00:16 +0800 Subject: [PATCH 01/35] Add ImGuiBinding extension properties for textures Introduce Extensions.cs with ImGuiBinding properties for Texture and TextureView. Refactor ImGuiController to use GCHandle for BackendRendererUserData, enabling instance retrieval. Make binding methods internal and update usage in App.cs to use new extensions. Improve encapsulation and idiomatic access to ImGui texture bindings. --- sources/Experiments/CornellBox/App.cs | 3 ++- sources/Experiments/FluidTank/App.cs | 3 ++- .../Zenith.NET.Extensions.ImGui/Extensions.cs | 23 ++++++++++++++++ .../ImGuiController.cs | 26 ++++++++++++------- 4 files changed, 43 insertions(+), 12 deletions(-) create mode 100644 sources/Extensions/Zenith.NET.Extensions.ImGui/Extensions.cs diff --git a/sources/Experiments/CornellBox/App.cs b/sources/Experiments/CornellBox/App.cs index 4fdbf5a2..af55a8aa 100644 --- a/sources/Experiments/CornellBox/App.cs +++ b/sources/Experiments/CornellBox/App.cs @@ -7,6 +7,7 @@ using Silk.NET.Windowing; using Zenith.NET; using Zenith.NET.DirectX12; +using Zenith.NET.Extensions.ImGui; using Zenith.NET.Metal; using Zenith.NET.Vulkan; @@ -140,7 +141,7 @@ public static void Run() } }); - ImGui.GetBackgroundDrawList().AddImage(imGui.Binding(renderer.Color), new(0, 0), new(Width / DpiScale.X, Height / DpiScale.Y)); + ImGui.GetBackgroundDrawList().AddImage(renderer.Color.ImGuiBinding, new(0, 0), new(Width / DpiScale.X, Height / DpiScale.Y)); }; window.Render += static _ => diff --git a/sources/Experiments/FluidTank/App.cs b/sources/Experiments/FluidTank/App.cs index b07b6bf4..27fc1ea9 100644 --- a/sources/Experiments/FluidTank/App.cs +++ b/sources/Experiments/FluidTank/App.cs @@ -7,6 +7,7 @@ using Silk.NET.Windowing; using Zenith.NET; using Zenith.NET.DirectX12; +using Zenith.NET.Extensions.ImGui; using Zenith.NET.Metal; using Zenith.NET.Vulkan; @@ -152,7 +153,7 @@ public static void Run() } }); - ImGui.GetBackgroundDrawList().AddImage(imGui.Binding(renderer.Color), new(0, 0), new(Width / DpiScale.X, Height / DpiScale.Y)); + ImGui.GetBackgroundDrawList().AddImage(renderer.Color.ImGuiBinding, new(0, 0), new(Width / DpiScale.X, Height / DpiScale.Y)); }; window.Render += static _ => diff --git a/sources/Extensions/Zenith.NET.Extensions.ImGui/Extensions.cs b/sources/Extensions/Zenith.NET.Extensions.ImGui/Extensions.cs new file mode 100644 index 00000000..44fdf72d --- /dev/null +++ b/sources/Extensions/Zenith.NET.Extensions.ImGui/Extensions.cs @@ -0,0 +1,23 @@ +using System.Runtime.InteropServices; +using Hexa.NET.ImGui; +using HexaImGui = Hexa.NET.ImGui.ImGui; + +namespace Zenith.NET.Extensions.ImGui; + +public static class Extensions +{ + extension(Texture texture) + { + public ImTextureRef ImGuiBinding => Controller().Binding(texture); + } + + extension(TextureView textureView) + { + public ImTextureRef ImGuiBinding => Controller().Binding(textureView); + } + + private static unsafe ImGuiController Controller() + { + return (ImGuiController)GCHandle.FromIntPtr((nint)HexaImGui.GetIO().BackendRendererUserData).Target!; + } +} diff --git a/sources/Extensions/Zenith.NET.Extensions.ImGui/ImGuiController.cs b/sources/Extensions/Zenith.NET.Extensions.ImGui/ImGuiController.cs index 0a9771d1..cc7498ed 100644 --- a/sources/Extensions/Zenith.NET.Extensions.ImGui/ImGuiController.cs +++ b/sources/Extensions/Zenith.NET.Extensions.ImGui/ImGuiController.cs @@ -7,6 +7,7 @@ namespace Zenith.NET.Extensions.ImGui; public unsafe class ImGuiController : DisposableObject { + private readonly GCHandle handle; private readonly ImGuiRenderer renderer; private readonly PlatformGetClipboardTextFn platformGetClipboardText; private readonly PlatformSetClipboardTextFn platformSetClipboardText; @@ -36,6 +37,7 @@ public ImGuiController(GraphicsContext context, AttachmentFormats attachmentForm io.BackendFlags |= ImGuiBackendFlags.HasMouseCursors; io.BackendFlags |= ImGuiBackendFlags.RendererHasVtxOffset; io.BackendFlags |= ImGuiBackendFlags.RendererHasTextures; + io.BackendRendererUserData = (void*)GCHandle.ToIntPtr(handle = GCHandle.Alloc(this, GCHandleType.Weak)); if (fontPath is not null) { @@ -66,16 +68,6 @@ public ImGuiController(GraphicsContext context, AttachmentFormats attachmentForm public IImGuiPlatformBindings? PlatformBindings { get; set; } - public ImTextureRef Binding(Texture texture) - { - return new(null, renderer.Binding(texture)); - } - - public ImTextureRef Binding(TextureView textureView) - { - return new(null, renderer.Binding(textureView)); - } - public void Update(double delta, uint width, uint height) { HexaImGui.SetCurrentContext(Context); @@ -191,17 +183,31 @@ public void KeyChar(char c) protected override void Destroy() { + HexaImGui.SetCurrentContext(Context); + HexaImGui.GetIO().Handle->BackendRendererUserData = null; + clipboardScope?.Dispose(); platformSetImeDataHandle.Free(); platformSetClipboardTextHandle.Free(); platformGetClipboardTextHandle.Free(); renderer.Dispose(); + handle.Free(); HexaImGui.SetCurrentContext(null); HexaImGui.DestroyContext(Context); } + internal ImTextureRef Binding(Texture texture) + { + return new(null, renderer.Binding(texture)); + } + + internal ImTextureRef Binding(TextureView textureView) + { + return new(null, renderer.Binding(textureView)); + } + private byte* PlatformGetClipboardText(ImGuiContext* context) { clipboardScope?.Dispose(); From 2ce6983b37cabf0e74a1989e1587f539095893af Mon Sep 17 00:00:00 2001 From: qian-o <1324771795@qq.com> Date: Wed, 16 Sep 2026 15:36:31 +0800 Subject: [PATCH 02/35] Refactor ImGuiController instance tracking logic Replaced GCHandle-based instance tracking with a [ThreadStatic] ImGuiController.Current field. Updated ImGuiBinding extension methods to use the new static field. Removed GCHandle allocation and freeing logic, simplifying controller lookup and avoiding direct use of BackendRendererUserData. --- .../Zenith.NET.Extensions.ImGui/Extensions.cs | 13 +++---------- .../Zenith.NET.Extensions.ImGui/ImGuiController.cs | 11 +++++------ 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/sources/Extensions/Zenith.NET.Extensions.ImGui/Extensions.cs b/sources/Extensions/Zenith.NET.Extensions.ImGui/Extensions.cs index 44fdf72d..55d763ec 100644 --- a/sources/Extensions/Zenith.NET.Extensions.ImGui/Extensions.cs +++ b/sources/Extensions/Zenith.NET.Extensions.ImGui/Extensions.cs @@ -1,6 +1,4 @@ -using System.Runtime.InteropServices; -using Hexa.NET.ImGui; -using HexaImGui = Hexa.NET.ImGui.ImGui; +using Hexa.NET.ImGui; namespace Zenith.NET.Extensions.ImGui; @@ -8,16 +6,11 @@ public static class Extensions { extension(Texture texture) { - public ImTextureRef ImGuiBinding => Controller().Binding(texture); + public ImTextureRef ImGuiBinding => ImGuiController.Current?.Binding(texture) ?? default; } extension(TextureView textureView) { - public ImTextureRef ImGuiBinding => Controller().Binding(textureView); - } - - private static unsafe ImGuiController Controller() - { - return (ImGuiController)GCHandle.FromIntPtr((nint)HexaImGui.GetIO().BackendRendererUserData).Target!; + public ImTextureRef ImGuiBinding => ImGuiController.Current?.Binding(textureView) ?? default; } } diff --git a/sources/Extensions/Zenith.NET.Extensions.ImGui/ImGuiController.cs b/sources/Extensions/Zenith.NET.Extensions.ImGui/ImGuiController.cs index cc7498ed..49bf1fbd 100644 --- a/sources/Extensions/Zenith.NET.Extensions.ImGui/ImGuiController.cs +++ b/sources/Extensions/Zenith.NET.Extensions.ImGui/ImGuiController.cs @@ -7,7 +7,9 @@ namespace Zenith.NET.Extensions.ImGui; public unsafe class ImGuiController : DisposableObject { - private readonly GCHandle handle; + [ThreadStatic] + internal static ImGuiController? Current; + private readonly ImGuiRenderer renderer; private readonly PlatformGetClipboardTextFn platformGetClipboardText; private readonly PlatformSetClipboardTextFn platformSetClipboardText; @@ -37,7 +39,6 @@ public ImGuiController(GraphicsContext context, AttachmentFormats attachmentForm io.BackendFlags |= ImGuiBackendFlags.HasMouseCursors; io.BackendFlags |= ImGuiBackendFlags.RendererHasVtxOffset; io.BackendFlags |= ImGuiBackendFlags.RendererHasTextures; - io.BackendRendererUserData = (void*)GCHandle.ToIntPtr(handle = GCHandle.Alloc(this, GCHandleType.Weak)); if (fontPath is not null) { @@ -130,6 +131,8 @@ public void Update(double delta, uint width, uint height) HexaImGui.NewFrame(); frameBegun = true; + + Current = this; } public void Render(CommandBuffer commandBuffer, ColorAttachment colorAttachment) @@ -183,16 +186,12 @@ public void KeyChar(char c) protected override void Destroy() { - HexaImGui.SetCurrentContext(Context); - HexaImGui.GetIO().Handle->BackendRendererUserData = null; - clipboardScope?.Dispose(); platformSetImeDataHandle.Free(); platformSetClipboardTextHandle.Free(); platformGetClipboardTextHandle.Free(); renderer.Dispose(); - handle.Free(); HexaImGui.SetCurrentContext(null); HexaImGui.DestroyContext(Context); From ec50fc05c8c5e83bce187426613548e0f6537301 Mon Sep 17 00:00:00 2001 From: qian-o <1324771795@qq.com> Date: Wed, 16 Sep 2026 15:46:54 +0800 Subject: [PATCH 03/35] Reset Current to null after frame rendering Added code to set Current = null at the end of the frame, ensuring the ImGuiController instance is cleared or reset after rendering is complete. --- .../Extensions/Zenith.NET.Extensions.ImGui/ImGuiController.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sources/Extensions/Zenith.NET.Extensions.ImGui/ImGuiController.cs b/sources/Extensions/Zenith.NET.Extensions.ImGui/ImGuiController.cs index 49bf1fbd..fea8d3be 100644 --- a/sources/Extensions/Zenith.NET.Extensions.ImGui/ImGuiController.cs +++ b/sources/Extensions/Zenith.NET.Extensions.ImGui/ImGuiController.cs @@ -147,6 +147,8 @@ public void Render(CommandBuffer commandBuffer, ColorAttachment colorAttachment) frameBegun = false; } + + Current = null; } public void MouseDown(ImGuiMouseButton button) From 9a4c1c1a0a0dc1f9a580689613bad7993b25f12e Mon Sep 17 00:00:00 2001 From: qian-o <1324771795@qq.com> Date: Thu, 17 Sep 2026 09:51:16 +0800 Subject: [PATCH 04/35] Update logo assets: replace SVG and PNG files with new designs --- documents/images/Zenith.NET-Logo.png | Bin 19952 -> 6904 bytes documents/images/Zenith.NET-Logo.svg | 46 ++++++--------------------- documents/images/Zenith.NET.png | Bin 8000 -> 3037 bytes documents/images/Zenith.NET.svg | 36 ++++----------------- 4 files changed, 17 insertions(+), 65 deletions(-) diff --git a/documents/images/Zenith.NET-Logo.png b/documents/images/Zenith.NET-Logo.png index bd96a940d8dfb0738b3895af83e54f1414322f8b..7cc4a058482407a9017c238b2089423b67a5ed95 100644 GIT binary patch literal 6904 zcmY+J2{@GB7x<@dcF9imB(ke4Qw);qJ0aOZS!3+R*lL6+b2d(S=R+|L_rsINgs!$|`If#|d}9~px{mx#dc zS5y?h_p)S=6L6#U)U@ycf!G8uK9{tNZxTQt&SI@cDvx2mH!~?evY0k?bA_l()jJ+3 z&NR_SP){iqmAFzw+C@fZ7DT0OVHs5nM@tP@s);PDSlO>ic-hz+LRN-GWP-)(oZoXl zkg*%xq(UGbIYl-fmAF`8QRQofIVI<9KCJ@FR8yw)9y7L6`_@sH0agB=%PhC5YL$q5 z@F%VH88Kn{84TH`RP~EJ<|Xx;8_Hx4`>!yH-B32{*{ItrkWq8p&K$5m$csdBN4qHdTVm! zzY=4Ilx#zWhWz|;UJgS5<&g(tEeCVd(+^B6T>>SxLvjPk{R}xwEKJh&U^I$wpoUA= zI+Sz10(xFontRnAthxXAFt|0;t*m0lYFHB}7cqMJ+uQd#OK9#W-W(+s`SKkdoMK;m z?Nl#`wq@EjClVN-<|ibwm9$zxFO?tYFPFs~GOv>;&nn0SWHT>`|f zuxPp7i;P?x^ud*)AawX4IQ8%|KQ~fjTE?G{kDY zWJ^l3Py3aYL$AdluYf>bclK_|)!=w6=k5m4@@yta9USXFdIwnD&%vN&jy2&#nn!8l zMx)(*Fq%29!a+d%!sPBp8di?A(!`y3+SZZf_4EiN9S9`X&HfUeqJKC1dRcXGtK`^Q z@&FKMw(@vVA@fP(baNMc=QM5p87BzjITpAWOyqnSTfJ1**z}AjI_wDoRf=HH^{)na zqga>|8l^vrfcEt#UEd(fYp99Y9QzW^ zGf=2J=@he`=d?x_IUy>R9>OSPH@Xhx4o6-E zfex8ZeRIh6ws#(G7-1>s8$T(YuH38h-;^(4``fH$4DG1M%#s1K%JP6fFDVS%n(oe+ zxE8CqncIS`P~EN2jmu44S$yy~MI{eNkp1M)MwgaUbz1duRYYt`<-2sb>c^i58;?3n z@ZMOde}iZ~m{m=bC`T}<3U*4b^mtEIdNEgXZf z%u&5G;MFW(SO~m$dE2U4AFj5ey>^DX={Sv zV%M%yq3l;Gxfa|V{GDcJY5&&|Bjn}`cCwyCg9RKxWy-8bdE=I&B{Vb7=TDINU-4VS zjEr{as;TyyLvM7hMccx?ADfw->(uFB;_-PePTNj=Cfkq3J$C5Mmud3Ki?Xw4-@tGR z-Gb-$hkEZ%tll>-;$3d)EctcT(%9J5s6CUOym()5+$l%rUPLv$OPJNXNr7wFg8XXZ zSAPV$Ve6Zv@drqLvvsRIYr5=-#9@19&u)wQs-_(flB^tX^D$+^8aW{eJZ zNiJ`_V`EH24UH1cqyY9TS!d<)a&n=n>KPJessMg>qoof-@pYeMYzdruDw%^s}k55GrU%1L@GJ{wI~S!iT47xIU==tws1NXlnDl zORrT3E^H7f65UjjR(F~WL2@ooV&e5AWH4;yd(yodML2I-laGDY4d67~(!>JtI_&bF zDzWmxmj>slwqv|scbG|hp0>g&_8JrQM3HSYl93*v72L!Cd`c{OsMnAQP)Bf z%$Oi&Ux%;s@3FtaHLF(*RRz{lM!U~#{CDlTjOF8i<&_{kp9(WZjJIR$ z%Dfc%+G}Hem>4yR_LMfi6cPQApA0Zhxi=rY>t2r2^e>!`G5^u?Ycpej*hX-EKK}No z{>NvfnXH5Dnr!iIiK$LB1?msos?0gh_V-oN#V!1vEI++_UN(A87uE_q{-|dKU zxbfNw>!t&fbWlpKz8r?QDhI1}0|0n9vx=6m(GQ zg6zrk#xDnH>jliDiNjo-R|}0<#g_1oOi%^FhgG&F&}jWF?VKOS2il8IsZmVSJL{Hd zosdoW^XqW7L_$Z&B%Od~UfP+~ z9u%}3>9Pj$u*t~D zu)n2K<6AcpsL7N!ot(%f3yJC9lZyFaRMTvTw(|l@1;u#wT|wadX`GzcSpswd8m0tEmNXaT6>g_IA8r*vBcmplXB_4$2ZVRKDEUq|&E$+@6#7@4v@M>$pKbQtkTAa^gYuo--j|v(;Tt+}(+^&_Jsa zFmpB!_I5I**u?KglUkyS;RV48&*aIWF(HJglw%AmD>F$TQ#WXCga;?;2d<^pNwTT4c{z#dd4A6}cb-MkRKQm;l$6Z%w$VqWZ~;vr9xvmZ{vHe>%ih zh*}nbey%(|uGVI%JY@vW{WY&5`IfRw7=~;{x1r%OQAZ0do$7Pa+hC8kHda4f3e@T= zwe8?@%>zp%fI%xcleR(Nvv`R9(;OCPz z4s=ea^f7Pnvg)bV)}B@bF2h3$+x$j>2~{=cvrBVyf*dC!;U=keq$hcFKVAlmnIj#M z0>?l75_*O&ElmIm^nLq*K=ZpL$F7YUNr}1B6UZpz#suz3y{)HIG!w|tCIq5B zyxC5YGS>0kNns^35D=lptF;;{B_?k;GGdz8??3IAjJOD^0wzCOAuoy@z0qCpG%I}} zHcXS6pRX~S0S-AzF(TpdR{HaO*<@US+dER#ZeOQ}D_K_Z$e*#!3bmEwjWvQU+iB4U zUtRB>_+LJ4a9UJ>1F`y4eO2(7;2phG4@5E8-nXPbStGhzCx@F(mnkx{1{WR7uqD=y zQ&%o=Y8wu~BWyP1o{FaiQ)P)x8jx->O>Jlu#|5f`^KVL;F+VIK-yC9E~tC5B5iVFVq*NK9r*bv?RyUL3VD-E3flBSO814m z>^y5`w%`v#6uW;ZCa7(!O1k>qkCXF-xS(=sz~{@B0*ia>7d8{;wRr&UV;YSa3`qFW z`IoGk+QzRyUTL{VEygfE=gB6yRGjV&_A_}ZrP{sO&Fip0DCU<3=$z^O_dZF$VXpJ4 zN;bru5&t9r@#yr;vUqj#S6xIZ`$$m_^FUDPO+|_F*Yp9DS3-pD)cw84qvXl>`aJ`} zy?^n3$#Hlx^CuFRD-*T0YKrQq<^aI8H$q!Fj+)q239IPXrc%51>E~u~CCWEUisfK$ zL&bp}-2`Er2On^HhQb2BRV()606Vn76DT@1Cfp|gzx^vgIr(VFQsg+ng3RFfn`u6o zA8i}nmxbR}*i1e;*5;8+?6u>O3*)s$Y+r+?!aMakCUTTRC$ z=PGpMXB*lDqzMwKP53K_1XO7LJP|)2U6Q{UWo77ze5iWe36+!m@1rid+OzXsD>INp)iMNk7sF-8Z(M|{S1dKYG9@XKq04;Y5&;6_ z72ZbH3aKth)A)i6eY0TMh;M(lU@H{A$}Yq<#)^u1-*iScl$ zAM^Oiv;{jTX z-U+BDDDsTXYtEkfO;_R)+Q54-n#6RhpI3GtQNwIJW!;WwBgz_k_ zNx*pQS;(^Z5qyvZ`?@evX#YYh{9w7X!71N;!Q<_0zd6Nb<`IQj^wn9z9S+Ne&%AwJ z+U&*-`caF%8MTs=B`~;^26r|~}vT?PngAWhUi24eqtHV+@j4j2R% zQ%J|z_&}zzv(Qn0dYfIctcqn14dFhk6m{V}I78z1M>X zG&xFJK=0z5a#*+rt}2^xO+_3=@%i^iG59AbkX48io#}l(M|y|d9UZ-=K&|vt%F(i( zQmWkC>sx!XI<3<0*ow_-Mi)6658_uxx#dy5qc_yuJ=q|uI&YF6=7&fqm*GwM!Tkbb z7kD06zn8EzUm2L2ewBkIb70#cTrh|r>E$h&cMndZ^p`91Vr7s~V|fS(+b`PEjePe! zUrpT(e&fD)6J;^!_$1+`uoLvRw5v8Kq(S5!G@e+NC*8qzy{==dX}A5E?OKaj$D zn!P7!EZFsY9DqXW%AT6P6H3YsM8ef0PdnsK@H`FC&>;Dc#oK4DtrdcC! zbX=lHH>~ z`UZa4jY5L+3NC|QZNdqO$>a}bp7B8>*j$vd#Ib61HIB|L;3M)7cc9_ERyW7FMz5zFah8?r)|!uH`3n2igh0q z^1muplb%f_P5!Jt_{+7e`hO`Vq`FF|Fx}I+=D|8<-_ia!#&lN%uKv6-udukx$p$Kn z_@{nedHLc!r8g4=c+|@n^eqT<&W`9`=RM-ItH?R%pd76I1|^~B@ULh7^JmXn(G6DM z9ZkiPO3l9eDKVaHm%O1C738t52vm{OwQ~kpZUA9wyJzpL?TWU!biUCvc>I`>cp9{z z{XblLf$mS%I!@vs)!d0&XWLyrZ26`wZFuD`{c9OluLM!4Xc?#43`gaI$M$c!$^rB- z>eQ4C0~wPDZ0+yNc1r>J!<8EQ6X7YY7f9C z1c&5gz3x0A0RMYBON05gY}j9N8=!vFa5??1ym zK;Ft|UIlGr#V#HkwgN!%V%PP5FIoVIExcG(l1&!7$HLZU^zS8&(YO(ZvBfU$Nt7>2 z;nx7r(d`CvzI%0}_+cD?!T*#b=pIBN%?V@NRI=L(ScW?ew~`s9Di$9*Vm7w+;Hr$G jI>W+1m;e8DTag4ReLx%OR_o1wQKF@$|ET=oGsOP^d8%xr literal 19952 zcmb4rby$?&)4r}OwS-FSN{T^9Euy4=f*>dzg5&~9hvd?@NQjh(bV*1^=h7@7prl9( zOG?AiUB74XQ{VW#*ZcnCbZ00V}Rek zA|?cW75L^2J$Ft4E%)$&x=X@JBFQU8jo8)hl|lm0jq_-`G4~r;@VB9pwVAdA42`$0 zJxRTq^Zw1puJ|iHBB0F{xz-T7o3U3O*5LZfA!AQ1Hy;n_ZZl> z8y{UQsG)ms)rnW~PSM30gmW5Nz9Gw-Y=%hB~P zl}Msfa?R&TND`MEOa(6A7}FeQdOe1?}Wubk+aG9hF_5dHRc< zn}seVn%497zJw3s;MsYWJ?;<2mivi8flM)kv~<9AE(VIr!hyqGbl$l1qXyXj zgR9%`&CCc?D#}I_gKz$tmO?y0$&_-p!}}s9#LyiVrNR=OGr7 zYI}dHvuP@XX>m@?RpBjv_3E+$}|7LohqPCn%1n=F#XS3P1s-JeFD!=0W1ycwK z#?rcf#fB!%fKK8}db0G)Ie?bVs|kEhz@ppm!nS2cZ*yDKV15;6>vHWbJ0DIB<{PRp5TtO$ua);RJu$ zo_Iq>De6WrJB-z^!>F_5k~{&ci7fuW7gM1K=e4{6%ul7!+m_5$crSuA-GVcV4l2`k33p(Tzv3G|J*b_&cHd`7_#S+1)4g$R*isFT!2;Pu|f3TtD}9m zzPxNMhDly5R8~YCXkBc&9hU{{jQmZVt5yv@evti@4SZ^PB5smgC-s+um1u2R5m5bc z@$|m);27-uw?&e)B*}u8?cDnvgPYYcfHT+4Z}fg88oyI`KDHraiAL*x3{(q#13Ew; zEHvGU;(%pCx1FfEWr)rj=HTBtu|C4czpwV{0WCsCUKQ|iAPMP}o|YISi&4b`nQ&UB zf}nqY!o2xjzB*?iF$xk__}iWTPC`F?<*fCB#vmKOqq!)%g}GDs9q zWj~)40u=;J*#hzr@Lv&TjWzep?w{FDNO{pO?7qG$kW?4-ea-L>Xc?b8fB?y=Enj=p zb_YlbGGCvY5um=mI?D&?OH;Dfv2TO6AM4;gLu_Nk!tgP<1ib6JVj>e-8!5k@z>ZeXVl|@YT(;g=SpU9+I`MS^rc*eM5f( z+@hjkCNuQp;|wMPHB#hX@B9pSjzNq?WPb%6N{E2_UCEC%F{HNKeKr3l@4FQAq`G)P zgQBW?Bi^*28Sm>)1D+@)ZjO}>d+j#!$g&WehpeaiPfHN9yfM6@fWK@!Y~aGDnDhP^ zATf6+iuDjZ7@Pn0-uDu?=|=FgTvq{~K+G4iY`nutZh<;%ww`bMswi=>Vn1}Qr&c8m zJZra2sQrL9V!6oVWp%r;#?JOchs;F~E0_P-%k2nahXD>RJE#F91uc9w{sGBD<0ESK zJhvKLm3MK8H7SGw)cAB4xU7pcf2_uh364nz;Dv>FjSsfJTVu?ErafwWuSPl@NI)h1 zlf`OtHGc6=9jryq1>MJ|K>$g`K#9rU+%de&6HKed`!&86075+%djC2YkXjd+8WqJQ z;|71Dv&-ZmSAigj4=m?RT5oJWmrG4$sp33Lb&FJRAC2oCFKpF~#{2%c=p>Oj?x9kO zSdELi|6J@07(u`FL6}iB8x}wqttIZkV}aq2vD;vDYY;lTBKdTJBh~2=m$Ms?%YkSf z{O;R#VgM7Kg-*G_=5U!R8tBrB@{aW9gwD#k?(vFNt2<}romw%ik zB^k;|jLhP{0 z8wBot_H1#-F-fqrmcQ*&VEvjOyrYFgeE7x18KLo%2~~lXm&hCMk~e}meg8yN@d04K zvMkE_@_uMq3w_Dg7Ztb&c(v}X^Ct~Yhl*IojU0BDt6326dF>^#jrJ$I4q1PkAf|_$ zA-TVEa?4qMRoxO&y-pkL{Gyk0A#z_fa&UV}7l9AbJ$6O=m~5p55o%rwp_A7a{}ozv z>W5rJ5OduDo_ima=fz)v5_@}$qbH9PoJ5!V($w>0VkLIgULDT%hgHV&c={@iTk`$a zSgIvo#WAAXEbX?wU5Np($9l@N(WVy-teS2i)fa&7zq51&{4MOyG`%Iclm}qR>Vbd(Di8n*A&AOJ8Jb**CXqf+~#`WRTI~$wi7f8lVP5P{VlS2m*n3`9FHGis5XD+h};^%KXlW#3%*T zR*wZ)RP;#zS`3%Jza{nbrH82#*`?c80N4Lr6@WTI&z9yQ!$x|l)V>cP?bn^-spNs; zvxm5&uGQFS3)}Hbrw@S?)hzfo0O)MG^?uG=m*d6TdS!b?>;;`bPfK{ zVIVdA$PNIA`~exIi+iM2Kyfbr#EkK~5{v>NNZ#LP{ji^S+D3Fx!++^ft*fc{-ne*Z zq*><&A{_QtzEJXr$+))I&82Y>Moq>?0vljX(s#2y+kgjt z1FPhK)uqp@j*o`3lh=mvd4I#`R!y1m=4HCGl%jItI24MLZmM7`pRDV|ZM>kYtgcT! zk-go#aC4+$F!?SP%4V;9V|$7SEjF89Iq|@IL_Y1`kiqZR+`rN0k=_q-zxDO?nmC!m5(ZSv(DU#y{*V+I-*V*Yc4EvG71YpEO z(XDiIn|fpCE%e~4e7YCnaODco`pt^NBlm%TIsgFA{rrs`&ip-!8oKb}%-!u$0e9CY z4b}_9;7gj9hSYq2)-?Zs3hViP-P)m}C^A@DKf42#qI$NMvU+=WJ@$##7d!~Q;Rbc+ zyHaH>5ZRG-^5ORBtOjLuj(CqPW9hl2FZiIUx;Ys+pYLVUF}$_-iLRBfhgUBGf`^sN zB0K`CV$!P!$4byy$z$kW7=sU!|61~p2Gt8StrQyXBI)Q?$Cr6TlSd2>RE#gt76BN^ z_v*y)rhajv=paz6nWc)06&R3cL z?Syk5T95Ar$(|wK&L-*G|D}dT;;_)pm!h~Sh`iiwtNJ_pA(l)IXx$CsXSZ9fbpn9! z3#0vpqRpvs#=b!pL6t>ej{EazlR@_*+YgbQO^7X_AF}8vqguwcI@w61%6GcdYFgYz zPBIjzMk0o*@Ndwem={hv;{Nqgt`XUAkT4RK$Ylq%^oek&Dr|_AYb9GPpKBq+aaAl%d^8 z;wgQHH6~eESm4wAvjO-0O-&<9F0bS6r)x%C80R1MmeIO(bI&RsEQsMU9d!9#iVv)v z(o>mj>u&98E?17;T^k!beXh@^oNz@kvguQ4RPA9~?Ng&`bBSxoB?1yNJYNQ~7;T5B ztr+||?OKJ4JuN3IqiYMhZ+fhiNoaqGKI9vcb?r!PH#Ym;v z8FPGs7a+i7+!td8l)VvY!*Q8pc61(@P z;Mr!}zSi_X~_@PG`iQTZ`FXQ@_c>a1)_}cAey`b1+JN zvgSagj#w_1q0$FJ;SrfqCjjdT-_2m8Fa1!NsxNvnA2JNIUoX)cq3ZChfgqiPMv5T!i2AcrBdRRZkra_z^S z^&*qz=1s_`!*zwaUt-a#{YyXh4hK)~)ZBNP@=_~L#JUeJiwhFhww|O9s^km>+Z!kq znXE^jKF_zD5Nkb|voK*+W~whY$kE!s@zxg(-mKXjI!$Od*7M7IV4!JXIj|-=T!BvF z$h**eyaCay_T8L4HM_e>fsy$tmM}MLFkC%I-WV{4eKvpf9bd7rJc zyaBFq&_~MGxKLbWyf6daTsaJ}b&*b{_YI;rl;NE#A6li_39+QMRIHo9ROX|28Mn&x zTbjHQE*uiq?YwzlPA5p&&(OffB^@Za8CtXb_4X%>Eub#|%2@|E#HOb#q#u;k;mmU%lx224D{GKH(D&qTc z`LJNY0I!0$JfUOpXVG8jDYgNhJ}h8UFj;Jg5wx0@WyGXiTB>iw>+==75WgK_Srl3* zo4nN?k&PL8+f|hL0JU&MC};PHcQN%yWGUvup@#ezh^qC+@gsEvY1vKFf>FR! zJ~Xg8WSeJdvAbn1q$7s|elhGpZm5EHj?hx+(k|oHcFla@-P*j=vfrj5Lu26MUB1R` zY5jC{N@V&7<&Eq0J-P`0TEa^YNDz-pyn;C_V;a{;JLITgYYnNpZ|huPmOB={_uW#q z@ol>0EBGRQ(QiO(`ncB^#Sy^d`tswZL##dgqdK}XU#OmWZnVf$1Ks4?@}xrtVJ&Vu zY&FY54x*4dG7^Al^>5nHHsNqrlE1gBvTv1%84QUH1(3XLk6_13^8T%B@St(Nw+B4pT*rOuB5S z)NG1zQ*Hd{3^R6uLf8)}?_DJ(7F|FTbhU}3E1%(2I4v|@VJu6z^X7fzw!6CU z`E)>F?Ex1?R4tF<{zY!#LZUn8}#3|M9qD&=W<5{YW8a|Dybj&w0 z9#!L{c$aTzA$;t@vhB&P(l-E8L@kIdsJN?`GttV{u3h@diLU^#L1&;HXej^{*rGnz zA950eZray9N&q=DjPLZOjOh0QaC+6u+cKAdS8lTp(oS+P(_x$MF@!zxBZ{m-d(B^= zj>(>VvdkDv1MA|sGXGRJ7cDgm&EDW4)s}M9lqhKB#_Q1K*IXy@0sX^#v<(%c`Kg_c%*8uZLll+sVg~Q10dd zSUX4!H!}6`%K$I@!Gl&!slzeHX|Iw6iyPc&~rJQK3rwU`KN2GJd+9 zPqvxaYSFk7H!lfu-|a=N49rz7n}WQ|S)gm67&E^;HNP{gE>_%Bf3f8yPQ41*;v*HyU17k<9|KO&Rfwx8hJ(11WE@zJL_=UnQ zyiF2YQRCwIgCQ3Oa!U5TJX-$zXmjlqz8=P0{HwM4mHu}}Qg-V~u$Sr0*eOUyCH+f* zk=Gn0Qc6F+tq9u2VFfsQPQn~Sm+7k*o!4J)?TJ&m6P`XL?N|oV3N8aP<?=XYR2| z^)aV-J(9Y#<57kk_rN9E1^UODy8DjoaAcn3tcaP=uzOea@_vc#g@|Iznl}LUR?9GV zm1$!v>OYJRg4DELr$9RRsA1}&54R8P6{*w^E)RI!ddUxYUXok6qBxe<_dVAh4rpyu z^%pEUP2bl*v>7ky62qOrv%Zg9v_Td4_IKagSI_>VYl!}8vc}@=LPYgF;3!!{@aTNo zMR@|5VIA=bdOve_?o0c^t6Ji&JF9md;Je9%;{nP2M-;P+_06u0nhRGKcY}rF_5IYR zhu(c2Rs}tL!8vF#7#UH6NpNVade&vFKL=W2dos3%lTHU`G)Fc1c}bFzZShtb6~vkm zdCP(c$*Bh>%vBLJ2h(lPV~FjjH>(^G781Ph4(wlcx1SG6T0o_NAQi!Mk+kGuj>N!( zlQ3P~OKE`1{`Xmmq?ZU-23_a7I_aZ?s(b~S7PYz=cMPd)6ma0z^0~za|fwJ0( z{L+z_f{;Dc^Ycq8)WF>9?t}1fI)7nVBr&!r}I?hD1xuYsAD;;p^0%5@QI;LkI#hM=l{>( zkEzQ=Vii##9c8qN=t{xB+h?D>dpO-iyow;mP5}XN?U>?Gm@QN2vjem*NX=Pxi$VsR zLEN3Le(YwlL^lxV3I*q}ROKW;n<1G0Y&CPBsW1iVJprzUtsQ#!K11S?+HGM{`A6tb ztV=u>G^W-advy;q&1QM}bB@Yb7a=Z<>IqyBB7XcTYklbZEgo%`rW1%RJ(g5nYua25 zvAlOj?PFL1Xftuz4NF|)sW!$)8k~iVdR!Aq&l7$7jwI&4&5km?5v+cxx8RHANch~n zR~JOA6fXJc=rMZ``hA1OT=vZJZm7of65OS14QASnqLdgRmG93ymP9oy4O zdQejpEvW1o;=cq+GyDwlJ-;L>oOgeplAYR(NGdZK40JI|`PtzL^>EjQamPyOmi3wO zgK$%%*Vk^Z+~p3619 z0mij0Tmv-@-s|D9xcXDML(v$v(af%afTOl^_*SPoQ5xvFK`My9Z=AXW3Fl3Go0hCF zx|yt0;jO<#UpFpy^;Ue{^_r;tuXpmBMH;Vp>ZA?=@5G^tL}F>?2DI9D>meGc=6^ID z9#M^{$Z;zevSgxDK^a={m7{bKtfnYKGM&;<4UZuMcQJH2W@~=wmAO}PA+IGy2pThW z&f6*xa$dgmGv6*KkbE{9P1n~Z>1t8Cmm~;-+flz>fToXprxzcYE~^JnH8ti%VDEk z)ru@RL#3534XPc}s`sb7JbSJbUHu>&pS1ALSVvb!i;LqGOSal*2sm7N_lzf{nHIKz z4PuAL7aKgkObwgMu+rpwucM04riNLuMHFHR!K9Wbxu=M_rc`bEy}Ib1b{OWt-B|6e z)2%J}SkEc)f_VqjEJ$s!Hw!al=)^M?6Kaks+Qvt_BjfV_9K!?-GNbP~_c$K*9!Pp} zv{YMkBjuKxNmhG@0RoT{hHVxcmMs_AQ4 znARa79qhG8+-{-Y4J(*Kfc>pI1A);h0YbbwF8L#fs+)cuRswQJun8~v_}|As(aHPE zOuKQt&bR~HGU5!G=ggjFCDnVLOZy4G6P!gFOheHWD!nvp7!ccR9JbRVp~rZlLweI@utcFoAp_JjG!=UH z9HSxXfw}Hlw34|?QiW2}>~Q7KWatG==Akg`wU#{0-ZqzS8F$S0s}HFl4MC|ve@}Pe zhc`zlL`$j|S*_R+V?Jy}GI6$UpI?q^t$(bZETOF87hi@1hv=}6H;gV(NLc&3&sZYu z)XMWD?iy;}m~9~7dt84qmO1+3^s99VvpDWh%U;>9^lA)!+0PPdGj5hz+>dV>2$$Vr z(%7Y+#B8pV$+aE!P0tHKYK^@=UagL1n2xxtGrw&h?Rd|*W3gR#!q&e3Uc8Ks)0}&$ z)~H)LMgsV!T9&P08hZ(l(oX5Xj3~={F?L+=Ol*bil0$&EyRbB_&wjM!W9Cd$?PQDQ z&!yoq%y;d)NhoXt?MXhd_wYjq$*(sbcq`LvJQWH?B;z1tk6#yYz`fmb#~Qw4B$)69 z!3B!{lk9L!AKet{!jEohG`LSI5QVujEhypLcD#to98I`@e5qER&7=quP(A(nI$rN| zRiJuK+_qZi>i#xXscNA+VJc&#@svLzGrjU?R>AKutUzM<>6;a4mmM%QeqY*7%UBo7AwuPnflk+Sye$Y1E{y zi@uBw!fh(fugqDSjF?3#uS^v$C1TsY)`AhkLsp3h&d(BetQ{RHYVJ=Qn$M!pM|g>Z|8m( zNXBM>oSVk|pd4Qv7~iFibvW!EX=Zf((eabHn>sFjWBz(PHqNrbdgs$tW+(B*peG$9 zh}ymI>?HCxu6hOa&u`PjR6o7eTIht43k3)Wu+NyGm?U2ck2x(`*q3dl-3YJeB07E< zrP_yUJSHnIflyqI)*+bFD%GJs-pkr;RMBVLEZfm)fVZRu!mW zxz%eLf`hX$xU$fZv^;?l6mDl$!N*wbcwljSfaPH`Pi**MJ zAvnH66#9GM_loVZME9m@q~*yU&oNV!H|wj4!Cxmh>Y?L+L)&L%9^_$2YZvll<_sGv~9&gH`F8L2`WX&5C+b;YJ5xQ zkPeT7W!H?g5sh)V+(P0DF+kKb$V9^LOz`>mO-T1N1N@&pG2cL1HOke!U->rZxu?vl zk@&LNQFJ*@$=dP20p7L(I~yP)`*bp^B}DBr7as-nlRUU4H4`sDgBvmM{Ho`P@^Yne zDX;af48*O!&$bzhM>=&Uu8d1R^CltT-iSB2w{SAKQvao=yUs}VMXz0)V}+l^26aqz zlxU{yfQ*15<5YL!9lk1{61pQW3!be=?n*gz&drSbp@fQ!g~+o3e!|Ax>U0UZNOhpf zn-MI9N|74}`VY>xpiJv|!g&gAVxnDnry+u;`|_Od3+5@rpM|-PV>TWDwN4WUyqxf> zPVy)AOD*Xbj}TDPd!jputuWdcFP%iE24H?Z`0<}an6BEzklxYrtqRxIziUYKPOlW^ z?A3eO8@2+SEXXy5dIr~{YG;R%Mr;16YuQi*S7vk*&;Ivgn+wT_?1MRr{b9&n35mE7 z6SfXVQQr|0H!_YFZrB$~*bsw-)}Ge7R5@#}YM+)bFN1=%T7uZ>Fk3u82WGuh&=%vI zqP0O8UHfq`tj`1L@vL^mgnQ=|em$iy?+V9$vu;63YTQpH+n4Bkm+wg|^m8=Z+Ow~7PG&mL+v2S&JC8=* zyY?k-l!!7roR#R3{ebUP8&p`2-24-VScG#L2 z(6k2WP>R0o%t~trflppb?>>G&9n+{yFLlDy@hEKnyt|!8>Vz;$sz-^EE^2?^N0QNm zd~QhgFe0bo&Cs95o6spJmUdy?E zt3y~%D)^ChhYZCR@~@H67atr=Th55Ww)Y5G+|Gx_?Oo}PGphHi->nmUpOdLLcrS)| zbSJC&KyAsDX!FDB)G%G>$-YX>Yhf?KRYb-+;Ml20<4+}i)$IkY5eYQaHEA+&UUpz# zGlJJHK&W&OTez7bHi3faEz@@bc0CfhJ4av}>LUqKvL9awXk&zfv7ypKAc2&A?H1^A zY=!T})a@&z@(nHT)41Tw38!iOT?1UXWqg5(dz@Y!)s6V+%|G6Br8)g2QSv?PilDdY;W_;;DfieNgggkZ-(kDiX}h;Uh{V#+PifN;cj%xexEpsN5K(JiDst3OS*()P3~eC%jHkQ;6q0HFMt8~Ib%_Ir-%^13KK z`UQ4)>#0ll$fyW2eYV1zJ*T6guaMv!POolKGN?Yo+(p{&#(hrDuR%KI47NL^kCe9d zv0Vyuhw{Wq5um1Z3XF)T*NAJdA!_oP%vL&3o~GegiP zs>HRC3mr6a8XE7h&Qyo6-^9F$T!|v#g3l$q90YYuHsaWn8NLP_=3v>ctb)|ULJtf@ zNrSy^xc5dZ6^8%xm2G$$Is@v}LdciPpeniRlJNbHQfSN*%6jX8hzs!ppXN-cWM`!N z-~pk!h%dvNgK7zUGAYIn-=7cp2W{3kG7~ezU7YyBa@2Li7$;qjB_40ij86DCjsaNM zM-l+@@7D_a_|8x7<2foE_*68Pp3tWv*<+P&cl`9Z`&&PQM<0xDwmFR~SLZM}caOMR z9EJb791{KEglOFJOYN^0y+-<}NZvs;#8#xW@d_y&mEUQXBne!*b|y8D6K^1yPz2uMTcmdPoaf-*2)h8|jI=lYYxOskOr_;j;x1J}p#FYF$qO|KykV=(LPG*oeQ=~X9O23Xs zj46a8t3vmbhLkK@KhUJVaUn>vcIbSCS2-=nADP`UTQq0jNkLStb z<*e8~@T`_igs^vft}%RSaDAFe4?!wWKO02@B8&f82}@R)IniuN+6B%2X=u-KY+&k3HRViAx%5;1hzfHMSfcc z6;AT?GsY}puxODkDKiGm@nxH;tcW6S;NZY-+5o7P{E)oygirlSddy2p-hoO+tyzGM zYfuP01uV10bQlr&l`rJAVTgs*b8yCJ80SVhFI+n!AD9;O0Mmk!Pd~R5*jKJhgEp^_ zk~RKhJ%~E*otpu=F77>)$H_s~im=vqwSg7nrfmOm)g$D93+|M^9hjo6GbZO*p4LM& z+UXrId^A=^gr;EbH+Wm5;!tc4_K3~(@pPScZgLM$!@_m1FB!f8Z9aJdPsLS`{V8Ro-4)oA_4C=#CUm~Vv8$|WQptxfB9)(GsiuvY_Nv0rH2VS8Nwfgk*geV1_ukm6JE z=T5KX62eTwgb%yKwqd|>I!5qB%eWKpbvE;N0;&?9k%jk9GI&FyDWdah+Z~yP*c~FM;-UPu`Sk22FWnvQigLS-Xd0CN zbV_*&Kr;-T9wgW%LhR`4>yvG+BiFzRUQfy68lLO7;4^fNM_x2BNG4D3{jXYdPpDWK z)V0pI#E4uxO*UPh;R|>1Yo#&p90~R*f@`xgBG>&Zy>n5wYMbuYWCyKestq^CmCsZ5 z?D2(l1T--ZPH7(R&1;%a<>-!nHRT>G2~3rK<*fG@#lf+wVW$$#F}Efy`{6R8uWeSV z-7?l)PizcqvWDbMJ4lPd#w>$n<^`_2Zbgi&Ex~DHfRRqV@BzqS<=~V9N~alWG17 z%*w8V25l-m8WTrn4%Iw%cvu$ZDZ%A2;>2r!qk}1+EU}%*)e1$JU{#){{T4Y zYuXqlQu$W8mWR}^P=(Do)udh+G{)z&&zFQ!AAjDzX!XSCuRvo{96}wVdD?gnPyH7< zX|Rpy5_tVZEi@ZL%}w_3Mep@UCbu?6&X=zzAi& zUn3Xo*#m{OUl`2B6t3%CJe(E|(>{L8XWF~|MDKWb9Y7?>j=O|{6D}#sWR9d9o?Bc< z6jOQ1l?k`Os%cMh2|EG&yi~hAD0SY!n#`#q$@*8nHIz1qL1xdUxYU34U_ zQM?S!OZU1g{ia9T86LTIM_fhdYJ`is&%3~Vz-phN$ zeVtxl`YGbv9LJuL!e0`O-|C9e*Gj{&NWMA@JM_H+WhMr;oE>`K)h56fG+lD;+i<|H zu!`>^+Q<;i_WIXyq`})n>Ij>3%>1*W6M=qh=EDuEgh!r|65JUEaiujh2P36i@SBUk z@PV`4n-H^0!uTjy*ERop#nbA>xOE;l+Zdx_n~&lrPQBKlGP;uIokVnArWpW5$BVJH z5&6>vdZbnK2S*BKjk@$C^q9opxs8a9-J3Jw688phdDsHD{wPFmsdv}L7`KU(CwzU9dYEfV)-uY87ff!F+UjSvqjhS zP{+`MWeyjGG9GrrXkqo`(iE5eO|N9*w2qUG@8;|hJF0JMI_EBr1Q<EKzaO`GJqYkjj$S`xgmy!`|GeWI{94zoHD|6B0rm+`qUm=@{H+}eka3(bRapGZxIxcJE;+@f^roF%Me{W6ETRR^1MUV)+oXuNui1h#mPBEl6G7sDj)2Y| z!10_0U-qp;^t0RRCU&U?9#!BzDg1~BxyRH3VZgb&#WS`-^nhVi zYZivVH92qgbu%EwWBpqk=(KvoT^x}aue84#&*VI)U)UhFb1_*9+%~29a^M#HfTQ@b zL?d|RjrgkT-I}Vb1GW$Y?^%9;ux0(^kzYvD!C{hp^zr5~E?<D-Zb;~N+XiTiWx>x^X#k&psBK^i7VyK?!vbjM zkWj#@>ANAI2x-@Z~*wntG#3k$7Y%Q)_&Xn|7dH7^Z| z^zM9$^%)PJb9e`G061=xvrzQfHC%g<-zxg+Yk znw6V!Gd-X?d4a;EpU0-vT+JgH9F|Mk;Y1C~7SMY3Oa}fYVfT6-nwY-Gsf=}QKR?pFK)QOP zCvA0p#m*+5s`(sh@O6mvL064iGB_Us?W*={F;=qH#-P9Hnv&%vR$-l=#Cy5r{^G|^ zT;>GYQ9OOzACArP#7R3qf&|e_brw&HVh7V-mN1x+hYcpBnl7vxh`zj8{+cFW^d1t? zd*2qqt1V(9sic+m0{g9U-=^h?u^LgBuySq&W~=H_;UbMeQma>x7VCW$wqldh@;qy3 z?Ud-|;VAL?T;xkya7Im>&VQ)0T28yAkdCc&#)9_SeH@zx$dWG=e$>C)Yeh^&YJjx=4P94zWk!O zdb7`>3tOgD*rdw585#J4;2;V2fXgPGAU*!`|dm0Ar(AX+jiAznX%(r9p=OI zl-{HK>mt>R&ZDU~bkk%1Hs*?54&(xx_Z;q^XIdZwAmr$d0;OEWh~cJ^c^xC`GH( zR7#%F?>)Chk~_|JM+q2Ani{6J-5#WdSB?LNR@Uht=v#s7NIuXg846DlS=oOLuo4oH zc{c8m(+8~>|0>1|37_m_ST8qxz3n>EE}(YowE2081BYBLR=`sGP~~7-I7k`ynym;I zI>KzHsqb9xKH=qAE=A<1Ay6x#@9OpL7W1dGFB_QPl{s7@Q|SI}8cn>gQkC~d4PFkd zRK*i|CpDRRWcrgDb_o!gcqsDB(!^Cblw=vI}d%1uO6kKSH%P8pgD#+q2$?d+)g;r z)AxVLQcUXrOg9rW(eNMI$1onB)V?d-!!3;awB94R=?Rwaz5`PSpqwwU3Gj>@G0e?g zw_kCYe8JiJSZw0W0U{#4Oe#W{vaBrb+}ilRG{%E-l%o@=IYJB^d0o0!tRnvttyC+p1+ z6zbQgOUS}k$*U`)PhIEgHH|C%*!^t+^p1pW0*+%w3=J7C4J!4uhh+nNUPn!ju%DpEU1Dn( z*4wkU4al;sW`3@O+4Yew7~hGWuRnJ9OB#06KUrUH8J;gY`JT-<-4(A;VoY0moR8)h-w2(n zz$O)uuWA#HYHH>p(b$7`E7xUmtzL_@Oq%HiIr&N-#BEjoCCxGh`*Vha&y>r6{u_R# zHH}DZ4X5ju4nLMV{Q%s3Q>pESlzj|lX<*T=Ve!y1s z>4(1@n>t2(%y2ohEax&%g#z;RR}h;twj8!#x2fiW_~K@WuxDCN1?>`X(3W*vo{3%D!ft!22!MQHEx-a_vjsW0Q4cK-sb9Q z#oTYL^THjI@SVvt#b%wx9HGX(H%F}isDd^>I8SxLbxdQ#|CFu*zn0>A4TRp#3 z;>z~{Gykp2tqJlOxCn@lbL~Nn8s!yU@u4nx&H!hXZpWD6F^d?lLsQSwrQB1kpZlv> z`0uI=ylPiWlzwz%-=!8mx>9w^uRSFg7`|=({;_RSsgRF_0EK)xNPQnpGj*VHEDJmt zIcpRA5K?yFvR$-{T2T6JNgvpzxDPJTDKKs~4 zIv}%@aZapDPIfW#6ByFH3D*r^6q$v*CE{c?ITEW<>qH<@#A`CbK*YD4MnUabRD> zO}Wkhjq03adIy0-xzBc1vi(*Z=TnO#Ey)dBJ!B*QY-BPT<*5Sc8@FisRQNnFx!092 z>;90mKYln5XwUfn*m1`QMP+6(=YXSL!aZHM@q4%88-dWud_da&YFf#!DXK3{(b*Yu_Cwma}v(!MFP&2aa})0 zZ@8_@{}>jaD%;&YnpLJ%ykqRXU4<7pKB^$NTVgime z>g_>y1nw-qZh>Lo+N)9D{`SAy$pJD^*lC9j?^(&>>uaB0`g-Y=)3LU!)?Iv`4{^h` zu0R&`Sv}f%3*^!p{e>E>U-q2ojXG@EIc@jjzW#Tn?4W}IgxRJqf4DK@-Y!Z0{1Ppr z-P!tAzOBpNapEX&d*!YJU0(Py_BNl@#fzTLyLRqp@pRx;?2k88Gk46Xd$9|c4DV*? zO}gy)*!667>BQSgtrZ`2f4i-HIL9Ho^Wy4w&1X4R3-=t`s2I9=DNDzxuyv+2y!{hp z%(hiU6<@Ej`0sccWZI9@mpB3@-n4lTRup(=u1U&ly+Thmf*w5~$) zevTw)O1SW^OYR!y_K4LXpzW={W`_DTtUD!kJ^ylv?k(B1 zbGOf)o!<>C6;85TUv_cx1K_DBVr#F>EL)kpbXJpIT~Y>kmlU+*=5~r%49rfJb8qdr zHUYd#6}n72)-id}zOa9p8-X6Q+~|E}+J*-kNyMaYZ@2(wNw3j?j&ATFX&U4ES)n`%NpWg2Td5&xPI^A@}?Pu8J+LQF?)jN{Y-@yj#FG5eSLO$=erg6>uyJYL+-=db@;gEP)2*tLPuloC z5ZYF1@pJ{yb8KC#uKmCvg3T{KGQHNH_VCcorBYqqGo4Fin0VrEU&{(#@l0sJ?q9a6 z<}k>D!uwjU&9SRLp8gDrP@7!2>tJfm>*7m$N{hSB=Dl;sP6&J0W$EglJ?*jaY{8fe z=_ykuXypfYyjIV`$cARo^UsGE)Slb9b=~r-<_1e6=GH&406J}M=0>15ff4Ww<2*E& dz@h)_T0!9=sXe=915a{e@O1TaS?83{1OS89Y?lB4 diff --git a/documents/images/Zenith.NET-Logo.svg b/documents/images/Zenith.NET-Logo.svg index 71a8ceba..c62e3d0f 100644 --- a/documents/images/Zenith.NET-Logo.svg +++ b/documents/images/Zenith.NET-Logo.svg @@ -1,37 +1,11 @@ - - Zenith.NET - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + Zenith.NET + A white Z on a solid graphite tile with a fine inner edge, paired with an outlined Zenith.NET wordmark. + + + diff --git a/documents/images/Zenith.NET.png b/documents/images/Zenith.NET.png index 68168576144b7861157863280435f046c8298294..8b8e72ebb9e7961c2177251051b08ae12395e779 100644 GIT binary patch delta 3031 zcmV;|3n=u!KHV3PB!3BTNLh0L02UaJ z;Nalk;Na+7IGw@Uv!uWP!K=LC@hU~4FH|YWp=wDE)k$(T;ntpo>fj^z3O*Bjp*irO z+a12m6hZg<{dc*fz!)0zGQp>`IJ3MYrB4=lq(>Tg@ZnVQ>xX)fUp?5J+;@Kxw{{G^ zfsY<~Bvthpe18WYQZlrN-q23?)}<(S8ZPiIuW}y^`a9Gvr)7xb;qGbVmk%WKpmvhM zm+)zNrbOt6)g<_WOWkhy7l!!aJwBztBL!Ph(_ECj{Oe|I@G*Q1pHo|++lt^3gTq8$ z_L<)4ZXS4@hydTy^FobF2t1});8Rn>w@9**>k|5@dw&%VhQ5XvAQo;hxVo#y^L?hl z&&uleBhjbq#XipubH+M6A|~{FP%cT~yO{((-P7-0y4)Pb{==PaOharWU+9oi6z}QW z{oWJ$A^zhYy)w9?4Q@SqXVR4*^sjVL{BfrQKRMZdE0%r!<(q3Iz;=N1TH;^7H@F=8 z3wNx!On=Q8$Vz^~S3R6C`GL=z2g7e~2mYL!PV(TM&#!vsz9J$|kSYjw#Q*iv3?C8= z+>z$C-hDlUrs(tH&g~=B$TNJ_$QV)rGz&t%pT|r9!5dtLN)&gXb#4W2Zy-PBy&n}P z{`FgI6`(PVsc_^Gm9hNVXU%J&+p9d^@$&Ce%70LM=1z;>++u))!bAUOer2Fxej8#+ zMJ1(CgP)crcY%_Ji#g)A?x`8%;>C;PM$CA1mSIFCP!>U|7rELe1;UUZ@qor>U6Xo| z9i?TYJzTwdm5d%Y!4SVQ!{s9$j~t3}`d8lIr~mlAswaOpk{msHj6}nwOP7co2T60L2g^^590cq@L*{XV}wZ{(?MmWv5r7zi08c$LlGN8X5WC{QR|kn6=Pg4J;DrfOEWg*sf@w2evwt4} zATqhs*hn}CIe-3wnnJeS3NZZX5#;ja%bWoe`31}Ec?LiVm6L#w=H_N3XY5A+*zZS; zQypM;Y}vZao&f+m`^avEwJ%`f3Q>Kp&@IUjo3! zzce`^5+I$tZ~p=EVaZ42-Ic4=s(;?K3g6UMW|Ao{&q&CSvPMCN1)wI%aLe{40PLlS zQ{!^-p3nA@nSY$E3NBa{vXWE!lF9>LF$q3yLytcGl)blr>uuuXKXgcfFTSkMET4|* z-OjSz%$9y=9&CFHh-8zePFJ1N9yWcrMYB9QH1!aKu)^!J-?V2UC>EPEWq;atR)Vu< z&k-$U>+dXI$t?IQ|GLJ$)xcN{DrJa8u34`%?HX2bh-8J5E!%XNu4Xy{=w-Myuma96 zdI>~10b;OcM~r2blQ{OxaZOh-PJlQK*RiH1Hbts)=gwW7KJjAu%-0R`w{im9U}%M_sMyae z_zQFM4fXeO0$gYJckN03x&2dS!7nP_WVjJ~oB-E#_O9Ph#4Pxz9T=(4k`v$tTUxM! zS?~`X{#tXjFDF18_NPD3V;20=r>oUL3`YIiZBGC+r9`SSCJJ;q1%I;#8~X3JH36P^ zZZtFPA=J%JJo%jAePCMx3>^HpI;w@0sAIyUmrdaZTM__ru?rV2GTZlYrZ9^yY)62; znO>&TMpmy`XDWZ#iU4>%m<9jie{3gukJRA=h+y54daH_IRzUjLj1yIDK>(z9 z@pZDo@#Fti=kS}+H-DBV08+eb*A+4gJ`R&+_LJoausDAiv*1H1H2BdcOzj^_695`} z!f?hPnpn;LfmoIR<6fA=tZxrM`qW{e9bKpfV8U=C?$U^i}V z>qmblR(d|iQUst6AdoX>&oT@C-p{{O^9fc;j#-8Pc-QE}iGP#Kf`9bbH^hqXC0l|3 zEPM5@HK1Z@xfKgzrY8WNXTj`#R=^NTl#Z=h7B@8kSoi9qfdhSkRu;vWmHV_)4lN2!QtjYtFDs@z&MV zs|2%SE4<+efb?rePq8N2z=7(aT?b(pngDp(6tjL=4rG3jj-s{m7#zbA0PhEG|D=@Z zbq_G7-Y9lkktzB&Xd-Y4&h|F&6ofvN5U zK$eeXihmct#LrJYEltSEc9p9Qpr{wr)ST(G)vB;)qpl>-odA$q*&TYW1iBLd%P0pS z@2~$rmm!k669Bb${$_C7bP=sdV2DFt`JTNz`v1k6wd*w{fguQhs}n~XR;^yAnIx?v z0<>z?%*pZpShnIlO-O(kMT4vI2xE@l2`~1i+{j4nlU9f2LUzDq>3?t=bon05o@A zgcmfl>hxjxOpDQhnZ<9-U!-Y$0E#Ob;|-Cw0AFZMN}nvve$ccTuh}yANHGr>l%shP z2!FBlh=ExV36LcP252dj#%ja5E?^`;?}#d>UeCzj9RrU?4n-t@+a11*E)gwSwn?#k zxkLYDzEz!LfWJ|XFaE|Y7qLZ*9nm0qLp!w`fr?=dq3}>knbLo-`n73wppL~5Q^Bk3 zaC8Kh6c_`c0~b(Q%hEF?y8nkpbw~ie-+zCX;8U8cG#Sh8hFFR|r7a@)7*ZOy5r&EC5zvJHY80wSZgYOZ8gs*xx3zwqYiK_-u zjW`={B4`tM_?r6siXbZsozCFx4!waqv)dcUM->r!5o*tNnZ2u(m;*kAZ&B4lVF&dZ zhtYr)!R=L^r~L&xpgw^p0y;E^5s^}c0FoabqaWtrBlrqFgYQ%s7xg8?98jp|-*j46 z`&B{uflCPXry|7JRBT#E_2~PdNvEADwP;V`)~?mUN04sAXAp2g!v|kFI5;>sI5;{N Z{{il^VyCP{cgUk49nVoS5S&)Pu42pK@k09Djx1@Pfkt7 z(N>hBCOI1R_20Vsimro$346Rdg|e!6LU|XhrODgAoHk{w*l!L~Lq!@)&tpHtJ^bW? z`>FHbs<^6Z|7lZ|a9reg$orU&HCk;pOUVc&wSkdsXYj6Yo6fB5wwxK97dCJG{rr9{+-1HIcz?XqeISr#QRp>8eLrljlXknI(Y z4r+1&TKVih*2M|iG+GIfZ#~+_uvEY(^C;HDv%Lr-S}l=Xv4UFd-zPT%j7!;`){m%5Yn z#!^oPWiQ9j0~N>peD|y7evZ%}xaMvC$<8iP_v_-0@!JT*8N?PXus(&gk`-1(iqKA- zKB&*9 z+9E-~K@^HgM}J;LAu~c2MVNx3M-#{x`#ZT8eUZ9EWDW%?MTg7sfRw7K4Mb6tW_({x zJWKuXpuRw1ee7hw4=P&~C)rtlhm|f|j#h$j_L&tU2n>_KPFEJBLD73ZjSLdjG)xM5 z?DDo0XWTH&a8O%_2LnL=^tFCsVnm46@wSd<13yMa|9SS9DCP?y03gmu_%a*GBOVwse|1E~~F#EW^1;ybEEtL%z#J@Aw%JH2vEiZcm^x zDT>mieeOp#7v?or;?6xjpg+Jq>N}eJ6kF^g{cq?!W9SDoi=q%szp2DF7Y<-LUm5&ct;{2-z zC76&N-Oc}e9}tTQ~*X+E$_a;7zX?KLMgYmDb_>-@JOuz6;R_CSwf zppZ^*3k>WYnrLa2gJ?#%cm_KtBFkzCbvZMY`P|!NvBar<_@ufdZE?1KC+~toCJVEl zZ5>}GHiia*xz{I!>|{XU(&*uTH;Q0&72Nm%3S(o!Fn(Af;tRPScF&BC?Smc=LwGbm z)}+K7iDZ@LV&m22E6193)u-0eUtTgshgF?q3N;Mk#{Uz6s7GOwrTNi_yowS|QJPI@ zA|GuKIFI6(Wjx`B;k9S#Z?m?h+^=~yKZ#Kp``YP*CzO)qdtdq%5Oac)RE?;kL{sT1 zU|f4>2x&1~mPM7aq+sO!p0#AFc)qwh%AG0cj4}Nn^)ZT~M6QNTZ zq(KX;FWreyseP)bi%nh*s|-b6elikvB@$|e->*T#X&@15Vsa^ZurIbd8$jk>@IuvJ zb#X&*YjIQnCUFjkGXgPGM^Vfzf++eW;dK4s!Lj6S_IS|@Z2Z{pYQfV|Q4c4!%F5%z z(_E5jTk^nRtapgIrlH9e-=zbPCT6rH&G=a^XbO-U{WZB%K2cYB>Np=Rw{(m;P9ej; z5b@Fw)kq??TaOl+ZSEFGw1j6%TxIrfeGK8y(s@IK6sQUUe+g2+cG*G&;D8jW=tvvrreI5=?j0Kvo#)(+(4LhdF7M8c&vY2Dw``m z?%CM!d`|v!4&)iq>KrmD7Sk0&_;kEj2yBL(!7Sbi@jUypW#Bt} z)60}S|2%Ab(&*29Jaa&y1#O00)Ytg8^0ZczUyFQad0d9M2-)R;%{%S_&*h$xeaS^SL2OR z8(a9r!h9Q8$~e&BEyn_Y_r@R*uY_|LpwcoK3IaPYAa=rTb6nJu@i2Vgqutcgx7Vj_ ztae3_fl!Y3kG)h7268HQe{jB$UeYZm)!^IF#oF=cM&6$(rk4&?=|>WM21}44ZC@58 zux({g^_W1;x=!K70!Ez?X7H_e;Q17O%zZ3PMfK$r;k3+d1N)xVcD0p06P15(aw7a6 z^7B)7RbXFjJNSG~#=5pLzm!E`Ph0^NT4mrV99!V`13T?c=>;x2oak1TBJ+u(rW>D9 zmgD^gj+=w})uF3E?hd6Lr^Gsm`K4&6K3{A;wc*i6QZnGzbem0@q2Ff51Z_SdP&U`; z0Nbem$EtV%$L@;CHw9Y>(30Rrj;Di8>V%OC?(k+S4G*?Yv|i?heg3Hc8|w;4RNDEnR5D?Zyam1Mpdq%n zaS;{lE`B(g{M^mVDJelmaYK0PRXgEJ(J%$MGxk}gY21>aFj^X`nV4K^&n@wTGeW-n9YV)9U7;pTUDRh0oy%P}x+U)FOj9UA z)_z>Y_nAHWLrQ3xdqUC`B~yJ;@enuM#}eKi%jZ7Y^u%Ls9HH&6BjVwtByBD$NxHi@ zi;&PgEpCT;^$Gh^@wBI!lpd_xz_0DoTp!G6mA#cPXp(lSnvl{o!aP*s9paiQ)KX>a zy}F1nF{QP;6e`6(dlKpKxb%vaMyfbyL0N-20`!P0{YuO1(ra^q6UJDb`Ts%Dmm?gX zd2VV~!lATx8f}4D>ZViVi1}rl_)ZfU1LXe#FF*Yqo9ptFX)Wj*>r%x;@QYBRMFN^k zzcDO+OoqRHn0)%lJ=?L(!YN7DmZ4*7sRmp0UIW`f!ItjEJ3DTjZ%_j4xxaHpp_7%KiKml^hfyRgbbT+m4O+&ST3n&+2fij+~I2QaF!1}Eb&Uv+EcDZ~SC;_QC zZrj0dhVf0={6~<=h+P_dK!u{^+~-jqAI&=vV-T|ZcIFTTJwSnf_ z>k`vWO0nn*29 z8KIqKe$)p1ea_wMH{;0ry}ITK<{v}E1WDcm+U-E^GSbH+EnoIBPdFg^F(c>@gz zGi8{*X~~>GpvNoyIu2!lj9OC1skap8N3)DN!1)a>x0P|q9FP^H%%rZ*;8%9}1Levsveto_s9u6MA~H-c7<=780idTE0Kwz*y2VFd`0h|Svx`7NIa6reQ^bF58Y>L zYIh}FaT!%;gqf|$>d>O?$>2T{-r<)o@&D+h((~M{Q#ox}+gI^4Kipy9(ZxP~Ic~&q zRdlBP*dhLU0yfVY?&3`^`EBIyAv7wv*nJKPODDL#?LQXX(~w&-e&e&5;D6E<8OY`Z z`v_Tn*+5-)`^mJUAcy^No@q)`uPH%f51WmyB=>4K>)KGvL;F0aWXvYB*OywR{Fkou zf_5(}tbbP?=udDmb~rw*B5oo<=1DZB%_u{V&_U&zMcd<1_c{7Q3@kRc@5vc?Ahb z~tU|*XR;u$;JvBK(ajCDESs`MJV+-&h*gnLc{}Gh| zS+zAqAH=)n{)R<_GH`#^u(bjCWirFH2>nzi@gihg=a+uX$w#*xfi+FWqVgOG4vsnIvze6QE{dAI*@v`q{Oc}3;uroHzQ11QM7ER(& z8-v20mAUIKy z`^atJla)Eb@sjp?sQ+JxqTE|13{xv!=ejefM3KrhF?S^FQe0KCzdU)`TM4vr{ZXoA zO6~CI&CLt%M;ZJ$Pk#^NUhJ0PxV`t>CM}>BJ3M1*!@|`gPoT_b?us6^l4gV;#{y zm1}xTJVV;at==iC13YJJjZ%ZV-7(LUY;_64A(=hckOIaYX5nBk$S$H98#-XlG#ry4 z8MSdq7jZVpZIW*l@7ij{YW1$n>T3B?vg>3Af8N-ZC=(8`b}zLKyB%$=nZ1saeEiND z@#rVz!N0P>dyp&+N4n2@NoCh(){wNdBcI=yUV2%^a1YG%OZ4#!hwGG!E(GJU{K%n9 z!z$EQ>s&eb3aPE>{~5f1HmdUxn}G zy*pur0)4b%i0zl~%u45AoXoD!p+Fzb0#5ZJJWLG~NfWXfVUPoDsP1zC(Qwj)=N=R+ zO_3@Xxn~&cSo|HH;OWhh;ihsJ4w^~PSJns0uTIj+QthUnf}B==sFnpTs7M=8A(;EJ z)jMQ@U@!WuGN5X+$03@myKbKja@c<_q)gd`$LLHS!SA)iJidoa%gfrW6JuK%hWFc! z>s;KnQq^NxyWs6_6GdXjhJZz$d^eIyd7SeEEHUdLkdU#Y04)25X2$Lv(VMdjJgS?u z!T?4@%F8EOWvNAeL!iZCl{Ol##GlDj??fkuf%eM(ipi?WD%`{DvLd6o5#V}dM#H-M zw6z??l7J~3S(lf#IW66*R;5nX5y2rIIBqmTyGuJHP$|;Z0Sk;HSHp@neVdcT&Vo{y z2YAf9HnOH72htUh!eIiXvU1a)r0HL()4wWR#gW<0z%U^jNqT{DsX?J;w832|PS@@< z0azuLDqKaKflK8LBayL$JbdyeDIejt$uUBEr9h-FAzOc z>77x6QiE+okCXf^!$3Jb4e~vtb@g}Vs0#RjyUbrwMtWqDO!u!UsejH!?6o(m{>fK( z!V<||f3#Y~W$sk8^c&&r(~RL5FS+F^*Z%lJHn*%So{O*Er(b%8pLOYSY`xIstvZ@I zto#Fd+>7Roxmt^MER!Iix$^B>x6g~v#}{B;NVH}N5PKp}EdlpAkhglN2gwV6+MrPP zjqd%j4E(HBP44RYDufrMxDcmC=VUC`gt9e6fesOCfNBV+kfUEA-HSl!@Jz zrFw1pJpJq95|wbmvSOhWCDE&}p6mJ37g#%m-h=NUJcU#R3Kdk8!r8rpqj1{HW3SY~ zCnk?!*47QTH#JYL5B&9JXQ=!Q{wZysbo2f!4dIIBB$D_%QAm$kOWVjujuTSC>QPWP z{PzzK?%d-Y;)$3L^)285TDp9Jd#X0R{1eJY6hmZnv}Ysz*DCISck3J5>q{+T+5(&D z_*6x|Pz%n$s2|8p!lC3|=G|RD%ErX|RU66qgccrEW={b}Ner`G6Js$%sJSP26CVhM z7v3FBMq6~>Z;$*%sX%*%I65T!1L*OMKIBAB`C!z>y;|$cdy01gMj`;?v3Vb{z5&oq zPm;M1^(-&R|LadX>IuyehqMbBvLl$KWi-OX5xJZ14>xpczL%#xJj+Y`E@J7TFKyr75M9Nn-48k?d)BaPa;cBnxh;A5dl>Y%bDejmH6p{^axN4u`5xWF zk?SLoBsdYp#`5Xs?kn%`CN;Tj4n6CT=awAM+xkbFXD13ShXZhLT z!G4+|P{gMvzPIbnbdTDJ?sWj6D+h}p1MJiA>2(?Y&y$bf#iE#j|e^>K%RCA}vCCTaai(?K| zeXx3Cw#rU-ltH=7r8dLOqwR{BHml5Giu12-56)?Y9^tNhBRQ|mTU1Q#V%&3``(2Kw z*(eqDh6h~|%H8Z@gVxOi`7u(v!XfU|ekB7VugbDg-b{_#_br<^;krI9D)_A2XX72)dD4E|y-Lx{X+dT|ni9i~xpzh)Kz7dvo^~J|nUrl%TujOi z($Q`Y|A>hYjb=-dIE$B=jb=EJhDR64UHi4!qaX*1!Qo8OZz3d!V!CoYs? z0)mAn!voW{lmYY?Ri1&(E_4*aQE3ODpG#wJl(rpIkPJo;`&uUw+7{#}~bmK5$M$(}zevQi#mvAq-yf!(1>p zN?daq+1bSk3NqLr(3~jdhjMB^f{_Vzl&P_(w3;$?|Kr)xr3(`Ot*irA&q(-ww9iL= z93*&RdECb0XV(VV>EH`5w`vCJQ+Z1Q>isAW!pPA|ih_(C+> ziu1wfqg{x#Y}yBZqlD+S=K~FEs1M0sMN)7Y>8Jw;Mft@fiNwH#8QN3U9PgzM{ZMG% zXIB&Ws2^ts%tu_}+TMgB=-2o0SH2E)!J56KP9y-{As{7=+AY7QzH@3h&JN$$BUgcB0{_*Q>c%kIjzBRgEi4hsu6?vD2m&Wb9b`SfK`kk}_P3n>^ z+!rl_h%1MOnS`vaf9rfdBM$YzTpf9>yj+0`eS?by!KtjneD~VazO>OI(VAlXV#^1J z>M8N0#}6^9eNy4G4#+mx&c{B6G@S3b*d;GE1`4g-vA$lwPnskNGjSq_kg7cad2mA) zuWmoGLD&=D2I6V`YR-Tvaz78y11BX?aEhkTY4D}JFW0KuM=f{-olV3&SJ5ISa?f+{>kMBqyVeM3}ZSC9KTjGGWy1rViie1$I04fb7 At^fc4 diff --git a/documents/images/Zenith.NET.svg b/documents/images/Zenith.NET.svg index b508b02d..29cd129e 100644 --- a/documents/images/Zenith.NET.svg +++ b/documents/images/Zenith.NET.svg @@ -1,29 +1,7 @@ - - Zenith.NET - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + Zenith.NET + A white Z on a solid graphite rounded square, with a thin, even inner edge for dark backgrounds. + + + + From 447f663b7c999efecd0acb90c9123331ec4f6a27 Mon Sep 17 00:00:00 2001 From: qian-o <1324771795@qq.com> Date: Thu, 17 Sep 2026 09:53:19 +0800 Subject: [PATCH 05/35] Reformat SVG files for consistent indentation and spacing Reformatted Zenith.NET-Logo.svg and Zenith.NET.svg to use consistent indentation and spacing for improved readability and maintainability. No changes to SVG content or appearance. --- documents/images/Zenith.NET-Logo.svg | 20 ++++++++++---------- documents/images/Zenith.NET.svg | 12 ++++++------ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/documents/images/Zenith.NET-Logo.svg b/documents/images/Zenith.NET-Logo.svg index c62e3d0f..82fa23c9 100644 --- a/documents/images/Zenith.NET-Logo.svg +++ b/documents/images/Zenith.NET-Logo.svg @@ -1,11 +1,11 @@ - - Zenith.NET - A white Z on a solid graphite tile with a fine inner edge, paired with an outlined Zenith.NET wordmark. - - - + + Zenith.NET + A white Z on a solid graphite tile with a fine inner edge, paired with an outlined Zenith.NET wordmark. + + + diff --git a/documents/images/Zenith.NET.svg b/documents/images/Zenith.NET.svg index 29cd129e..b6f93b01 100644 --- a/documents/images/Zenith.NET.svg +++ b/documents/images/Zenith.NET.svg @@ -1,7 +1,7 @@ - - Zenith.NET - A white Z on a solid graphite rounded square, with a thin, even inner edge for dark backgrounds. - - - + + Zenith.NET + A white Z on a solid graphite rounded square, with a thin, even inner edge for dark backgrounds. + + + From e10b2df6a04d0faed42390f26308a160560185fa Mon Sep 17 00:00:00 2001 From: qian-o <1324771795@qq.com> Date: Thu, 17 Sep 2026 11:33:17 +0800 Subject: [PATCH 06/35] Update README.md for improved clarity and organization --- README.md | 95 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 48 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index 667734c0..a47e0bfa 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,34 @@ -

- Zenith.NET Logo +

+ Zenith.NET

-

Zenith.NET

-

- A modern rendering hardware interface for .NET.
- One consistent C# API for graphics and compute across DirectX 12, Metal 4, and Vulkan 1.4. + A modern rendering hardware interface for .NET.

- NuGet - License + Documentation · + Tutorials · + API Reference · + NuGet

---- - ## Overview -Zenith.NET provides a consistent C# API for resources, pipelines, command recording, synchronization, and presentation across DirectX 12, Metal 4, and Vulkan 1.4. +Zenith.NET provides one C# API for graphics and compute across DirectX 12, Metal 4, and Vulkan 1.4. It gives applications explicit control over GPU resources, pipelines, command recording, synchronization, and presentation. -The RHI exposes rasterization, compute, and indirect commands. Inline Ray Tracing and mesh shading are optional; check `Capabilities.RayTracingSupported` and `Capabilities.MeshShadingSupported` before use. Bindless resource handles expose shader resources, while queues, barriers, and texture layouts express ordering and access dependencies. +Build rasterization and compute workloads, access shader resources through bindless handles, and coordinate GPU work through queues, barriers, and timelines. Inline ray tracing and mesh shading are available through the same API when the device exposes the corresponding capabilities. -## Get Started +## Getting Started -Install the core package and one graphics API package: +In a .NET 10 project, install the core package and the backend you want to use. For Vulkan: -```powershell +```console dotnet add package Zenith.NET dotnet add package Zenith.NET.Vulkan ``` -Create a graphics context in C#: +Create a graphics context: ```csharp using Zenith.NET; @@ -40,47 +37,51 @@ using Zenith.NET.Vulkan; using GraphicsContext context = GraphicsContext.CreateVulkan(useValidationLayer: true); ``` -Continue with the [RHI Guide](https://qian-o.github.io/Zenith.NET/docs/) or build the examples in the [Tutorials](https://qian-o.github.io/Zenith.NET/tutorials/). +Follow [Project Setup](https://qian-o.github.io/Zenith.NET/tutorials/getting-started/project-setup.html) to configure a complete application, then continue with [Hello Triangle](https://qian-o.github.io/Zenith.NET/tutorials/guides/hello-triangle.html) for the first rendering workload. -## Platform Support +## Packages -| | DirectX 12 | Metal 4 | Vulkan 1.4 | -| :-------: | :--------: | :-----: | :--------: | -| Windows | Yes | | Yes | -| Apple | | Yes | Yes | -| Android | | | Yes | -| Linux | | | Yes | +Choose packages by their role in your application. Add a graphics backend, then the compiler, extensions, or UI integration you need. -## Packages +### Core and Backends -### Core +| Package | Purpose | +| --- | --- | +| `Zenith.NET` | Shared graphics and compute API, resource types, and command interfaces. | +| `Zenith.NET.Compiler` | Compile Slang shaders for the selected graphics API. | +| `Zenith.NET.DirectX12` | DirectX 12 backend. | +| `Zenith.NET.Metal` | Metal 4 backend. | +| `Zenith.NET.Vulkan` | Vulkan 1.4 backend. | -[![Zenith.NET](https://img.shields.io/nuget/v/Zenith.NET.svg?label=Zenith.NET&style=flat-square)](https://www.nuget.org/packages/Zenith.NET) +### Extensions -### Backends +| Package | Purpose | +| --- | --- | +| `Zenith.NET.Extensions.ImageSharp` | Load images into GPU textures with ImageSharp. | +| `Zenith.NET.Extensions.ImGui` | Dear ImGui rendering and input integration. | +| `Zenith.NET.Extensions.Skia` | SkiaSharp rendering with Zenith.NET textures. | +| `Zenith.NET.Extensions.Upscaling` | Spatial and temporal image upscaling. | -[![DirectX12](https://img.shields.io/nuget/v/Zenith.NET.DirectX12.svg?label=DirectX12&style=flat-square)](https://www.nuget.org/packages/Zenith.NET.DirectX12) -[![Metal](https://img.shields.io/nuget/v/Zenith.NET.Metal.svg?label=Metal&style=flat-square)](https://www.nuget.org/packages/Zenith.NET.Metal) -[![Vulkan](https://img.shields.io/nuget/v/Zenith.NET.Vulkan.svg?label=Vulkan&style=flat-square)](https://www.nuget.org/packages/Zenith.NET.Vulkan) +### UI Integrations -### Extensions +| Package | Purpose | +| --- | --- | +| `Zenith.NET.Views` | Shared rendering-view interfaces and frame events. | +| `Zenith.NET.Views.Avalonia` | Avalonia rendering control. | +| `Zenith.NET.Views.Maui` | .NET MAUI rendering control. | +| `Zenith.NET.Views.WinForms` | Windows Forms rendering control. | +| `Zenith.NET.Views.WinUI` | WinUI 3 and Uno rendering control. | +| `Zenith.NET.Views.WPF` | WPF rendering control. | -[![ImageSharp](https://img.shields.io/nuget/v/Zenith.NET.Extensions.ImageSharp.svg?label=ImageSharp&style=flat-square)](https://www.nuget.org/packages/Zenith.NET.Extensions.ImageSharp) -[![ImGui](https://img.shields.io/nuget/v/Zenith.NET.Extensions.ImGui.svg?label=ImGui&style=flat-square)](https://www.nuget.org/packages/Zenith.NET.Extensions.ImGui) -[![Skia](https://img.shields.io/nuget/v/Zenith.NET.Extensions.Skia.svg?label=Skia&style=flat-square)](https://www.nuget.org/packages/Zenith.NET.Extensions.Skia) -[![Upscaling](https://img.shields.io/nuget/v/Zenith.NET.Extensions.Upscaling.svg?label=Upscaling&style=flat-square)](https://www.nuget.org/packages/Zenith.NET.Extensions.Upscaling) +See [Views](https://qian-o.github.io/Zenith.NET/docs/presentation/views.html) for integrating rendering into a UI application. -### Views +## Documentation and Examples -[![Views](https://img.shields.io/nuget/v/Zenith.NET.Views.svg?label=Views&style=flat-square)](https://www.nuget.org/packages/Zenith.NET.Views) -[![Avalonia](https://img.shields.io/nuget/v/Zenith.NET.Views.Avalonia.svg?label=Avalonia&style=flat-square)](https://www.nuget.org/packages/Zenith.NET.Views.Avalonia) -[![MAUI](https://img.shields.io/nuget/v/Zenith.NET.Views.Maui.svg?label=MAUI&style=flat-square)](https://www.nuget.org/packages/Zenith.NET.Views.Maui) -[![WinForms](https://img.shields.io/nuget/v/Zenith.NET.Views.WinForms.svg?label=WinForms&style=flat-square)](https://www.nuget.org/packages/Zenith.NET.Views.WinForms) -[![WinUI](https://img.shields.io/nuget/v/Zenith.NET.Views.WinUI.svg?label=WinUI&style=flat-square)](https://www.nuget.org/packages/Zenith.NET.Views.WinUI) -[![WPF](https://img.shields.io/nuget/v/Zenith.NET.Views.WPF.svg?label=WPF&style=flat-square)](https://www.nuget.org/packages/Zenith.NET.Views.WPF) +- [RHI Guide](https://qian-o.github.io/Zenith.NET/docs/) — resources, shaders, pipelines, commands, synchronization, and presentation. +- [Tutorials](https://qian-o.github.io/Zenith.NET/tutorials/) — rendering and compute walkthroughs, from a triangle to ray tracing and mesh shading. +- [API Reference](https://qian-o.github.io/Zenith.NET/api/) — types and members. +- [Experiments](sources/Experiments/) — sample applications and utilities in this repository. -## Documentation +## License -- [RHI Guide](https://qian-o.github.io/Zenith.NET/docs/) -- [Tutorials](https://qian-o.github.io/Zenith.NET/tutorials/) -- [API Reference](https://qian-o.github.io/Zenith.NET/api/) +Zenith.NET is licensed under the [MIT License](LICENSE). From 1eed633c29bcf4e92860d32d6214ea611c18d6e9 Mon Sep 17 00:00:00 2001 From: qian-o <1324771795@qq.com> Date: Thu, 17 Sep 2026 11:34:09 +0800 Subject: [PATCH 07/35] Bump NuGet package to 1.1.0-alpha Updated NuGet.Packaging.props to reference version 1.1.0-alpha instead of 1.0.0. --- sources/NuGet.Packaging.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/NuGet.Packaging.props b/sources/NuGet.Packaging.props index e60169d2..932c0733 100644 --- a/sources/NuGet.Packaging.props +++ b/sources/NuGet.Packaging.props @@ -7,7 +7,7 @@ $(MSBuildThisFileDirectory)..\.nuget - 1.0.0 + 1.1.0-alpha qian-o Copyright (c) 2026 qian-o Zenith.NET is a modern rendering hardware interface for .NET with one consistent C# API for graphics and compute across DirectX 12, Metal 4, and Vulkan 1.4. From 03385b04c5d9b2b980eef3ef8529f3d0cfc75c0e Mon Sep 17 00:00:00 2001 From: qian-o <1324771795@qq.com> Date: Fri, 18 Sep 2026 00:10:56 +0800 Subject: [PATCH 08/35] feat: add interactive API browser, home scene animation, member finder, motion effects, and custom search functionality - Implemented an interactive API browser with dynamic namespace and type filtering. - Added a rotating canvas geometry scene for the home page. - Created a member finder dialog for quick access to API members. - Introduced motion effects for content reveal on scroll. - Developed a custom search interface utilizing DocFX's generated index and search worker. --- README.md | 16 +- documents/api/index.md | 45 +- documents/docfx.json | 18 +- .../docs/fundamentals/bindless-resources.md | 99 - documents/docs/fundamentals/commands.md | 62 - documents/docs/fundamentals/queries.md | 85 - documents/docs/fundamentals/runtime.md | 79 - documents/docs/fundamentals/shaders.md | 71 - .../docs/fundamentals/synchronization.md | 79 - documents/docs/index.md | 34 - documents/docs/presentation/swap-chains.md | 58 - documents/docs/presentation/views.md | 48 - documents/docs/resources/buffers.md | 72 - documents/docs/resources/heaps.md | 82 - documents/docs/resources/textures.md | 91 - documents/docs/toc.yml | 44 - documents/docs/workloads/compute.md | 48 - documents/docs/workloads/mesh-shading.md | 53 - documents/docs/workloads/rasterization.md | 68 - documents/docs/workloads/ray-tracing.md | 74 - documents/images/Zenith.NET-Logo.png | Bin 6904 -> 6576 bytes documents/images/Zenith.NET-Logo.svg | 5 +- documents/index.md | 219 +- documents/learn/concepts/execution-model.md | 3 + .../learn/concepts/platform-integration.md | 3 + .../learn/concepts/resource-management.md | 3 + .../learn/concepts/shader-data-and-binding.md | 3 + documents/learn/concepts/synchronization.md | 3 + documents/learn/first-triangle.md | 3 + documents/learn/index.md | 33 + documents/learn/samples.md | 3 + documents/learn/toc.yml | 22 + .../templates/ManagedReference.extension.js | 26 +- .../ManagedReference.html.primary.tmpl | 7 + documents/templates/layout/_master.tmpl | 184 + .../templates/partials/api.enum.tmpl.partial | 18 + .../partials/api.header.tmpl.partial | 13 + .../partials/api.namespace.tmpl.partial | 13 + .../partials/api.relationships.tmpl.partial | 11 + .../partials/api.seealso.tmpl.partial | 2 + .../partials/api.signature.tmpl.partial | 7 + .../templates/partials/api.type.tmpl.partial | 25 + documents/templates/public/api.css | 208 + documents/templates/public/api.js | 117 + documents/templates/public/home.js | 190 + documents/templates/public/main.css | 4500 ++++------------- documents/templates/public/main.js | 1171 +---- documents/templates/public/member-finder.js | 156 + documents/templates/public/motion.js | 42 + documents/templates/public/search.js | 201 + documents/toc.yml | 10 +- .../getting-started/application-host.md | 291 -- .../getting-started/project-setup.md | 134 - documents/tutorials/guides/compute-shader.md | 253 - documents/tutorials/guides/hello-triangle.md | 216 - .../tutorials/guides/indirect-drawing.md | 289 -- documents/tutorials/guides/mesh-shading.md | 454 -- documents/tutorials/guides/ray-tracing.md | 441 -- documents/tutorials/guides/spinning-cube.md | 265 - documents/tutorials/index.md | 36 - documents/tutorials/toc.yml | 24 - 61 files changed, 2561 insertions(+), 8269 deletions(-) delete mode 100644 documents/docs/fundamentals/bindless-resources.md delete mode 100644 documents/docs/fundamentals/commands.md delete mode 100644 documents/docs/fundamentals/queries.md delete mode 100644 documents/docs/fundamentals/runtime.md delete mode 100644 documents/docs/fundamentals/shaders.md delete mode 100644 documents/docs/fundamentals/synchronization.md delete mode 100644 documents/docs/index.md delete mode 100644 documents/docs/presentation/swap-chains.md delete mode 100644 documents/docs/presentation/views.md delete mode 100644 documents/docs/resources/buffers.md delete mode 100644 documents/docs/resources/heaps.md delete mode 100644 documents/docs/resources/textures.md delete mode 100644 documents/docs/toc.yml delete mode 100644 documents/docs/workloads/compute.md delete mode 100644 documents/docs/workloads/mesh-shading.md delete mode 100644 documents/docs/workloads/rasterization.md delete mode 100644 documents/docs/workloads/ray-tracing.md create mode 100644 documents/learn/concepts/execution-model.md create mode 100644 documents/learn/concepts/platform-integration.md create mode 100644 documents/learn/concepts/resource-management.md create mode 100644 documents/learn/concepts/shader-data-and-binding.md create mode 100644 documents/learn/concepts/synchronization.md create mode 100644 documents/learn/first-triangle.md create mode 100644 documents/learn/index.md create mode 100644 documents/learn/samples.md create mode 100644 documents/learn/toc.yml create mode 100644 documents/templates/ManagedReference.html.primary.tmpl create mode 100644 documents/templates/layout/_master.tmpl create mode 100644 documents/templates/partials/api.enum.tmpl.partial create mode 100644 documents/templates/partials/api.header.tmpl.partial create mode 100644 documents/templates/partials/api.namespace.tmpl.partial create mode 100644 documents/templates/partials/api.relationships.tmpl.partial create mode 100644 documents/templates/partials/api.seealso.tmpl.partial create mode 100644 documents/templates/partials/api.signature.tmpl.partial create mode 100644 documents/templates/partials/api.type.tmpl.partial create mode 100644 documents/templates/public/api.css create mode 100644 documents/templates/public/api.js create mode 100644 documents/templates/public/home.js create mode 100644 documents/templates/public/member-finder.js create mode 100644 documents/templates/public/motion.js create mode 100644 documents/templates/public/search.js delete mode 100644 documents/tutorials/getting-started/application-host.md delete mode 100644 documents/tutorials/getting-started/project-setup.md delete mode 100644 documents/tutorials/guides/compute-shader.md delete mode 100644 documents/tutorials/guides/hello-triangle.md delete mode 100644 documents/tutorials/guides/indirect-drawing.md delete mode 100644 documents/tutorials/guides/mesh-shading.md delete mode 100644 documents/tutorials/guides/ray-tracing.md delete mode 100644 documents/tutorials/guides/spinning-cube.md delete mode 100644 documents/tutorials/index.md delete mode 100644 documents/tutorials/toc.yml diff --git a/README.md b/README.md index a47e0bfa..bb5eb1e1 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,16 @@

- Zenith.NET + Zenith.NET icon

+

Zenith.NET

+

A modern rendering hardware interface for .NET.

- Documentation · - Tutorials · + Learn · + Samples · API Reference · NuGet

@@ -37,7 +39,7 @@ using Zenith.NET.Vulkan; using GraphicsContext context = GraphicsContext.CreateVulkan(useValidationLayer: true); ``` -Follow [Project Setup](https://qian-o.github.io/Zenith.NET/tutorials/getting-started/project-setup.html) to configure a complete application, then continue with [Hello Triangle](https://qian-o.github.io/Zenith.NET/tutorials/guides/hello-triangle.html) for the first rendering workload. +The [First Triangle](https://qian-o.github.io/Zenith.NET/learn/first-triangle.html) tutorial is being prepared. ## Packages @@ -73,12 +75,12 @@ Choose packages by their role in your application. Add a graphics backend, then | `Zenith.NET.Views.WinUI` | WinUI 3 and Uno rendering control. | | `Zenith.NET.Views.WPF` | WPF rendering control. | -See [Views](https://qian-o.github.io/Zenith.NET/docs/presentation/views.html) for integrating rendering into a UI application. +The [Platform Integration](https://qian-o.github.io/Zenith.NET/learn/concepts/platform-integration.html) guide is being prepared. ## Documentation and Examples -- [RHI Guide](https://qian-o.github.io/Zenith.NET/docs/) — resources, shaders, pipelines, commands, synchronization, and presentation. -- [Tutorials](https://qian-o.github.io/Zenith.NET/tutorials/) — rendering and compute walkthroughs, from a triangle to ray tracing and mesh shading. +- [Learn](https://qian-o.github.io/Zenith.NET/learn/) — the documentation outline; content is being prepared. +- [Samples](https://qian-o.github.io/Zenith.NET/learn/samples.html) — the sample index placeholder. - [API Reference](https://qian-o.github.io/Zenith.NET/api/) — types and members. - [Experiments](sources/Experiments/) — sample applications and utilities in this repository. diff --git a/documents/api/index.md b/documents/api/index.md index a92e1ecc..d9e89e40 100644 --- a/documents/api/index.md +++ b/documents/api/index.md @@ -1,32 +1,13 @@ -# API Reference - -The API reference documents the public Zenith.NET types, members, parameters, and enum values. Start with the [RHI Guide](../docs/index.md) when learning a workflow. - -## Start Here - -| Type | Purpose | -|------|---------| -| `GraphicsContext` | Creates resources and exposes capabilities and command queues | -| `CommandQueue` | Owns and lends command buffers for one class of GPU work | -| `CommandBuffer` | Queue-owned recorder borrowed for one immediate submission | -| `TimelineValue` | Represents a queue-submission completion point that can be queried or waited on | -| `QueryHeap` / `QueryHeapDesc` | Collect visibility results and GPU timestamps | -| `BufferDesc` / `TextureDesc` | Describe resources before creation | -| `GraphicsPipelineDesc` / `ComputePipelineDesc` | Describe shader pipelines | -| `Surface` / `SwapChain` | Connect rendering to a window | -| `ZenithCompiler` | Compiles Slang source for the selected graphics API | - -## Public Namespaces - -| Namespace | Contents | -|-----------|----------| -| `Zenith.NET` | Core RHI types and Slang compilation | -| `Zenith.NET.DirectX12` | DirectX 12 context factory | -| `Zenith.NET.Metal` | Metal context factory | -| `Zenith.NET.Vulkan` | Vulkan context factory | -| `Zenith.NET.Extensions.ImageSharp` | Image loading and mip generation | -| `Zenith.NET.Extensions.ImGui` | Dear ImGui integration | -| `Zenith.NET.Views` | Shared View contracts and frame event data | -| `Zenith.NET.Views.*` | Framework-specific View controls | - -Browse the namespace tree to inspect the complete public API reference. The guide pages link related concepts, while the [Tutorials](../tutorials/index.md) show the types in complete applications. +--- +title: API Reference +description: Explore the types and members in Zenith.NET. +--- + +
+
Reference

API Reference

Types and members for graphics, compute, and platform integration.

+ +

Namespaces

+
diff --git a/documents/docfx.json b/documents/docfx.json index 56d86754..d96eaf20 100644 --- a/documents/docfx.json +++ b/documents/docfx.json @@ -22,8 +22,7 @@ { "files": [ "api/**/*.{md,yml}", - "docs/**/*.{md,yml}", - "tutorials/**/*.{md,yml}", + "learn/**/*.{md,yml}", "index.md", "toc.yml" ] @@ -41,6 +40,21 @@ "modern", "templates" ], + "fileMetadata": { + "_section": { + "learn/**": "learn", + "api/**": "api" + }, + "_apiReference": { + "api/**": true + }, + "_disableAffix": { + "api/**": true + }, + "_disableTocFilter": { + "learn/**": true + } + }, "globalMetadata": { "_appTitle": "Zenith.NET", "_appLogoPath": "images/Zenith.NET-Logo.svg", diff --git a/documents/docs/fundamentals/bindless-resources.md b/documents/docs/fundamentals/bindless-resources.md deleted file mode 100644 index 7441f9db..00000000 --- a/documents/docs/fundamentals/bindless-resources.md +++ /dev/null @@ -1,99 +0,0 @@ -# Bindless Resources - -Shaders access Zenith.NET resources through `ResourceHandle` values. Store the handles in constant data, upload that data to a constant buffer, and declare matching typed handles in Slang. - -## Select a Handle - -Choose the handle that matches the shader access: - -| C# resource | Handle | Slang resource | -|--------------|--------|----------------| -| `Buffer` / `BufferView` | `ConstantHandle` | `ConstantBuffer` | -| `Buffer` / `BufferView` | `StorageReadOnlyHandle` | `StructuredBuffer` | -| `Buffer` / `BufferView` | `StorageReadWriteHandle` | `RWStructuredBuffer` | -| `Texture` / `TextureView` | `SampledHandle` | `Texture1D`, `Texture2D`, `Texture3D`, or cube texture types | -| `Texture` / `TextureView` | `StorageHandle` | `RWTexture1D`, `RWTexture2D`, or `RWTexture3D` | -| `Sampler` | `Handle` | `SamplerState` or `SamplerComparisonState` | -| `TopLevelAccelerationStructure` | `Handle` | `RaytracingAccelerationStructure` | - -The resource description must include the usage required by the selected handle. - -## Define Constant Data - -Use an unmanaged C# structure whose layout matches the shader structure: - -```csharp -[StructLayout(LayoutKind.Explicit, Size = 8)] -file struct Constants -{ - [FieldOffset(0)] - public ResourceHandle Resource; -} -``` - -Populate the structure with handles from the resources or views used by the command: - -```csharp -Constants constants = new() { Resource = texture.SampledHandle }; -``` - -Create a constant buffer and upload the structure: - -```csharp -BufferDesc desc = new() -{ - SizeInBytes = sizeof(Constants), - StrideInBytes = 0, - Usages = BufferUsages.Constant | BufferUsages.TransferDst, - Residency = MemoryResidency.GpuOnly -}; - -Buffer buffer = context.CreateBuffer(desc); -buffer.Upload(0, new() -{ - Pointer = &constants, - SizeInBytes = sizeof(Constants) -}); -``` - -Verify field offsets against the Slang layout, especially when a structure contains vectors, matrices, or nested records. - -## Declare Shader Handles - -Declare matching typed handles and expose the record as `ConstantBuffer`: - -```slang -struct Constants -{ - DescriptorHandle Resource; -}; - -ConstantBuffer constants; -``` - -## Bind the Constants - -Bind the constant buffer after setting the pipeline: - -```csharp -commandBuffer.SetConstantBuffer(buffer, 0); -``` - -The second argument is the byte offset into the buffer. - -## Use Views - -`Buffer` and `Texture` expose handles for the whole resource. Create a `BufferView` when a shader needs a byte subrange with a specific stride, and create a `TextureView` when it needs selected mip levels or array layers. Use `sizeof(T)` for typed buffer sizes and strides. - -Views do not own their source resource. Keep both the view and its source alive while submitted work uses the handle. - -## Match Usage and Synchronization - -A handle does not change a texture layout or create a memory dependency: - -- Sampled access requires `TextureUsages.Sampled` and `TextureLayout.Sampled`. -- Storage texture access requires `TextureUsages.Storage` and `TextureLayout.Storage`. -- Storage buffer access requires the matching storage usage. -- Producer/consumer access without a layout change requires a `Barrier`. - -`ResourceHandle` does not own its resource. Keep the resource or view alive through the final submission that uses the handle, and update constant data when replacing it. diff --git a/documents/docs/fundamentals/commands.md b/documents/docs/fundamentals/commands.md deleted file mode 100644 index 6ba920fb..00000000 --- a/documents/docs/fundamentals/commands.md +++ /dev/null @@ -1,62 +0,0 @@ -# Commands - -GPU work is recorded in a `CommandBuffer` borrowed from its `CommandQueue`. Recording preserves command order, but execution begins only after submission. - -## Record and Submit Work - -Borrow a command buffer from the queue that should execute the work: - -```csharp -CommandBuffer commandBuffer = context.ComputeQueue.CommandBuffer(); - -commandBuffer.Transition(texture, default, TextureLayout.Undefined, TextureLayout.Storage); - -commandBuffer.SetPipeline(pipeline); -commandBuffer.SetConstantBuffer(buffer, 0); -commandBuffer.Dispatch(groupCountX, groupCountY, 1); - -commandBuffer.Transition(texture, default, TextureLayout.Storage, TextureLayout.Sampled); - -commandBuffer.Submit(); -``` - -A command buffer is queue-owned and valid only for the current recording. Set the matching pipeline before binding state or issuing work, submit it immediately, and never store, reuse, or dispose it. - -## Track Completion - -`Submit()` returns a `TimelineValue`. Use `IsCompleted` only for a non-blocking status query. Call `Wait()` when CPU code must observe GPU results, including command-buffer downloads. To order queues without blocking the CPU, pass the producer value to the consumer submission. See [Synchronization](synchronization.md). - -## Record a Render Pass - -Transition attachments before beginning a render pass: - -```csharp -commandBuffer.Transition(texture, default, TextureLayout.Undefined, TextureLayout.ColorAttachment); -commandBuffer.BeginRenderPass([ColorAttachment.Clear(texture, default)], null); - -commandBuffer.SetPipeline(pipeline); -commandBuffer.SetVertexBuffer(buffer, 0, 0); -commandBuffer.Draw(vertexCount, 1, 0, 0); - -commandBuffer.EndRenderPass(); -``` - -`BeginRenderPass` resets the viewport and scissor state to one pair, regardless of the number of color attachments. The pair covers the selected mip level of the first color attachment. When there are no color attachments, its dimensions come from the depth/stencil attachment's selected mip level instead. - -`SetViewports` and `SetScissors` replace the corresponding active arrays, including their counts. Call them after `BeginRenderPass` to change the rendering region or configure multiple viewports. Both arrays must be nonempty and within the device's supported limits, and their counts must match before drawing. Using more than one pair requires device support for multiple viewports. - -The array indices identify viewport/scissor slots, not color attachments. See [MRT and Viewports](../workloads/rasterization.md#mrt-and-viewports) for the distinction. - -## Transfer Data - -Command buffers can upload, download, copy, and resolve resources. These operations can be batched with later GPU work. - -Texture transfer commands do not change texture layouts. Record the required `CopySrc`, `CopyDst`, `ResolveSrc`, or `ResolveDst` transitions around them. - -For simple one-off transfers, `Buffer.Upload`, `Buffer.Download`, `Texture.Upload`, and `Texture.Download` complete the transfer before returning. - -## Label GPU Work - -Use `BeginDebugEvent`, `EndDebugEvent`, and `InsertDebugMarker` to identify recorded GPU work in diagnostics. - -Query and acceleration-structure commands follow the same record-then-submit model. See [Queries](queries.md) for visibility and timestamp results, and [Ray Tracing](../workloads/ray-tracing.md) for acceleration-structure builds. diff --git a/documents/docs/fundamentals/queries.md b/documents/docs/fundamentals/queries.md deleted file mode 100644 index 5b2c6d9c..00000000 --- a/documents/docs/fundamentals/queries.md +++ /dev/null @@ -1,85 +0,0 @@ -# Queries - -Queries report information produced while the GPU executes commands. Create a query heap from the same `GraphicsContext` as the command buffer, record query operations, and read the results after the submission has completed. - -## Create a Query Heap - -Choose a query heap description for the result you need: - -| Description | Result | Recording commands | -|-------------|--------|--------------------| -| `QueryHeapDesc.Occlusion` | Number of samples that pass the visibility tests | `BeginQuery` and `EndQuery` | -| `QueryHeapDesc.BinaryOcclusion` | Whether any sample passes the visibility tests | `BeginQuery` and `EndQuery` | -| `QueryHeapDesc.Timestamp` | GPU timestamp values | `WriteTimestamp` | - -The count in the description is the number of query slots. Use a separate index for each result that must remain available at the same time: - -```csharp -QueryHeap queryHeap = context.CreateQueryHeap(QueryHeapDesc.Occlusion(1)); -``` - -Keep the query heap alive until every submitted command that refers to it has completed. - -## Record Occlusion Queries - -While a render pass is active, surround the drawing commands whose visibility you want to measure with `BeginQuery` and `EndQuery`. Keep both query commands in the same render pass: - -```csharp -commandBuffer.BeginRenderPass([ColorAttachment.Load(colorTarget)], null); -commandBuffer.BeginQuery(queryHeap, 0); - -commandBuffer.SetPipeline(pipeline); -commandBuffer.Draw(vertexCount, 1, 0, 0); - -commandBuffer.EndQuery(queryHeap, 0); -commandBuffer.EndRenderPass(); -``` - -Use an occlusion heap for a sample count or a binary occlusion heap when only a visible-or-not result is needed. Submit the command buffer before reading the result. - -## Record Timestamps - -Write two timestamps around the work whose GPU duration you want to measure. Timestamp results are raw `ulong` values until the queue converts their difference: - -```csharp -QueryHeap queryHeap = context.CreateQueryHeap(QueryHeapDesc.Timestamp(2)); -CommandBuffer commandBuffer = context.ComputeQueue.CommandBuffer(); - -commandBuffer.WriteTimestamp(queryHeap, 0); - -commandBuffer.SetPipeline(pipeline); -commandBuffer.Dispatch(groupCountX, groupCountY, groupCountZ); - -commandBuffer.WriteTimestamp(queryHeap, 1); - -TimelineValue completion = commandBuffer.Submit(); -completion.Wait(); -``` - -Read the two results and ask the same queue that recorded them for the elapsed time: - -```csharp -Span timestamps = stackalloc ulong[2]; -queryHeap.GetResults(timestamps, 0); - -double elapsedNanoseconds = context.ComputeQueue.GetElapsedNanoseconds(timestamps[0], timestamps[1]); -``` - -The two timestamp values must come from the same queue. `GetElapsedNanoseconds` returns the elapsed GPU time between the values; it does not represent a wall-clock time. - -## Read Results - -Wait for the submission that writes the queries before calling `GetResults`: - -```csharp -Span results = stackalloc ulong[1]; -queryHeap.GetResults(results, 0); -``` - -The span length selects how many consecutive results to read, and `startIndex` selects the first query slot. Keep the span within the query heap's count. Reuse a slot only after the submission that last wrote it has completed. - -## Manage Query Lifetime - -Query heaps are application-owned resources. Dispose them after the command submissions that use them have completed. Command buffers remain queue-owned borrows; submit them before reading their query results and do not dispose them directly. - -Queries use the same recording and completion model as other commands. Review [Commands](commands.md) for command-buffer lifetime and [Synchronization](synchronization.md) for submission dependencies. \ No newline at end of file diff --git a/documents/docs/fundamentals/runtime.md b/documents/docs/fundamentals/runtime.md deleted file mode 100644 index dfd3ae11..00000000 --- a/documents/docs/fundamentals/runtime.md +++ /dev/null @@ -1,79 +0,0 @@ -# Runtime - -`GraphicsContext` is the root of a Zenith.NET application. It identifies the selected graphics API, reports device capabilities, exposes command queues, and creates resources. - -Create resources that work together from the same context. - -## Create a Context - -Add the core package and at least one graphics API package: - -| Package | Graphics API | Platform support | -|---------|--------------|------------------| -| `Zenith.NET.DirectX12` | DirectX 12 | Windows | -| `Zenith.NET.Metal` | Metal 4 | Apple platforms | -| `Zenith.NET.Vulkan` | Vulkan 1.4 | Windows, Apple platforms, Android, and Linux | - -Each package adds a context factory. For example: - -```csharp -GraphicsContext context = GraphicsContext.CreateVulkan(useValidationLayer: true); -``` - -Use `CreateDirectX12`, `CreateMetal`, or `CreateVulkan` for the selected backend. Reference only the packages your application can select. The selected API is available through `context.GraphicsApi`. - -## Check Capabilities - -Inspect optional features before creating the resources that require them: - -```csharp -Console.WriteLine(context.Capabilities.DeviceName); - -if (context.Capabilities.RayTracingSupported) -{ - // Acceleration structures and inline RayQuery can be used. -} - -if (context.Capabilities.MeshShadingSupported) -{ - // Mesh shading pipelines can be created. -} -``` - -Use capabilities to select an application feature or a compatible fallback. - -## Choose a Queue - -Every context exposes three command queues: - -| Property | Intended work | -|----------|---------------| -| `GraphicsQueue` | Rendering, compute, copies, and presentation | -| `ComputeQueue` | Compute and acceleration-structure work | -| `TransferQueue` | Buffer transfers and copy commands | - -Borrow a command buffer from the queue that will execute the work, such as `context.GraphicsQueue.CommandBuffer()`. Record and submit it immediately; the queue owns and recycles it. - -See [Commands](commands.md) for recording and submission. - -## Enable Validation - -Enable validation during development and subscribe before creating resources: - -```csharp -GraphicsContext context = GraphicsContext.CreateVulkan(useValidationLayer: true); - -context.ValidationMessage += static (_, args) => Console.WriteLine($"[{args.Severity}] {args.Message}"); -``` - -Set resource names when they help identify objects in diagnostics: - -```csharp -buffer.Name = "Buffer"; -``` - -Validation messages have `Error`, `Warning`, or `Info` severity. - -## Dispose Objects - -Zenith.NET resources implement `IDisposable`. After rendering has stopped, dispose application-owned resources and dispose the context last. Command buffers are queue-owned borrows for one recording and submission; never dispose or retain them. diff --git a/documents/docs/fundamentals/shaders.md b/documents/docs/fundamentals/shaders.md deleted file mode 100644 index 20e76cbd..00000000 --- a/documents/docs/fundamentals/shaders.md +++ /dev/null @@ -1,71 +0,0 @@ -# Shaders - -Zenith.NET compiles Slang entry points for the active `GraphicsApi`, then creates `Shader` objects from the resulting descriptions. Pipeline creation combines those shader objects with workload-specific state. - -## Compile from a File - -Pass the active graphics API, the source file, and the entry-point name to `ZenithCompiler.CompileFromFile`: - -```csharp -ShaderDesc vertexDesc = ZenithCompiler.CompileFromFile(context.GraphicsApi, "Shaders/Basic.slang", "VSMain"); - -Shader vertexShader = context.CreateShader(vertexDesc); -``` - -The `name` argument identifies the Slang entry point. Compile each entry point required by the pipeline, then assign the resulting shaders to its description. - -## Compile from Source - -Use `CompileFromSource` when the Slang source is already available as a string: - -```csharp -const string source = """ -[shader("compute")] -[numthreads(8, 8, 1)] -void CSMain(uint3 dispatchThreadID : SV_DispatchThreadID) -{ -} -"""; - -ShaderDesc computeDesc = ZenithCompiler.CompileFromSource(context.GraphicsApi, source, "CSMain"); - -Shader computeShader = context.CreateShader(computeDesc); -``` - -Provide additional lookup directories through `searchPaths` when the shader imports other source files: - -```csharp -ShaderDesc desc = ZenithCompiler.CompileFromFile(context.GraphicsApi, "Shaders/Lighting.slang", "PSMain", ["Shaders", "Shaders/Shared"]); -``` - -## Create a Pipeline - -Assign compiled shaders to the pipeline description that matches the workload: - -```csharp -ComputePipeline pipeline = context.CreateComputePipeline(new() { ComputeShader = computeShader }); -``` - -Graphics pipelines use vertex and fragment shaders, while mesh shading pipelines use mesh and fragment shaders and may also use a task shader. For both pipeline types, the attachment formats and render state must match the render pass where the pipeline is used. - -## Use Thread-Group Size - -Compute shader reflection stores the entry point's thread-group dimensions in `ShaderDesc.ThreadGroupSize`. Use those values when converting a workload size into dispatch groups: - -```csharp -ThreadGroupSize threadGroupSize = computeShader.Desc.ThreadGroupSize; - -uint groupCountX = (width + threadGroupSize.X - 1) / threadGroupSize.X; -uint groupCountY = (height + threadGroupSize.Y - 1) / threadGroupSize.Y; - -commandBuffer.SetPipeline(pipeline); -commandBuffer.Dispatch(groupCountX, groupCountY, 1); -``` - -Round each dimension up to a complete group and handle threads outside the workload in the shader. - -## Manage Shader Lifetime - -Shader objects are required while creating a pipeline and can be disposed after pipeline creation returns. Keep the pipeline alive until every submitted command that uses it has completed. - -Use [Rasterization](../workloads/rasterization.md), [Compute](../workloads/compute.md), [Ray Tracing](../workloads/ray-tracing.md), and [Mesh Shading](../workloads/mesh-shading.md) for workload-specific pipeline descriptions and commands. \ No newline at end of file diff --git a/documents/docs/fundamentals/synchronization.md b/documents/docs/fundamentals/synchronization.md deleted file mode 100644 index 09a5587c..00000000 --- a/documents/docs/fundamentals/synchronization.md +++ /dev/null @@ -1,79 +0,0 @@ -# Synchronization - -Synchronization makes data produced by earlier GPU work available to later work. Choose the mechanism that matches the dependency: - -| Mechanism | Use it when | -|-----------|-------------| -| `Barrier(before, after)` | Commands in one command buffer share data without changing a texture layout | -| `Transition(texture, subresource, before, after)` | A texture changes its access role | -| `Submit(waitValues...)` | A submission depends on work submitted to another queue | - -## Add a Memory Barrier - -Use `Barrier` when a later command consumes memory written by an earlier command and the resource layout does not change: - -```csharp -commandBuffer.SetPipeline(pipeline); -commandBuffer.Dispatch(groupCount, 1, 1); - -commandBuffer.Barrier(BarrierStages.ComputeShading, BarrierStages.ComputeShading); - -commandBuffer.SetPipeline(nextPipeline); -commandBuffer.Dispatch(nextGroupCount, 1, 1); -``` - -Common cases include storage-buffer producer/consumer chains and compute-generated indirect arguments. Select the stages that perform the producing and consuming work, and combine flags when several stages consume the result. - -Use `BarrierStages.All` only when a narrower dependency cannot describe the work. - -## Transition a Texture - -Supply the current and next layout whenever a texture changes how it is used: - -```csharp -commandBuffer.Transition(texture, default, TextureLayout.Undefined, TextureLayout.Storage); - -commandBuffer.SetPipeline(pipeline); -commandBuffer.SetConstantBuffer(buffer, 0); -commandBuffer.Dispatch(groupCountX, groupCountY, 1); - -commandBuffer.Transition(texture, default, TextureLayout.Storage, TextureLayout.Sampled); -``` - -`default` selects mip level zero and array layer zero. Pass a `TextureSubresource` with the required `MipLevel` and `ArrayLayer` when another subresource is needed. - -Use `Undefined` as the source only when previous contents can be discarded. Copy, resolve, and command-buffer upload or download operations do not insert transitions. The `Texture.Upload` and `Texture.Download` convenience methods perform their declared current-to-final layout transitions. - -The principal layouts are listed in declaration order: - -| Layout | Access role | -|--------|-------------| -| `Undefined` | Previous contents are discarded | -| `Common` | General access and shared-texture presentation paths | -| `Sampled` | Sampled texture reads | -| `Storage` | Storage texture reads and writes | -| `ColorAttachment` | Color attachment access | -| `DepthStencilAttachment` | Writable depth/stencil attachment access | -| `DepthStencilReadOnly` | Read-only depth/stencil access | -| `CopySrc` / `CopyDst` | Copy source or destination | -| `ResolveSrc` / `ResolveDst` | Resolve source or destination | -| `Present` | Presentation | - -## Order Work Across Queues - -Pass a producer's `TimelineValue` to the dependent submission: - -```csharp -CommandBuffer commandBuffer = context.TransferQueue.CommandBuffer(); -commandBuffer.Upload(buffer, 0, data); -TimelineValue timelineValue = commandBuffer.Submit(); - -commandBuffer = context.ComputeQueue.CommandBuffer(); -commandBuffer.SetPipeline(pipeline); -commandBuffer.SetConstantBuffer(buffer, 0); -commandBuffer.Dispatch(groupCountX, groupCountY, 1); - -commandBuffer.Submit(timelineValue); -``` - -Passing a producer `TimelineValue` to `Submit` orders the consumer submission after that value without blocking the CPU. Call `Wait()` only when CPU code must observe GPU results. diff --git a/documents/docs/index.md b/documents/docs/index.md deleted file mode 100644 index df51b4d1..00000000 --- a/documents/docs/index.md +++ /dev/null @@ -1,34 +0,0 @@ -# RHI Guide - -Use this guide to learn the Zenith.NET programming model. It covers the C# objects and workflows used to create resources, record GPU work, and present results. - -## Fundamentals - -Start here if you are new to Zenith.NET: - -1. [Runtime](fundamentals/runtime.md) introduces the graphics context, capabilities, queues, and object lifetime. -2. [Commands](fundamentals/commands.md) shows how to record and submit work. -3. [Synchronization](fundamentals/synchronization.md) explains barriers, texture transitions, and queue dependencies. -4. [Shaders](fundamentals/shaders.md) shows how to compile Slang entry points and create shader objects. -5. [Bindless Resources](fundamentals/bindless-resources.md) shows how shaders access resources through handles. -6. [Queries](fundamentals/queries.md) shows how to collect visibility results and measure GPU work. - -## Resources - -- [Heaps](resources/heaps.md) covers placed resources, allocation requirements, offsets, and lifetime. -- [Buffers](resources/buffers.md) covers creation, data transfer, mapping, and views. -- [Textures](resources/textures.md) covers creation, views, uploads, layouts, resolves, and samplers. - -## Workloads - -- [Rasterization](workloads/rasterization.md) covers graphics pipelines, render passes, and draw commands. -- [Compute](workloads/compute.md) covers compute pipelines and dispatch commands. -- [Ray Tracing](workloads/ray-tracing.md) covers acceleration structures and inline ray queries. -- [Mesh Shading](workloads/mesh-shading.md) covers mesh shading pipelines and dispatch commands. - -## Presentation - -- [Swap Chains](presentation/swap-chains.md) shows how to render to a window and present a frame. -- [Views](presentation/views.md) shows how to render through supported .NET UI controls. - -Follow the [Tutorials](../tutorials/index.md) to build complete examples. Use the [API Reference](../api/index.md) for exact types and signatures. diff --git a/documents/docs/presentation/swap-chains.md b/documents/docs/presentation/swap-chains.md deleted file mode 100644 index 6d3ff2f0..00000000 --- a/documents/docs/presentation/swap-chains.md +++ /dev/null @@ -1,58 +0,0 @@ -# Swap Chains - -A `Surface` identifies a window and its drawable size. `SwapChain.Drawable` returns the texture to render for the current frame. - -## Create a Surface - -Create the surface that matches the application's window system and native handles, such as `Surface.Win32(hwnd, width, height)`. - -Zenith.NET provides `Win32`, `Wayland`, `Xlib`, `Android`, and `Apple` surface factories. Select the factory that corresponds to the handles supplied by the window host. Use a [View integration](views.md) when a supported UI framework should manage the surface. - -## Create a Swap Chain - -Create the swap chain from the same context used for rendering: - -```csharp -SwapChain swapChain = context.CreateSwapChain(new() -{ - Surface = surface, - Format = PixelFormat.B8G8R8A8UNorm -}); -``` - -The graphics pipeline color format must match the swap-chain format. - -## Render and Present - -Borrow a graphics command buffer for each frame, record the current drawable, and wait for the submission to complete before presentation: - -```csharp -CommandBuffer commandBuffer = context.GraphicsQueue.CommandBuffer(); - -commandBuffer.Transition(swapChain.Drawable, default, TextureLayout.Undefined, TextureLayout.ColorAttachment); -commandBuffer.BeginRenderPass([ColorAttachment.Clear(swapChain.Drawable, default)], null); - -commandBuffer.SetPipeline(pipeline); -commandBuffer.SetVertexBuffer(buffer, 0, 0); -commandBuffer.Draw(vertexCount, 1, 0, 0); - -commandBuffer.EndRenderPass(); -commandBuffer.Transition(swapChain.Drawable, default, TextureLayout.ColorAttachment, TextureLayout.Present); - -commandBuffer.Submit().Wait(); -swapChain.Present(); -``` - -Wait for the graphics submission before calling `Present()`. Do not dispose or retain the command buffer or drawable; borrow both again for the next frame. - -## Resize - -Skip rendering while either dimension is zero. Dispose and recreate application-owned size-dependent textures, then call `swapChain.Resize(width, height)` before rendering again. - -Recreate a pipeline only when its attachment formats or sample count change. - -## Refresh a Surface - -If the window system replaces its surface handle, create a new `Surface` and pass it to `swapChain.Refresh(...)`. - -Use `Resize` when only the dimensions change. Use `Refresh` when the handle or surface type changes. diff --git a/documents/docs/presentation/views.md b/documents/docs/presentation/views.md deleted file mode 100644 index ddebbb14..00000000 --- a/documents/docs/presentation/views.md +++ /dev/null @@ -1,48 +0,0 @@ -# Views - -Zenith.NET provides controls for supported .NET UI frameworks. Each control implements `IZenithView` and manages its own frame presentation. - -## Framework Packages - -| Package | Framework | -|---|---| -| `Zenith.NET.Views.WinForms` | Windows Forms | -| `Zenith.NET.Views.WPF` | WPF | -| `Zenith.NET.Views.WinUI` | WinUI 3 and Uno | -| `Zenith.NET.Views.Maui` | .NET MAUI | -| `Zenith.NET.Views.Avalonia` | Avalonia | - -Add the package for the framework used by the application. - -## Connect a View - -Assign a `GraphicsContext`, then subscribe to updates and rendering: - -```csharp -view.GraphicsContext = context; - -view.RenderRequested += (_, args) => -{ - args.CommandBuffer.BeginRenderPass([ColorAttachment.Clear(args.Drawable, default)], null); - - args.CommandBuffer.SetPipeline(pipeline); - args.CommandBuffer.Draw(vertexCount, 1, 0, 0); - - args.CommandBuffer.EndRenderPass(); -}; -``` - -Both event argument types provide `DeltaSeconds` and `TotalSeconds`. `RenderEventArgs` also provides the current `CommandBuffer` and `Drawable`. - -## Follow the Callback Contract - -The command buffer and drawable are borrowed for the duration of the synchronous `RenderRequested` callback. Within the callback: - -- Record commands into `args.CommandBuffer`. -- Treat `args.Drawable` as a `ColorAttachment`. -- End every render pass before returning. -- Do not submit, wait, dispose, or retain either object. - -The View completes and presents the frame after the callback returns. Dispose application-owned pipelines and resources separately, and keep the assigned context alive until the control has released its rendering resources. - -For graphics API selection, see [Runtime](../fundamentals/runtime.md). Use [Swap Chains](swap-chains.md) when the application manages a window without a View integration. diff --git a/documents/docs/resources/buffers.md b/documents/docs/resources/buffers.md deleted file mode 100644 index 3b8a43d1..00000000 --- a/documents/docs/resources/buffers.md +++ /dev/null @@ -1,72 +0,0 @@ -# Buffers - -Buffers store linear data such as vertices, indices, constants, structured records, and indirect arguments. A `BufferDesc` defines the byte size, structured-element stride, permitted uses, and residency. - -## Create a Standalone Buffer - -When explicit heap placement is unnecessary, define the buffer properties and create it directly from the context: - -```csharp -BufferDesc desc = new() -{ - SizeInBytes = sizeof(Element) * count, - StrideInBytes = 0, - Usages = BufferUsages.Vertex | BufferUsages.TransferDst, - Residency = MemoryResidency.GpuOnly -}; - -Buffer buffer = context.CreateBuffer(desc); -``` - -Set `Usages` to every operation the buffer must support and select its CPU access with `Residency`. - -`StrideInBytes` describes structured elements. Use zero for unstructured data. - -## Choose Memory Residency - -| Residency | CPU access | Typical use | -|-----------|------------|-------------| -| `GpuOnly` | Not mappable | Persistent GPU data | -| `CpuReadOnly` | Read through `Map()` | Readback data | -| `CpuWriteOnly` | Write through `Map()` | Frequently updated constants and staging data | - -Prefer `GpuOnly` unless CPU access is part of the buffer's regular use. - -## Upload and Download - -`Buffer.Upload` copies data into a buffer and completes before returning: - -```csharp -buffer.Upload(0, new() -{ - Pointer = data, - SizeInBytes = sizeof(Element) * count -}); -``` - -`Buffer.Download` follows the same pattern and writes into caller-provided memory before returning. - -Use command-buffer transfers to batch several operations: - -```csharp -CommandBuffer commandBuffer = context.TransferQueue.CommandBuffer(); -commandBuffer.Upload(buffer, 0, data); - -TimelineValue timelineValue = commandBuffer.Submit(); -``` - -Record additional transfers before `Submit()` to include them in the same submission. Pass `timelineValue` to a submission that consumes the buffers. For `CommandBuffer.Download`, keep the destination memory valid until the submission's `TimelineValue` has been waited on. - -## Map CPU-Visible Memory - -Map only buffers created with `CpuReadOnly` or `CpuWriteOnly` residency. Pair each `Map()` with `Unmap()`, and use mapping for repeated CPU access. Use `Upload` or `Download` for individual transfers. - -## Create a View - -A `BufferView` selects a byte range and structured element stride. Use `sizeof(T)` for the stride and derive the selected byte range from the element count. - -Use `BufferViewDesc.Constant`, `StorageReadOnly`, or `StorageReadWrite` to match the intended shader access. See [Bindless Resources](../fundamentals/bindless-resources.md) for shader declarations. - -See [Heaps](heaps.md) for allocation requirements and explicit buffer placement. - -Buffer views depend on their source buffer. Keep buffers and views alive until all submissions that use them have completed. Use a [memory barrier](../fundamentals/synchronization.md#add-a-memory-barrier) when later GPU work consumes buffer data written earlier in the same command stream. diff --git a/documents/docs/resources/heaps.md b/documents/docs/resources/heaps.md deleted file mode 100644 index 0b101976..00000000 --- a/documents/docs/resources/heaps.md +++ /dev/null @@ -1,82 +0,0 @@ -# Heaps - -A `Heap` is an explicit memory allocation. Create placed buffers and textures from it with `Heap.CreateBuffer` and `Heap.CreateTexture`, supplying each resource's byte offset. Use a heap when several compatible resources should share an allocation or when the application needs to control resource placement. - -## Query Requirements - -Define every resource description explicitly and query it before sizing the heap. The returned `SizeInBytes` is the allocation space required by the resource, and `AlignmentInBytes` is the required alignment of its offset in the heap. - -## Place Buffers - -Define the buffer description, query its requirements, then create a compatible heap and place the buffer. Offset zero satisfies the first resource's alignment requirement: - -```csharp -BufferDesc desc = new() -{ - SizeInBytes = sizeof(Element) * count, - StrideInBytes = 0, - Usages = BufferUsages.Vertex | BufferUsages.TransferDst, - Residency = MemoryResidency.GpuOnly -}; - -SizeAndAlignment sizeAndAlignment = context.GetSizeAndAlignment(desc); - -Heap heap = context.CreateHeap(HeapDesc.GpuOnly(sizeAndAlignment.SizeInBytes)); -Buffer buffer = heap.CreateBuffer(0, desc); -``` - -Only add another description and requirement query when placing another resource. Align each later offset to that resource's `AlignmentInBytes`, and size the heap through the final resource. - -Use the `SizeInBytes` and `AlignmentInBytes` returned by `GetSizeAndAlignment` when calculating offsets and heap size. Do not substitute `BufferDesc.SizeInBytes` for the returned `SizeInBytes`. - -## Place Textures - -Define the texture description, query its requirements, then create a compatible heap and place the texture. Offset zero satisfies the first resource's alignment requirement: - -```csharp -TextureDesc desc = new() -{ - Type = TextureType.Texture2D, - Format = PixelFormat.R8G8B8A8UNorm, - Width = width, - Height = height, - Depth = 1, - MipLevels = mipLevels, - ArrayLayers = 1, - SampleCount = SampleCount.Count1, - Usages = TextureUsages.Sampled | TextureUsages.TransferDst -}; - -SizeAndAlignment sizeAndAlignment = context.GetSizeAndAlignment(desc); - -Heap heap = context.CreateHeap(HeapDesc.GpuOnly(sizeAndAlignment.SizeInBytes)); -Texture texture = heap.CreateTexture(0, desc); -``` - -For multiple textures, align each offset to that texture's `AlignmentInBytes`. Set `HeapDesc.SizeInBytes` to at least the maximum `offset + SizeInBytes` of all placed resources. - -## Match Residency - -For a placed buffer, use the same residency in its `BufferDesc` and the containing `HeapDesc`: - -| Heap helper | Resource residency | -|-------------|--------------------| -| `HeapDesc.GpuOnly` | `MemoryResidency.GpuOnly` | -| `HeapDesc.CpuReadOnly` | `MemoryResidency.CpuReadOnly` | -| `HeapDesc.CpuWriteOnly` | `MemoryResidency.CpuWriteOnly` | - -Create texture heaps with `HeapDesc.GpuOnly`. Query each exact resource description on the context that creates the heap, use its returned size and alignment, and keep every resource range within `HeapDesc.SizeInBytes`. - -A heap does not add usages to a resource or replace required texture transitions and memory barriers. - -## Create Standalone Resources - -When explicit placement is unnecessary, create a standalone buffer or texture directly from the context. - -Standalone resources use the same descriptions, usages, layouts, and synchronization rules, but do not require a `Heap`. Continue with [Buffers](buffers.md) and [Textures](textures.md) for resource-specific workflows. - -## Manage Lifetime - -Placed resources use memory owned by the heap. After rendering has stopped using them, dispose every placed buffer and texture before disposing the heap. - -`ResourceHandle` does not own its resource. Keep each placed resource, and any explicit view used to obtain a stored handle, alive through the final submission that uses the handle. Dispose explicit views before their source resources, and update constant data when replacing a stored handle. diff --git a/documents/docs/resources/textures.md b/documents/docs/resources/textures.md deleted file mode 100644 index 42970d39..00000000 --- a/documents/docs/resources/textures.md +++ /dev/null @@ -1,91 +0,0 @@ -# Textures - -Textures store formatted one-, two-, or three-dimensional data. A `TextureDesc` defines the shape, format, sample count, and permitted uses. Each texture subresource has a layout supplied by the application when recording commands. - -## Create a Standalone Texture - -When explicit heap placement is unnecessary, create a standalone texture from the context: - -```csharp -TextureDesc desc = new() -{ - Type = TextureType.Texture2D, - Format = PixelFormat.R8G8B8A8UNorm, - Width = width, - Height = height, - Depth = 1, - MipLevels = mipLevels, - ArrayLayers = 1, - SampleCount = SampleCount.Count1, - Usages = TextureUsages.Sampled | TextureUsages.TransferDst -}; - -Texture texture = context.CreateTexture(desc); -``` - -Other dimensional helpers include `Texture1D`, `Texture3D`, and `TextureCube`. They create sampled textures with `TransferDst` usage. Attachment helpers create sampled color or depth/stencil render targets. - -Add usages to the description before creation when a texture needs another role. For example, add `TextureUsages.Storage` before creating a storage texture. - -Usage declares what the texture may do. Layout describes how one subresource is used by recorded commands. - -## Create Attachments - -Use `TextureDesc.ColorAttachment` and `TextureDesc.DepthStencilAttachment` for render targets. Transition each attachment to its matching layout before beginning a render pass. - -## Upload Texture Data - -Provide the source pointer together with row and slice strides: - -```csharp -texture.Upload(default, TextureLayout.Undefined, TextureLayout.Sampled, default, extent, data); -``` - -`Texture.Upload` completes before returning. Supply the known current layout and required final layout; on return, the uploaded subresource is in that final layout. - -Use `CommandBuffer.Upload` with explicit transitions when several transfers should share one submission. - -## Load an Image - -`Zenith.NET.Extensions.ImageSharp` loads an image into a sampled texture with `LoadTextureFromFile` or `LoadTextureFromStream`. - -Enable `generateMipMaps` when the texture should contain a complete mip chain. - -## Select a Subresource - -A `TextureSubresource` selects one mip level and array layer. Use `default` for mip level zero and array layer zero, or initialize both fields for another subresource. - -Track the current layout of every subresource used by the application. See [Synchronization](../fundamentals/synchronization.md#transition-a-texture) for layout rules. - -## Create a Texture View - -A `TextureView` selects a type, format, mip range, or array range. Create it from the context with the matching `TextureViewDesc` helper. - -The selected range and format must be compatible with the source texture. Views do not own their source texture. - -## Create a Sampler - -Samplers define filtering and addressing independently from textures. Use a `SamplerDesc` preset when it matches the required behavior. - -Other presets include `LinearClamp`, `PointWrap`, `PointClamp`, and `Anisotropic(maxAnisotropy)`. Create a custom `SamplerDesc` for comparison sampling, border colors, or a specific LOD range. - -Pass `sampler.Handle` beside the sampled texture handle and declare matching `DescriptorHandle` and `DescriptorHandle` fields in Slang. - -## Resolve and Read Back - -Resolve a multisampled texture into a compatible single-sampled texture: - -```csharp -commandBuffer.Transition(texture, default, TextureLayout.ColorAttachment, TextureLayout.ResolveSrc); -commandBuffer.Transition(nextTexture, default, TextureLayout.Undefined, TextureLayout.ResolveDst); - -commandBuffer.ResolveTexture(texture, default, nextTexture, default); -``` - -Create resolve and download sources with `TextureUsages.TransferSrc`. Resolve destinations require `TextureUsages.TransferDst`. - -Texture copy, resolve, and command-buffer upload or download operations do not insert layout transitions. `Texture.Download` is the synchronous convenience path and performs its declared current-to-final transitions; use `CommandBuffer.Download` with explicit transitions when readback belongs to a larger submission. - -See [Heaps](heaps.md) for allocation requirements and explicit texture placement. - -Keep a texture alive while any view, handle, or submitted command refers to it. When replacing a size-dependent texture, recreate its views and update constant data that stores its handles. diff --git a/documents/docs/toc.yml b/documents/docs/toc.yml deleted file mode 100644 index 66e7d6be..00000000 --- a/documents/docs/toc.yml +++ /dev/null @@ -1,44 +0,0 @@ -- name: RHI Guide - href: index.md - -- name: Fundamentals - items: - - name: Runtime - href: fundamentals/runtime.md - - name: Commands - href: fundamentals/commands.md - - name: Synchronization - href: fundamentals/synchronization.md - - name: Shaders - href: fundamentals/shaders.md - - name: Bindless Resources - href: fundamentals/bindless-resources.md - - name: Queries - href: fundamentals/queries.md - -- name: Resources - items: - - name: Heaps - href: resources/heaps.md - - name: Buffers - href: resources/buffers.md - - name: Textures - href: resources/textures.md - -- name: Workloads - items: - - name: Rasterization - href: workloads/rasterization.md - - name: Compute - href: workloads/compute.md - - name: Ray Tracing - href: workloads/ray-tracing.md - - name: Mesh Shading - href: workloads/mesh-shading.md - -- name: Presentation - items: - - name: Swap Chains - href: presentation/swap-chains.md - - name: Views - href: presentation/views.md diff --git a/documents/docs/workloads/compute.md b/documents/docs/workloads/compute.md deleted file mode 100644 index a90138fe..00000000 --- a/documents/docs/workloads/compute.md +++ /dev/null @@ -1,48 +0,0 @@ -# Compute - -Compute pipelines process data outside a render pass. Record compute work on the compute or graphics queue according to the surrounding workload. - -## Create a Compute Pipeline - -Define a Slang compute entry point and its thread-group size: - -```slang -[shader("compute")] -[numthreads(16, 16, 1)] -void CSMain(uint3 dispatchThreadID : SV_DispatchThreadID) -{ - // Process one element or pixel. -} -``` - -Compile the entry point and create its `Shader` as described in [Shaders](../fundamentals/shaders.md), then create the pipeline: - -```csharp -ComputePipeline pipeline = context.CreateComputePipeline(new() { ComputeShader = shader }); -``` - -## Dispatch Work - -Calculate group counts from the workload dimensions and the shader's `[numthreads]` values, rounding each dimension up to a complete group. - -Bind the pipeline and constants, then dispatch: - -```csharp -CommandBuffer commandBuffer = context.ComputeQueue.CommandBuffer(); - -commandBuffer.SetPipeline(pipeline); -commandBuffer.SetConstantBuffer(buffer, 0); -commandBuffer.Dispatch(groupCountX, groupCountY, 1); - -commandBuffer.Submit(); -``` - -Guard out-of-range threads in the shader when group counts round up the workload dimensions. - -## Dispatch Indirectly - -`DispatchIndirect` reads `GroupCountX`, `GroupCountY`, and `GroupCountZ` from an `IndirectDispatchArgs` record. - -Create the argument buffer with `BufferUsages.Indirect`. If earlier GPU work writes the arguments, also add the appropriate storage usage and record a barrier before dispatch. - -See [Bindless Resources](../fundamentals/bindless-resources.md) for passing buffers and textures to the shader. See [Synchronization](../fundamentals/synchronization.md) when a dispatch consumes or produces data for other GPU work. diff --git a/documents/docs/workloads/mesh-shading.md b/documents/docs/workloads/mesh-shading.md deleted file mode 100644 index f1a37286..00000000 --- a/documents/docs/workloads/mesh-shading.md +++ /dev/null @@ -1,53 +0,0 @@ -# Mesh Shading - -Mesh shading is an optional graphics path that uses mesh shader workgroups instead of vertex and index input. - -## Check Support - -Check `context.Capabilities.MeshShadingSupported` before creating a mesh shading pipeline. - -## Create the Pipeline - -Compile the mesh and fragment entry points for the active context. Compile a task entry point only when the workload uses a task stage. See [Shaders](../fundamentals/shaders.md) for the shared compilation workflow. - -Create a pipeline from a description whose attachment formats match the render pass: - -```csharp -MeshShadingPipelineDesc desc = new() -{ - TaskShader = null, - MeshShader = meshShader, - FragmentShader = fragmentShader, - PrimitiveTopology = PrimitiveTopology.TriangleList, - AttachmentFormats = attachmentFormats, - RenderState = renderState -}; - -MeshShadingPipeline pipeline = context.CreateMeshShadingPipeline(desc); -``` - -Set `TaskShader` to a compiled task entry point when the workload uses a task stage. - -## Dispatch Mesh Work - -Mesh dispatch runs inside a render pass: - -```csharp -commandBuffer.Transition(texture, default, TextureLayout.Undefined, TextureLayout.ColorAttachment); -commandBuffer.BeginRenderPass([ColorAttachment.Clear(texture, default)], null); - -commandBuffer.SetPipeline(pipeline); -commandBuffer.DispatchMesh(groupCountX, groupCountY, groupCountZ); - -commandBuffer.EndRenderPass(); -``` - -Without a task stage, the dispatch counts select mesh shader workgroups directly. When `TaskShader` is present, they select task shader workgroups, and each task workgroup determines how many mesh shader workgroups to launch. Each mesh shader workgroup determines how many vertices and primitives it emits. - -## Dispatch Indirectly - -`DispatchMeshIndirect` reads one or more `IndirectDispatchMeshArgs` records. Its counts follow the same task-versus-mesh workgroup interpretation as `DispatchMesh`. - -Create the argument buffer with `BufferUsages.Indirect`. If earlier GPU work writes the arguments, also add the matching storage usage and record a barrier before dispatch. - -See [Bindless Resources](../fundamentals/bindless-resources.md) for shader-visible mesh data and [Synchronization](../fundamentals/synchronization.md) when GPU work produces mesh data or indirect arguments. diff --git a/documents/docs/workloads/rasterization.md b/documents/docs/workloads/rasterization.md deleted file mode 100644 index 6565d1ea..00000000 --- a/documents/docs/workloads/rasterization.md +++ /dev/null @@ -1,68 +0,0 @@ -# Rasterization - -Rasterization draws vertices and indexed geometry into color and depth/stencil attachments. A graphics pipeline combines Slang shaders, vertex input, attachment formats, and render state. - -## Compile the Shaders - -Compile the vertex and fragment entry points for the active context with `ZenithCompiler`, then create both shaders from their descriptions. See [Shaders](../fundamentals/shaders.md) for compilation from files or source strings. - -## Create the Pipeline - -Define one `InputLayout` for each vertex-buffer slot. `Add` appends an element and updates the stream stride: - -```csharp -InputLayout inputLayout = new(); -inputLayout.Add(new() -{ - Format = ElementFormat.Float4, - Semantic = ElementSemantic.Position -}); -``` - -Add the remaining elements in the same order as the shader input. - -Create a pipeline from a description whose attachment formats match the render pass: - -```csharp -GraphicsPipelineDesc desc = new() -{ - VertexShader = vertexShader, - FragmentShader = fragmentShader, - InputLayouts = [inputLayout], - PrimitiveTopology = PrimitiveTopology.TriangleList, - AttachmentFormats = attachmentFormats, - RenderState = renderState -}; - -GraphicsPipeline pipeline = context.CreateGraphicsPipeline(desc); -``` - -Keep the input element order, semantics, and formats aligned with the Slang vertex input. - -## Draw in a Render Pass - -Transition the attachments, begin the pass, bind the pipeline state, and draw: - -```csharp -commandBuffer.Transition(texture, default, TextureLayout.Undefined, TextureLayout.ColorAttachment); -commandBuffer.BeginRenderPass([ColorAttachment.Clear(texture, default)], null); - -commandBuffer.SetPipeline(pipeline); -commandBuffer.Draw(vertexCount, 1, 0, 0); - -commandBuffer.EndRenderPass(); -``` - -Choose `Load`, `Clear`, or `DontCare` for each attachment according to whether previous contents are needed. `BeginRenderPass` initializes one viewport/scissor pair, independent of the color attachment count. Its dimensions come from the first color attachment's selected mip level, or the depth/stencil attachment's selected mip level when there are no color attachments. - -Set a smaller viewport and scissor after beginning the pass when rendering to only part of an attachment. To change the number of active viewports, set both arrays with matching counts before drawing. See [Commands](../fundamentals/commands.md#record-a-render-pass) for the count and device requirements. - -Use `Draw` for non-indexed geometry and `DrawIndexed` for indexed geometry. `DrawIndirect` and `DrawIndexedIndirect` read commands from a buffer created with `BufferUsages.Indirect`. - -## MRT and Viewports - -Multiple render targets (MRT) use fragment shader outputs `SV_Target0`, `SV_Target1`, and so on to write to color attachments at the corresponding indices. Keep the output indices aligned with both `AttachmentFormats.ColorFormats` and the `colorAttachments` array passed to `BeginRenderPass`. These outputs share the viewport transform and scissor selected for the primitive. Multiple color attachments do not require multiple viewports or scissors. - -Multiple viewports instead let different primitives select different viewport transforms and scissor rectangles. The pre-rasterization shader output `SV_ViewportArrayIndex` selects the viewport/scissor pair for a primitive, not a color attachment. Without this output, primitives use pair zero. Setting multiple viewports does not duplicate geometry or create additional render targets. - -See [Bindless Resources](../fundamentals/bindless-resources.md) for shader-visible resources and [Synchronization](../fundamentals/synchronization.md) when GPU work produces indirect arguments. diff --git a/documents/docs/workloads/ray-tracing.md b/documents/docs/workloads/ray-tracing.md deleted file mode 100644 index f8ef16f0..00000000 --- a/documents/docs/workloads/ray-tracing.md +++ /dev/null @@ -1,74 +0,0 @@ -# Ray Tracing - -Zenith.NET Ray Tracing uses bottom-level and top-level acceleration structures with inline Slang `RayQuery` operations. - -## Check Support - -Check `context.Capabilities.RayTracingSupported` before creating Ray Tracing resources. - -## Build a BLAS - -A bottom-level acceleration structure (BLAS) contains triangle or axis-aligned bounding-box geometry. Set `Geometries` and `BuildFlags` in its description, then record the build: - -```csharp -BottomLevelAccelerationStructureDesc desc = new() -{ - Geometries = geometries, - BuildFlags = AccelerationStructureBuildFlags.PreferFastTrace -}; - -BottomLevelAccelerationStructure resource = commandBuffer.BuildAccelerationStructure(desc); -``` - -Use `RayTracingGeometry.Aabbs` instead when the geometry is represented by bounding boxes. - -## Build a TLAS - -The top-level acceleration structure (TLAS) contains instances of existing BLAS objects. Set `Instances` and `BuildFlags` in its description, then record the build: - -```csharp -TopLevelAccelerationStructureDesc desc = new() -{ - Instances = instances, - BuildFlags = AccelerationStructureBuildFlags.PreferFastTrace -}; - -TopLevelAccelerationStructure resource = commandBuffer.BuildAccelerationStructure(desc); -``` - -Submit the build before tracing against the TLAS. Work submitted to the same queue remains ordered; when tracing on another queue, pass the build submission's `TimelineValue` to the tracing submission. - -Keep every referenced BLAS alive while the TLAS is in use. - -## Update an Acceleration Structure - -Set `AllowUpdate` on the initial build and every later in-place update, and pass the updated description to `UpdateAccelerationStructure`. - -Choose `PreferFastTrace`, `PreferFastBuild`, or `MinimizeMemory` according to how the structure is used. - -## Trace Rays in Slang - -Store the TLAS handle in constant data and declare the matching field as `DescriptorHandle` in Slang. - -For triangle geometry, initialize a `RayQuery`, trace it, and inspect the committed result: - -```slang -RayDesc ray; -ray.Origin = origin; -ray.Direction = direction; -ray.TMin = 0.001; -ray.TMax = 100000.0; - -RayQuery query; -query.TraceRayInline(*constants.Resource, RAY_FLAG_NONE, 0xFF, ray); - -while (query.Proceed()) -{ -} - -bool hit = query.CommittedStatus() != COMMITTED_NOTHING; -``` - -For procedural AABB geometry, handle each `CANDIDATE_PROCEDURAL_PRIMITIVE` during `Proceed()` and call `CommitProceduralPrimitiveHit` for an accepted intersection. - -See [Shaders](../fundamentals/shaders.md) for compiling the entry point and [Bindless Resources](../fundamentals/bindless-resources.md) for the C#/Slang handle contract. Use a [timeline dependency](../fundamentals/synchronization.md#order-work-across-queues) when building and tracing on different queues. diff --git a/documents/images/Zenith.NET-Logo.png b/documents/images/Zenith.NET-Logo.png index 7cc4a058482407a9017c238b2089423b67a5ed95..9cff01b8b13bb97d21c8c1eb676f00adb3bc0a06 100644 GIT binary patch literal 6576 zcmY*-2{_bW)c;fzvXvzvLXo|Qu?&h3vTxaj$dbvvjlG8KOZM!MUC3^%O<{^`iLs8c z4h?238M3`!{ht5-dEf8z%zS6=y=T4WoO|vkT2Duvj)t8E1Om}%Jbq*V0-f6je!rr+ z2z=wk0v&-Dwfkc;FA#|J_Sxs0hQTco2z1?6#RQs9okXUm&laG%g^P^9W;@>kboxt>#-5o-tHR|+f9Qm zZ$+Lg?L|8HUznH5vuWwOM$5fR*-y!99?sx--NVcy)BpT@l4V3s4~t`g+Bp#DZd`J5 z@=k0}v0u`!4EXti-gf1#)d{3t!_bc_Ra5rStW}adEL9TS_NFB~g%lZd8Ty1hvm}Yd zx-mLcS)IPwzIDHV-Bx#aG{Twd`leiBl3qJR5_Ll1bU$9 z5!nAX;KK6QB(jIG?O`Flu5|0Kf@)V6VCSXrYp_mwv!Anqxtv6^>-qU)!+Stw4H)NkVB>(=bVKAE(1%gZO})v zs5#QUc#-oU4z_qX9E11oxK`ME9t6_s*`Pl~^dwCRa`Q_0dw&yqpB@CatHvB^{jxkG zPR@gRUi9n#uJ)58v)(8e6Z6_k_!X zK<=_Z>$!d+Duh{wDtK$j#5*9KEp_r_xm!8<7uJz4t0%ZynWQ*DAWoXb-EM1IvhbC)+&V^4j6Q>`?SWp2;^-9#71m114`h~%K zC3S~Kr|+}fyv5De3^D<0oJ5W}*&#c56mbT*Q)t!Z zt1YE9yhYmsR=8J|b@GzDIeVd;Q&{kKxky)WKGAiqQvp+EH`VUHBP)bC5;qZc6k1ed z|Gk}Celp`S-DFk0hm`kSZ@C!_D?pPEvzQX2Pd08#&W5JiwWB-`csBTHn1)8)=xnul zhe^8<@xsWd_+`2->(cqwUqp&&ByHcO5{1~@JWb#i>D8sahRizv+wWjA(ymi}HG zGgt6?zx?CJBd}1L>_F-ZzS;d6$%U4Rii(hO&yKEIbF0q0@J`LxuHQD5BKpv3m5q1ZD{OI4rXJ_6SRU4fEH0HXcMVi}H$^?AndC zC@EN1I0zn%VbW09GP3(*{hlf9_4Uskcy zbyQ){9JJYfIK6PYzsP4`Cy(r#`;StnZJFKmr1>GKl?GZ=SILEl#QDTtiiEHxS>Io2 zSF&z~Y>JvYMj>}tA9DnTI(Of(5NLgk+c=jttwXnb*pg1JsIFE_LBp~y|202iMqn)S z8GcS2)bPNmum%V`99K}F=u~nz&QJ_4R`1FPp>UH$aj-xLP*zCjdzS!5_4P}-v$b7?G{@oewR&GOx}rnU zl`++i97l#=C6^4~e6Ax#)IyIut>Wi@a4W?iL7ZG6;#EcaWSRqi=GgL znwD{)K~iDB^fmF@AiH*wMBGib{Dbp466($Vl1L<_y$T8E@OB`fR_a|iA+plA`M zeHD`8r?CbmeqOTd#wN~)(m5sdt;{~y3gCwJ50s(y+4KuU?oc7^&3cESq%7{aXaqi6 zDH!Q|-`lt|yMm*ku76xcRPvARs;teHpY9UdDlw#B`(#Hq=(snYLwC{D?C-1z9lH1W z+Q|d(;^~w3Gj=Pge#bJhgZ+X~CCl88xaOCWo^r>B7j}u$_fyB{#Z2YMr*|`P0zZdD zit~B`^nTN!R7eTTN6Vt4Jr-_5$^3qUR&y0r>1%`2eF!{9Rh@D9RJ^}JDMWj3=P5!H zR?b5$X#CRy|Ltmf@?$6M^XSHC*Cwl+TX4BK+C2Bn&v@53GP~wx;c4Y|tAt z%Hig$F>lu$n<=m63LMhHSPLVg`bPL*w-u=oQ;%dTE$)ZL;xt}n6tA+u4xaT6B1(5) zNkub>=x0KazWh$8A-VZRGHhRm`2ny!d=#O?_mNq%#bRdkH{?Y6`U2nmJ*v6`Zxy6y zcv7)=|E(bWty2o`_50aa2};Ci)IvWqSIY0H7nL;7%#2S$Z;*qg+Y}0679?U@$U9|t zt~nP~Ug{}4{Zhbk<{-u*=2TF9GK{p^+@9RA!hh)oL z%4I7c+GqIB>>juSPUH->O!EP)^->eO~;1K6zva+MY?-Gaxb{)4J8A*@#=K-#I|d zFAd)fJ4QK$s-uSm%uvD@_s%+bY$Liq#<9eZb9kRCpJN7bDx*0YtiIer@E^L!LF6aX zQxNq~m$Zbto98w&q&Elc{+bA0uB3uy8iB1ATb!nueFnh2e>u5?q83rl)BCgo;4u_k z;pj!H0r4&QM5v@{f8dtqXCoRcEdi$+qgsp2UV-Ke!RDp*zF6A6$0@~cgRgA`(KKEP zd+PPzEbcr@SOkTVlukvMqBwE0bJm@W;TX}7@8=Jg8I7553kx}%MlndFR zFW>T$yMlLXokrxC5MU>R8yyahVtNnEuKu~F=%|JuPD7U=uA0gusj;!KuAc!Sknnstn$9e1{Lju9gvEBG@o(&%3zS{mV?iZ7jY8;-8swJq+0pl;LA#$-SkW5LKL^`n zrIxVV*RzgDv@@7JG8%9&>4n<`o1kyGjuU&}bL6WmK_A6V*zmH@cf+JWha8hIt*g+}THK=X9%hy7JBvzN22+CVpLQTOtP2z;|{T&CQWskzPot`aQV z>*%7f-QgD1cu`?WTR9fDrk0)gS-VoVJ*9d5CVW#v1J`QBJ@mx4o(j4c#%WEsd3M-I zP;TsAmn{CCD?l(q=KK)am+4i6$tu8N+{&iyg0N3aJvF?38a*EuyMi(#A7xTE;N)-1 z${q2+~PYUu;!O*$lTXe^y!nI zDJZ&bj~vkHFhTH--)`M~?u!y8N~*iK97SvK$=crojLw$WM3P@eh1=gdioVkHF5gBP z1IGsn#QJ@5xxq%}pG$~>X|wx8q?~aKzh*r;cSC-Nlfo$I(s)V*n3DV}vQT zCQOsvA)(EwbkTt`>k=nUItRHBnA&<6F1%* zf`G^OJi(eIbAhoD*hOSq_E^`W<%w2)5{{Jp6l{q7z-hIsZ$XmvWo$Pf&XrE6)`oF2 zug%B-3NO#Nh5-&7rD*62zWO=U|i{+;Z-gW{fh5~+wU!y+*AhYGZa<|tesc|+hgfl&NCc(&E; zks2C;{x%ET?1ZUK!Uv>(OSS8=bPQeI-BIhz+;NcYgA#PhH@HeUzuwbHB6x0!{8eXa z4;f>tO){hpLKmIg|M@4Pj`#5+h8QY~c-CviZI6P-eD z&5s#bLCh5taD_NG;QSG#=DJL0feDG}D7MvYY-et`#K08;c_5>`$=KeCOXFDAi$>p7 zocbvvKn;~e`vWJzv1?^Sz<$yQ!Ze{VDlqjdH#2a%pR%Q0()q~|5fR@uy>wFLDQdJy zeI5*tpT|j zW_)W3fw(qyp_R9XVMg4HBi5nmMw#ZvKDQ($(I{@s}|;e?Z?~Zsz9P`bezj`3k;;qqEAH0 zzD0$d?th_B_R^P&hhaleO%Yk-d!~YwgVo)wRiSz72SQp$YQi1Nmt`w?h|sdze&Jm9 zH*TkSzn&rsj9=AngcYa{|LMH-=I~+nk%;J57e+`A%&bc6Ue_-my<`@|nOTK1O)j`xOpA zmSogPDqPpaj5o8JU$W$S#`q+y0QZk91$ykcA(7D}u7!FGq8wYj^S{hzzu$+@UKPgkU10QjflvUlIo zx?yNSz7?5TV^p_;;`K+*fj&QjUs#U(vnsX{E*?l8|NL9vQ;M%Za;{HeO_eyCV)#Ft z>njtj=~|l0#u%pL%WoQsW>+Rx>r62Q6RgdF*gwq2^0H!kiO->k6~!EImfw}HeR+WA z6)t_8A%TYxsKft5n!diD*{Gj#Tv_Gi;Bv!$dX{3>gPoYT(+fE)tUg#9m0R)*Icfe+ zCq07ebM)YwR%*x9PXadt{d8Uj8k4cD0?2t7VJ}_r|D$gK#?S(5@VvX*>-F|s2ivjV zjY(F!ao=pvN!HAau6}pp{)6dSS{6ipe{uN*)0Rf}Gg&u!fP+$=*6$I%$+C~wD)~PS zuMxGj`)9~a015PHi{qT_PQlj3Qkh!9Dye)3S6+w`q@L+(k);0YtK=6%0I->g;C31| zErlo*|BkUddgeTLd{-p#0UfY$kp>0^o}B`Wa<)r(%TY!(p+k(=2W4Uc0&x0&5F?x4 z&HMT_jgwRdD9q0dagM})&}QkKry=*^G1Bi@+!Dv-t+n#Sy{Vn00l?{6u}-jHTP#O% z1Dqt~eW?%nC>}sK8F|>&{ps-~;L#`UkAg<{t5R^Vs9HZ@z0&({hEt{AM#nyNi$pE? zCJ67P)0ne(h&oFElco*Seov(x2kbrW?o;mR97dYQ)=(kf3FfNhdS&Vm9ogn z$nax#z6)fV!xmg<@DF8c)!JJt(CaM7KD)m37av9I9?G&al-}t3PJs9>$?R?0yS$)&qURSTr1f+J$QrtkKnBZQ94$f*7F7l4d)zxk<7oJmy zt6P#-u3NU6hcB{W#X(X)Uc7P@{c9V#s^j+lNU~Y!*E=9?ZpdGYX`n|U46#j4xzXSK zg;JJV;#xko{AgKkp+$<6_ncfO;u9L`0c~hq#|{TYwo`q)0QeSuem)b(2s zG_RxBFSW##wVQZk>Q5?c_+I*InO>$35dGiBCg6m6fVI+b2d(S=R+|L_rsINgs!$|`If#|d}9~px{mx#dc zS5y?h_p)S=6L6#U)U@ycf!G8uK9{tNZxTQt&SI@cDvx2mH!~?evY0k?bA_l()jJ+3 z&NR_SP){iqmAFzw+C@fZ7DT0OVHs5nM@tP@s);PDSlO>ic-hz+LRN-GWP-)(oZoXl zkg*%xq(UGbIYl-fmAF`8QRQofIVI<9KCJ@FR8yw)9y7L6`_@sH0agB=%PhC5YL$q5 z@F%VH88Kn{84TH`RP~EJ<|Xx;8_Hx4`>!yH-B32{*{ItrkWq8p&K$5m$csdBN4qHdTVm! zzY=4Ilx#zWhWz|;UJgS5<&g(tEeCVd(+^B6T>>SxLvjPk{R}xwEKJh&U^I$wpoUA= zI+Sz10(xFontRnAthxXAFt|0;t*m0lYFHB}7cqMJ+uQd#OK9#W-W(+s`SKkdoMK;m z?Nl#`wq@EjClVN-<|ibwm9$zxFO?tYFPFs~GOv>;&nn0SWHT>`|f zuxPp7i;P?x^ud*)AawX4IQ8%|KQ~fjTE?G{kDY zWJ^l3Py3aYL$AdluYf>bclK_|)!=w6=k5m4@@yta9USXFdIwnD&%vN&jy2&#nn!8l zMx)(*Fq%29!a+d%!sPBp8di?A(!`y3+SZZf_4EiN9S9`X&HfUeqJKC1dRcXGtK`^Q z@&FKMw(@vVA@fP(baNMc=QM5p87BzjITpAWOyqnSTfJ1**z}AjI_wDoRf=HH^{)na zqga>|8l^vrfcEt#UEd(fYp99Y9QzW^ zGf=2J=@he`=d?x_IUy>R9>OSPH@Xhx4o6-E zfex8ZeRIh6ws#(G7-1>s8$T(YuH38h-;^(4``fH$4DG1M%#s1K%JP6fFDVS%n(oe+ zxE8CqncIS`P~EN2jmu44S$yy~MI{eNkp1M)MwgaUbz1duRYYt`<-2sb>c^i58;?3n z@ZMOde}iZ~m{m=bC`T}<3U*4b^mtEIdNEgXZf z%u&5G;MFW(SO~m$dE2U4AFj5ey>^DX={Sv zV%M%yq3l;Gxfa|V{GDcJY5&&|Bjn}`cCwyCg9RKxWy-8bdE=I&B{Vb7=TDINU-4VS zjEr{as;TyyLvM7hMccx?ADfw->(uFB;_-PePTNj=Cfkq3J$C5Mmud3Ki?Xw4-@tGR z-Gb-$hkEZ%tll>-;$3d)EctcT(%9J5s6CUOym()5+$l%rUPLv$OPJNXNr7wFg8XXZ zSAPV$Ve6Zv@drqLvvsRIYr5=-#9@19&u)wQs-_(flB^tX^D$+^8aW{eJZ zNiJ`_V`EH24UH1cqyY9TS!d<)a&n=n>KPJessMg>qoof-@pYeMYzdruDw%^s}k55GrU%1L@GJ{wI~S!iT47xIU==tws1NXlnDl zORrT3E^H7f65UjjR(F~WL2@ooV&e5AWH4;yd(yodML2I-laGDY4d67~(!>JtI_&bF zDzWmxmj>slwqv|scbG|hp0>g&_8JrQM3HSYl93*v72L!Cd`c{OsMnAQP)Bf z%$Oi&Ux%;s@3FtaHLF(*RRz{lM!U~#{CDlTjOF8i<&_{kp9(WZjJIR$ z%Dfc%+G}Hem>4yR_LMfi6cPQApA0Zhxi=rY>t2r2^e>!`G5^u?Ycpej*hX-EKK}No z{>NvfnXH5Dnr!iIiK$LB1?msos?0gh_V-oN#V!1vEI++_UN(A87uE_q{-|dKU zxbfNw>!t&fbWlpKz8r?QDhI1}0|0n9vx=6m(GQ zg6zrk#xDnH>jliDiNjo-R|}0<#g_1oOi%^FhgG&F&}jWF?VKOS2il8IsZmVSJL{Hd zosdoW^XqW7L_$Z&B%Od~UfP+~ z9u%}3>9Pj$u*t~D zu)n2K<6AcpsL7N!ot(%f3yJC9lZyFaRMTvTw(|l@1;u#wT|wadX`GzcSpswd8m0tEmNXaT6>g_IA8r*vBcmplXB_4$2ZVRKDEUq|&E$+@6#7@4v@M>$pKbQtkTAa^gYuo--j|v(;Tt+}(+^&_Jsa zFmpB!_I5I**u?KglUkyS;RV48&*aIWF(HJglw%AmD>F$TQ#WXCga;?;2d<^pNwTT4c{z#dd4A6}cb-MkRKQm;l$6Z%w$VqWZ~;vr9xvmZ{vHe>%ih zh*}nbey%(|uGVI%JY@vW{WY&5`IfRw7=~;{x1r%OQAZ0do$7Pa+hC8kHda4f3e@T= zwe8?@%>zp%fI%xcleR(Nvv`R9(;OCPz z4s=ea^f7Pnvg)bV)}B@bF2h3$+x$j>2~{=cvrBVyf*dC!;U=keq$hcFKVAlmnIj#M z0>?l75_*O&ElmIm^nLq*K=ZpL$F7YUNr}1B6UZpz#suz3y{)HIG!w|tCIq5B zyxC5YGS>0kNns^35D=lptF;;{B_?k;GGdz8??3IAjJOD^0wzCOAuoy@z0qCpG%I}} zHcXS6pRX~S0S-AzF(TpdR{HaO*<@US+dER#ZeOQ}D_K_Z$e*#!3bmEwjWvQU+iB4U zUtRB>_+LJ4a9UJ>1F`y4eO2(7;2phG4@5E8-nXPbStGhzCx@F(mnkx{1{WR7uqD=y zQ&%o=Y8wu~BWyP1o{FaiQ)P)x8jx->O>Jlu#|5f`^KVL;F+VIK-yC9E~tC5B5iVFVq*NK9r*bv?RyUL3VD-E3flBSO814m z>^y5`w%`v#6uW;ZCa7(!O1k>qkCXF-xS(=sz~{@B0*ia>7d8{;wRr&UV;YSa3`qFW z`IoGk+QzRyUTL{VEygfE=gB6yRGjV&_A_}ZrP{sO&Fip0DCU<3=$z^O_dZF$VXpJ4 zN;bru5&t9r@#yr;vUqj#S6xIZ`$$m_^FUDPO+|_F*Yp9DS3-pD)cw84qvXl>`aJ`} zy?^n3$#Hlx^CuFRD-*T0YKrQq<^aI8H$q!Fj+)q239IPXrc%51>E~u~CCWEUisfK$ zL&bp}-2`Er2On^HhQb2BRV()606Vn76DT@1Cfp|gzx^vgIr(VFQsg+ng3RFfn`u6o zA8i}nmxbR}*i1e;*5;8+?6u>O3*)s$Y+r+?!aMakCUTTRC$ z=PGpMXB*lDqzMwKP53K_1XO7LJP|)2U6Q{UWo77ze5iWe36+!m@1rid+OzXsD>INp)iMNk7sF-8Z(M|{S1dKYG9@XKq04;Y5&;6_ z72ZbH3aKth)A)i6eY0TMh;M(lU@H{A$}Yq<#)^u1-*iScl$ zAM^Oiv;{jTX z-U+BDDDsTXYtEkfO;_R)+Q54-n#6RhpI3GtQNwIJW!;WwBgz_k_ zNx*pQS;(^Z5qyvZ`?@evX#YYh{9w7X!71N;!Q<_0zd6Nb<`IQj^wn9z9S+Ne&%AwJ z+U&*-`caF%8MTs=B`~;^26r|~}vT?PngAWhUi24eqtHV+@j4j2R% zQ%J|z_&}zzv(Qn0dYfIctcqn14dFhk6m{V}I78z1M>X zG&xFJK=0z5a#*+rt}2^xO+_3=@%i^iG59AbkX48io#}l(M|y|d9UZ-=K&|vt%F(i( zQmWkC>sx!XI<3<0*ow_-Mi)6658_uxx#dy5qc_yuJ=q|uI&YF6=7&fqm*GwM!Tkbb z7kD06zn8EzUm2L2ewBkIb70#cTrh|r>E$h&cMndZ^p`91Vr7s~V|fS(+b`PEjePe! zUrpT(e&fD)6J;^!_$1+`uoLvRw5v8Kq(S5!G@e+NC*8qzy{==dX}A5E?OKaj$D zn!P7!EZFsY9DqXW%AT6P6H3YsM8ef0PdnsK@H`FC&>;Dc#oK4DtrdcC! zbX=lHH>~ z`UZa4jY5L+3NC|QZNdqO$>a}bp7B8>*j$vd#Ib61HIB|L;3M)7cc9_ERyW7FMz5zFah8?r)|!uH`3n2igh0q z^1muplb%f_P5!Jt_{+7e`hO`Vq`FF|Fx}I+=D|8<-_ia!#&lN%uKv6-udukx$p$Kn z_@{nedHLc!r8g4=c+|@n^eqT<&W`9`=RM-ItH?R%pd76I1|^~B@ULh7^JmXn(G6DM z9ZkiPO3l9eDKVaHm%O1C738t52vm{OwQ~kpZUA9wyJzpL?TWU!biUCvc>I`>cp9{z z{XblLf$mS%I!@vs)!d0&XWLyrZ26`wZFuD`{c9OluLM!4Xc?#43`gaI$M$c!$^rB- z>eQ4C0~wPDZ0+yNc1r>J!<8EQ6X7YY7f9C z1c&5gz3x0A0RMYBON05gY}j9N8=!vFa5??1ym zK;Ft|UIlGr#V#HkwgN!%V%PP5FIoVIExcG(l1&!7$HLZU^zS8&(YO(ZvBfU$Nt7>2 z;nx7r(d`CvzI%0}_+cD?!T*#b=pIBN%?V@NRI=L(ScW?ew~`s9Di$9*Vm7w+;Hr$G jI>W+1m;e8DTag4ReLx%OR_o1wQKF@$|ET=oGsOP^d8%xr diff --git a/documents/images/Zenith.NET-Logo.svg b/documents/images/Zenith.NET-Logo.svg index 82fa23c9..38f0157c 100644 --- a/documents/images/Zenith.NET-Logo.svg +++ b/documents/images/Zenith.NET-Logo.svg @@ -1,11 +1,10 @@  Zenith.NET - A white Z on a solid graphite tile with a fine inner edge, paired with an outlined Zenith.NET wordmark. - + A white Z on a solid graphite tile with a fine inner edge, paired with a soft silver-white Zenith.NET wordmark for dark backgrounds. - + diff --git a/documents/index.md b/documents/index.md index 35b1819a..89af3af4 100644 --- a/documents/index.md +++ b/documents/index.md @@ -1,163 +1,66 @@ ---- -title: Zenith.NET - Modern RHI for .NET -description: A modern rendering hardware interface for .NET with one consistent C# API across DirectX 12, Metal 4, and Vulkan 1.4. +--- +title: Modern RHI for .NET +description: A consistent C# API for graphics and compute across DirectX, Metal, and Vulkan. _layout: landing +_disableToc: true +_disableAffix: true --- -
-
-
-
-

Zenith.NETModern RHI for .NET.

-

Build graphics and compute applications with one consistent C# API for resources, pipelines, commands, and presentation.

- -
- - DirectX 12 - Metal 4 - Vulkan 1.4 -
-
-
-
- Hello Triangle - 1 / 6 - - - - - - - -
- -
-
-
-
-
-
- THE RHI -

One model for rendering.Designed for modern C#.

-

Start with a small set of objects and use the same workflow across supported graphics APIs.

-
-
-
-
-

Consistent C# API

-

Create resources, pipelines, commands, and swap chains through a focused object model.

-
-
-
-

Clear command flow

-

Record work in order, submit it to a queue, and track completion with timeline values.

-
-
-
-

Simple shader binding

-

Pass compact resource handles in constant data and use them as typed Slang resources.

-
-
-
-

Modern workloads

-

Use rasterization, compute, and indirect commands, with capability-gated Ray Tracing and mesh shading.

-
-
-
-
-
- -
-
- -
- +
+ + +
+

Start building.

A first frame. A focused example. A closer look at the API.

+ +
diff --git a/documents/learn/concepts/execution-model.md b/documents/learn/concepts/execution-model.md new file mode 100644 index 00000000..41734934 --- /dev/null +++ b/documents/learn/concepts/execution-model.md @@ -0,0 +1,3 @@ +# Execution Model + + diff --git a/documents/learn/concepts/platform-integration.md b/documents/learn/concepts/platform-integration.md new file mode 100644 index 00000000..36918a16 --- /dev/null +++ b/documents/learn/concepts/platform-integration.md @@ -0,0 +1,3 @@ +# Platform Integration + + diff --git a/documents/learn/concepts/resource-management.md b/documents/learn/concepts/resource-management.md new file mode 100644 index 00000000..5f2be7dd --- /dev/null +++ b/documents/learn/concepts/resource-management.md @@ -0,0 +1,3 @@ +# Resource Management + + diff --git a/documents/learn/concepts/shader-data-and-binding.md b/documents/learn/concepts/shader-data-and-binding.md new file mode 100644 index 00000000..a9786f65 --- /dev/null +++ b/documents/learn/concepts/shader-data-and-binding.md @@ -0,0 +1,3 @@ +# Shader Data and Binding + + diff --git a/documents/learn/concepts/synchronization.md b/documents/learn/concepts/synchronization.md new file mode 100644 index 00000000..ebdc42f1 --- /dev/null +++ b/documents/learn/concepts/synchronization.md @@ -0,0 +1,3 @@ +# Synchronization + + diff --git a/documents/learn/first-triangle.md b/documents/learn/first-triangle.md new file mode 100644 index 00000000..14c768dc --- /dev/null +++ b/documents/learn/first-triangle.md @@ -0,0 +1,3 @@ +# First Triangle + + diff --git a/documents/learn/index.md b/documents/learn/index.md new file mode 100644 index 00000000..7f05a91b --- /dev/null +++ b/documents/learn/index.md @@ -0,0 +1,33 @@ +--- +title: Learn +description: Get started with Zenith.NET and explore its programming model. +_pageKind: hub +_disableAffix: true +--- + + diff --git a/documents/learn/samples.md b/documents/learn/samples.md new file mode 100644 index 00000000..289397ea --- /dev/null +++ b/documents/learn/samples.md @@ -0,0 +1,3 @@ +# Samples + + diff --git a/documents/learn/toc.yml b/documents/learn/toc.yml new file mode 100644 index 00000000..90f9b0fe --- /dev/null +++ b/documents/learn/toc.yml @@ -0,0 +1,22 @@ +- name: Learn + href: index.md + +- name: First Triangle + href: first-triangle.md + +- name: Samples + href: samples.md + +- name: Concepts + expanded: true + items: + - name: Execution Model + href: concepts/execution-model.md + - name: Resource Management + href: concepts/resource-management.md + - name: Shader Data and Binding + href: concepts/shader-data-and-binding.md + - name: Synchronization + href: concepts/synchronization.md + - name: Platform Integration + href: concepts/platform-integration.md diff --git a/documents/templates/ManagedReference.extension.js b/documents/templates/ManagedReference.extension.js index 64fa9aeb..8daed42e 100644 --- a/documents/templates/ManagedReference.extension.js +++ b/documents/templates/ManagedReference.extension.js @@ -1,10 +1,26 @@ exports.postTransform = function (model) { - if (!model.namespace?.uid || !model.namespace.specName) { - return model; + const labels = { + classes: 'Classes', structs: 'Structs', interfaces: 'Interfaces', enums: 'Enums', + delegates: 'Delegates', constructors: 'Constructors', fields: 'Fields', properties: 'Properties', + methods: 'Methods', events: 'Events', operators: 'Operators', eii: 'Explicit implementations' + }; + const kind = type => type ? type.charAt(0).toUpperCase() + type.slice(1) : 'Type'; + model.apiKind = kind(model.type); + model.apiName = model.name?.[0]?.value || model.uid; + model.apiHasMemberFinder = !model.isNamespace; + model.apiSeeAlsoId = 'seealso'; + model.apiHasRelationships = ['inheritance', 'implements', 'derivedClasses', 'inheritedMembers', 'extensionMethods'] + .some(key => Array.isArray(model[key]) && model[key].length > 0); + for (const group of model.children || []) { + group.apiTitle = model.isEnum ? 'Values' : labels[group.id] || group.id.replace(/[-_]/g, ' '); + for (const item of group.children || []) { + item.apiSeeAlsoId = item.id + '_seealso'; + } } - - for (const name of model.namespace.specName) { - name.value = `${model.namespace.uid}`; + if (model.namespace?.uid && model.namespace.specName) { + for (const name of model.namespace.specName) { + name.value = `${model.namespace.uid}`; + } } return model; diff --git a/documents/templates/ManagedReference.html.primary.tmpl b/documents/templates/ManagedReference.html.primary.tmpl new file mode 100644 index 00000000..214e0305 --- /dev/null +++ b/documents/templates/ManagedReference.html.primary.tmpl @@ -0,0 +1,7 @@ +{{!master(layout/_master.tmpl)}} +
+ {{>partials/api.header}} + {{#isNamespace}}{{>partials/api.namespace}}{{/isNamespace}} + {{#isEnum}}{{>partials/api.enum}}{{/isEnum}} + {{^isNamespace}}{{^isEnum}}{{>partials/api.type}}{{/isEnum}}{{/isNamespace}} +
diff --git a/documents/templates/layout/_master.tmpl b/documents/templates/layout/_master.tmpl new file mode 100644 index 00000000..dca7e3c2 --- /dev/null +++ b/documents/templates/layout/_master.tmpl @@ -0,0 +1,184 @@ +{{!Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license.}} +{{!include(/^public/.*/)}} +{{!include(favicon.ico)}} +{{!include(logo.svg)}} + + + + + + {{#redirect_url}} + + {{/redirect_url}} + {{^redirect_url}} + {{#title}}{{title}}{{/title}}{{^title}}{{>partials/title}}{{/title}} {{#_appTitle}}| {{_appTitle}} {{/_appTitle}} + + + {{#_description}}{{/_description}} + {{#description}}{{/description}} + + + {{#_apiReference}}{{/_apiReference}} + + + {{#_noindex}}{{/_noindex}} + {{#_enableSearch}}{{/_enableSearch}} + {{#_disableNewTab}}{{/_disableNewTab}} + {{#_disableTocFilter}}{{/_disableTocFilter}} + {{#docurl}}{{/docurl}} + + + + + + + + + + + + + + + + {{#_googleAnalyticsTagId}} + + + {{/_googleAnalyticsTagId}} + {{/redirect_url}} + + + {{^redirect_url}} + + + +
+ {{^_disableToc}} +
+
+
+
Contents
+ +
+
+ {{#_apiReference}} + + {{/_apiReference}} + {{^_apiReference}} + + {{/_apiReference}} +
+
+
+ {{/_disableToc}} + +
+ {{^_disableToc}} + {{#apiHasMemberFinder}}
{{/apiHasMemberFinder}} + + {{#apiHasMemberFinder}} + +
+ {{/apiHasMemberFinder}} + {{/_disableToc}} + +
+ {{!body}} +
+
+ + {{^_disableAffix}} +
+ +
+ {{/_disableAffix}} +
+ + {{#apiHasMemberFinder}} + +

Find a member

{{uid}}

+ +
+ +
+ {{/apiHasMemberFinder}} + + {{#_enableSearch}} + +

Search documentation

+ +
+

Search the docs, concepts, and API.

+ +
    + +
    + +
    + {{/_enableSearch}} + + + + {{/redirect_url}} + diff --git a/documents/templates/partials/api.enum.tmpl.partial b/documents/templates/partials/api.enum.tmpl.partial new file mode 100644 index 00000000..35ceece5 --- /dev/null +++ b/documents/templates/partials/api.enum.tmpl.partial @@ -0,0 +1,18 @@ +{{!Based on the .NET Foundation DocFX templates, licensed under the MIT license.}} +{{#children}} +
    +

    {{apiTitle}}

    +
    + {{#children}} +
    +

    {{syntax.content.0.value}}

    + {{#summary}}
    {{{summary}}}
    {{/summary}} + {{#remarks}}
    {{{remarks}}}
    {{/remarks}} +
    + {{/children}} +
    +
    +{{/children}} +{{#remarks}}

    Remarks

    {{{remarks}}}
    {{/remarks}} +{{#example.0}}

    Examples

    {{#example}}{{{.}}}{{/example}}
    {{/example.0}} +{{>partials/api.seealso}} diff --git a/documents/templates/partials/api.header.tmpl.partial b/documents/templates/partials/api.header.tmpl.partial new file mode 100644 index 00000000..9dab6aee --- /dev/null +++ b/documents/templates/partials/api.header.tmpl.partial @@ -0,0 +1,13 @@ +{{!Based on the .NET Foundation DocFX templates, licensed under the MIT license.}} +
    +
    {{apiKind}}{{#sourceurl}}Source{{/sourceurl}}
    +

    {{name.0.value}}

    + {{#namespace.uid}}
    {{{namespace.specName.0.value}}}{{#assemblies.0}}{{assemblies.0}}.dll{{/assemblies.0}}
    {{/namespace.uid}} + {{#summary}}
    {{{summary}}}
    {{/summary}} + {{#conceptual}}
    {{{conceptual}}}
    {{/conceptual}} +
    +{{#syntax.content.0.value}} +
    C# type declaration
    {{syntax.content.0.value}}
    +{{/syntax.content.0.value}} +{{#syntax}}{{>partials/api.signature}}{{/syntax}} +{{#apiHasRelationships}}{{>partials/api.relationships}}{{/apiHasRelationships}} diff --git a/documents/templates/partials/api.namespace.tmpl.partial b/documents/templates/partials/api.namespace.tmpl.partial new file mode 100644 index 00000000..aed72875 --- /dev/null +++ b/documents/templates/partials/api.namespace.tmpl.partial @@ -0,0 +1,13 @@ +{{!Based on the .NET Foundation DocFX templates, licensed under the MIT license.}} +{{#children}} +
    +

    {{apiTitle}}

    +
    + {{#children}} +
    {{name.0.value}}{{#summary}}
    {{{summary}}}
    {{/summary}}
    + {{/children}} +
    +
    +{{/children}} +{{#remarks}}

    Remarks

    {{{remarks}}}
    {{/remarks}} +{{#example.0}}

    Examples

    {{#example}}{{{.}}}{{/example}}
    {{/example.0}} diff --git a/documents/templates/partials/api.relationships.tmpl.partial b/documents/templates/partials/api.relationships.tmpl.partial new file mode 100644 index 00000000..0524f771 --- /dev/null +++ b/documents/templates/partials/api.relationships.tmpl.partial @@ -0,0 +1,11 @@ +{{!Based on the .NET Foundation DocFX templates, licensed under the MIT license.}} +
    + Show inherited members and related typesHide inherited members and related types +
    + {{#inheritance.0}}

    Inheritance

      {{#inheritance}}
    • {{{specName.0.value}}}
    • {{/inheritance}}
    • {{apiName}}
    {{/inheritance.0}} + {{#implements.0}}

    Interfaces

      {{#implements}}
    • {{{specName.0.value}}}
    • {{/implements}}
    {{/implements.0}} + {{#derivedClasses.0}}

    Derived types

      {{#derivedClasses}}
    • {{{specName.0.value}}}
    • {{/derivedClasses}}
    {{/derivedClasses.0}} + {{#inheritedMembers.0}}

    Inherited members

      {{#inheritedMembers}}
    • {{#definition}}{{/definition}}{{^definition}}{{/definition}}
    • {{/inheritedMembers}}
    {{/inheritedMembers.0}} + {{#extensionMethods.0}}

    Extension methods

      {{#extensionMethods}}
    • {{#definition}}{{/definition}}{{^definition}}{{/definition}}
    • {{/extensionMethods}}
    {{/extensionMethods.0}} +
    +
    diff --git a/documents/templates/partials/api.seealso.tmpl.partial b/documents/templates/partials/api.seealso.tmpl.partial new file mode 100644 index 00000000..2543611c --- /dev/null +++ b/documents/templates/partials/api.seealso.tmpl.partial @@ -0,0 +1,2 @@ +{{!Based on the .NET Foundation DocFX templates, licensed under the MIT license.}} +{{#seealso.0}}{{/seealso.0}} diff --git a/documents/templates/partials/api.signature.tmpl.partial b/documents/templates/partials/api.signature.tmpl.partial new file mode 100644 index 00000000..9c0385e9 --- /dev/null +++ b/documents/templates/partials/api.signature.tmpl.partial @@ -0,0 +1,7 @@ +{{!Based on the .NET Foundation DocFX templates, licensed under the MIT license.}} +{{#parameters.0}}

    Parameters

    {{#parameters}}
    {{id}}{{{type.specName.0.value}}}
    {{{description}}}
    {{/parameters}}
    {{/parameters.0}} +{{#typeParameters.0}}

    Type parameters

    {{#typeParameters}}
    {{id}}
    {{{description}}}
    {{/typeParameters}}
    {{/typeParameters.0}} +{{#return}}
    Returns
    {{{type.specName.0.value}}}{{#description}}
    {{{description}}}
    {{/description}}
    {{/return}} +{{#fieldValue}}
    Type
    {{{type.specName.0.value}}}{{#description}}
    {{{description}}}
    {{/description}}
    {{/fieldValue}} +{{#propertyValue}}
    Type
    {{{type.specName.0.value}}}{{#description}}
    {{{description}}}
    {{/description}}
    {{/propertyValue}} +{{#eventType}}
    Type
    {{{type.specName.0.value}}}{{#description}}
    {{{description}}}
    {{/description}}
    {{/eventType}} diff --git a/documents/templates/partials/api.type.tmpl.partial b/documents/templates/partials/api.type.tmpl.partial new file mode 100644 index 00000000..45da3dc8 --- /dev/null +++ b/documents/templates/partials/api.type.tmpl.partial @@ -0,0 +1,25 @@ +{{!Based on the .NET Foundation DocFX templates, licensed under the MIT license.}} +{{#children}} +
    +

    {{apiTitle}}

    +
    + {{#children}} + {{#overload}}{{/overload}} +
    +

    {{name.0.value}}

    {{#sourceurl}}Source{{/sourceurl}}
    + {{#summary}}
    {{{summary}}}
    {{/summary}} + {{#conceptual}}
    {{{conceptual}}}
    {{/conceptual}} + {{#syntax.content.0.value}}
    {{syntax.content.0.value}}
    {{/syntax.content.0.value}} + {{#syntax}}{{>partials/api.signature}}{{/syntax}} + {{#remarks}}

    Remarks

    {{{remarks}}}
    {{/remarks}} + {{#example.0}}

    Examples

    {{#example}}{{{.}}}{{/example}}
    {{/example.0}} + {{#exceptions.0}}

    Exceptions

    {{#exceptions}}
    {{{type.specName.0.value}}}
    {{{description}}}
    {{/exceptions}}
    {{/exceptions.0}} + {{>partials/api.seealso}} +
    + {{/children}} +
    +
    +{{/children}} +{{#remarks}}

    Remarks

    {{{remarks}}}
    {{/remarks}} +{{#example.0}}

    Examples

    {{#example}}{{{.}}}{{/example}}
    {{/example.0}} +{{>partials/api.seealso}} diff --git a/documents/templates/public/api.css b/documents/templates/public/api.css new file mode 100644 index 00000000..e9b13b02 --- /dev/null +++ b/documents/templates/public/api.css @@ -0,0 +1,208 @@ +/* Zenith API reference: generated content, site-owned presentation. */ +body.zenith-theme[data-section="api"] > main.container-xxl { + grid-template-columns: 264px minmax(0, 1fr); + column-gap: 44px; +} + +body.zenith-theme[data-section="api"] > main > .content { padding-block: 40px 72px; } +body.zenith-theme[data-section="api"] > main > .toc-offcanvas { padding: 28px 22px 24px 0; } +.api-reference { min-width: 0; max-width: 1120px; } + +/* A namespace picker and flat type list replace the expanding namespace tree. */ +.api-browser { display: flex; flex-direction: column; min-height: 0; height: 100%; font-size: 13px; } +.api-browser-home { display: flex; align-items: center; gap: 10px; margin-bottom: 28px; color: #edf4ff; font-size: 15px; font-weight: 600; text-decoration: none; } +.api-browser-home i { display: grid; place-items: center; width: 30px; height: 30px; border: 1px solid #3b4c63; border-radius: 5px; background: #1c2a3c; color: #bfd8f7; } +.api-namespace-label { margin-bottom: 8px; color: #8e9bad; font: 10px/1.4 var(--bs-font-monospace); letter-spacing: .1em; text-transform: uppercase; } +.api-namespace-picker { position: relative; flex-shrink: 0; min-height: 44px; padding: 12px 32px 12px 12px; border: 1px solid #45566e; border-radius: 5px; background: #1c2736; color: #e0ebfa; font: 500 13px/1.6 var(--bs-body-font-family); } +#api-namespace-name { display: block; overflow-wrap: anywhere; pointer-events: none; } +.api-namespace-picker select { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; } +.api-namespace-picker:hover { background: #25364d; border-color: #7492b7; } +.api-namespace-picker:focus-within { outline: 2px solid var(--zenith-focus); outline-offset: 3px; } +.api-namespace-picker > i { position: absolute; right: 12px; top: 50%; transform: translateY(-50%); color: #9eb5d1; pointer-events: none; } +.api-type-search { display: flex; flex-shrink: 0; align-items: center; gap: 10px; margin: 16px 0 18px; padding: 8px 2px; border-bottom: 1px solid #354153; color: #8496ae; } +.api-type-search:focus-within { border-bottom-color: #aecdf3; color: #c8dffc; } +.api-type-search input { width: 100%; min-width: 0; border: 0; outline: 0; background: none; color: #eef4ff; font: 13px/1.5 var(--bs-body-font-family); } +.api-type-search input::placeholder { color: #95a1b2; } +.api-browser-caption { flex-shrink: 0; margin-bottom: 10px; color: #929fb1; font-size: 11px; } +.api-type-scroll { position: relative; min-height: 0; flex: 1; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; } +#api-type-list { margin: 0; padding: 0 6px 0 0; list-style: none; } +#api-type-list li { margin: 2px 0; } +#api-type-list a { display: block; padding: 8px 10px; border-radius: 4px; color: #aeb8c7; font-size: 13px; line-height: 1.5; text-decoration: none; overflow-wrap: anywhere; transition: background-color 180ms, color 180ms; } +#api-type-list a:hover { background: #202a38; color: #f2f6fc; } +#api-type-list a[aria-current] { background: #273a52; color: #e4f0ff; font-weight: 600; } +#api-type-list small { display: block; margin-top: 3px; color: #90a6c3; font-size: 10px; } +.api-browser-status { color: #aab5c4; font-size: 12px; } + +/* Identity and compact declarations. */ +.api-heading { margin-bottom: 26px; } +.api-heading-meta { display: flex; align-items: center; gap: 14px; margin-bottom: 16px; color: #93a2b6; font: 11px/1.5 var(--bs-font-monospace); } +.api-kind { display: inline-flex; align-items: center; padding: 4px 9px; border: 1px solid #3e5674; border-radius: 4px; background: #1b2c42; color: #bedbff; font: 500 10px/1.5 var(--bs-font-monospace); text-transform: uppercase; letter-spacing: .08em; } +.api-reference .api-heading h1 { margin: 0 0 18px; font-size: clamp(30px, 3.1vw, 46px); font-weight: 600; line-height: 1.15; letter-spacing: -.045em; overflow-wrap: anywhere; } +.api-identity { display: flex; flex-wrap: wrap; gap: 8px 22px; align-items: baseline; font-size: 12px; } +.api-identity a { color: #b9d0ee; text-decoration: none; } +.api-identity a:hover { color: #eaf3ff; text-decoration: underline; } +.api-assembly { color: #8d9aad; font: 11px/1.6 var(--bs-font-monospace); } +.api-reference .api-source { flex-shrink: 0; margin-left: auto; padding: 5px 10px; border: 1px solid #38495e; border-radius: 4px; background: #1a2533; color: #bad0ec; font: 500 11px/1.4 var(--bs-body-font-family); text-decoration: none; transition: background-color 180ms, border-color 180ms; } +.api-reference .api-source:hover { background: #2b405b; border-color: #7793b6; color: #fff; } +.api-summary { color: #afbac9; font-size: 14px; line-height: 1.75; } +.api-heading > .api-summary { margin-top: 18px; } +.api-summary > :last-child { margin-bottom: 0; } +.api-intro { max-width: 620px; margin: 0; color: #abb9cc; font-size: 16px; } +.api-declaration { position: relative; margin-bottom: 14px; border: 1px solid #303b4b; border-radius: 6px; background: #111720; } +.api-code-label { padding: 14px 100px 0 18px; color: #a5b3c6; font: 500 12px/1.5 var(--bs-body-font-family); } +.api-reference pre, .api-reference pre[data-language] { margin: 14px 0; padding: 15px 44px 15px 16px; border: 1px solid #283649; border-radius: 4px; background: #101720; font-size: 13px; line-height: 1.7; box-shadow: none; } +.api-reference pre[data-language]::before { content: none; } +.api-reference pre .code-action { top: 7px; right: 5px; padding: 4px 8px; color: #9eb5d1; font-size: 13px; } +.api-reference .api-declaration pre { position: static; margin: 0; padding: 16px 18px 20px; border: 0; background: none; } +.api-declaration pre > code { white-space: pre-wrap; overflow-wrap: anywhere; } +.api-reference .api-declaration .code-action { display: inline-flex; align-items: center; gap: 6px; top: 8px; right: 12px; padding: 6px 9px; border-radius: 4px; background: #202d3e; color: #d0e1f7; font: 500 11px/1.5 var(--bs-body-font-family); text-decoration: none; } +.api-declaration .code-action::after { content: "Copy"; } +.api-declaration .code-action.link-success::after { content: "Copied"; } +.api-reference .api-declaration .code-action:hover { background: #324b6b; } +.api-reference :not(pre) > code { padding: 1px 4px; border-radius: 3px; background: #223044; color: #cee0f7; } +.api-reference a.xref { color: #c5d9f2; text-decoration: none; } +.api-reference a.xref:hover { color: #fff; text-decoration: underline; } + +/* Context stays available without competing with the API itself. */ +.api-relationships { margin: 0 0 20px; border-block: 1px solid #2d3a4c; font-size: 12px; } +.api-reference summary { display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 13px 2px; color: #a6bad5; cursor: pointer; list-style: none; } +.api-reference summary::-webkit-details-marker { display: none; } +.api-reference summary::after { content: "+"; flex-shrink: 0; width: 20px; color: #c4daf6; font: 18px/1 var(--bs-font-monospace); text-align: center; transition: transform 180ms; } +.api-reference details[open] > summary::after { transform: rotate(45deg); } +.api-reference summary:hover { color: #edf6ff; } +.api-relationships { border: 1px solid #303e52; border-radius: 5px; background: #161f2b; } +.api-relationships > summary { padding: 12px 14px; color: #c5d8f2; font-size: 12px; font-weight: 500; } +.api-relationships > summary:hover { background: #203249; } +.api-relationships .api-when-open, .api-relationships[open] .api-when-closed { display: none; } +.api-relationships[open] .api-when-open { display: inline; } +.api-reference details[open] > :not(summary) { animation: zenith-panel-in 220ms ease-out; } +.api-relationships-body { display: grid; gap: 22px; padding: 10px 14px 20px; } +.api-reference .api-relation h4 { margin: 0 0 10px; color: #dce7f6; font-size: 12px; } +.api-relation ul, .api-related ul { display: flex; flex-wrap: wrap; gap: 6px; margin: 0; padding: 0; list-style: none; } +.api-relation li { max-width: 100%; margin: 0; padding: 5px 9px; border: 1px solid #29384a; border-radius: 4px; background: #161f2b; overflow-wrap: anywhere; } +.api-reference :is(.api-group-heading h2, .api-member-heading h3, .api-enum-value h3):target { animation: api-location-cue 900ms ease-out; } +@keyframes api-location-cue { from { color: #fff; text-shadow: 0 0 18px #a9cfff99; } to { color: var(--zenith-text); text-shadow: none; } } +.api-group { min-width: 0; margin: 0 0 40px; } +.api-group-heading { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; } +.api-reference .api-group-heading h2 { margin: 0; padding: 0; border: 0; font-size: 22px; font-weight: 550; letter-spacing: -.5px; } + +/* Namespace directories use one dense, scannable grid. */ +.api-type-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1px; overflow: hidden; border: 1px solid #303d50; border-radius: 6px; background: #303d50; } +.api-type-entry { position: relative; display: flex; flex-wrap: wrap; align-content: center; gap: 9px; min-width: 0; min-height: 68px; padding: 17px 18px; background: #161d27; transition: background-color 180ms; } +.api-type-entry:hover, .api-type-entry:focus-within { background: #24364e; } +.api-type-entry > a { flex: 1; min-width: 0; color: #e0ebfa; font: 500 13px/1.6 var(--bs-font-monospace); text-decoration: none; overflow-wrap: anywhere; } +.api-type-entry > a::after { content: ""; position: absolute; inset: 0; } +.api-type-entry > a:focus-visible { outline: none; } +.api-type-entry:focus-within { outline: 2px solid #bdd8fa; outline-offset: -3px; } +.api-type-entry > .api-summary { flex-basis: 100%; font-size: 12px; } + +.api-enum-values { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1px; overflow: hidden; border: 1px solid #303d50; border-radius: 6px; background: #303d50; } +.api-enum-value { min-width: 0; padding: 17px 18px; background: #161d27; } +.api-reference .api-enum-value h3 { margin: 0; font-size: 13px; line-height: 1.7; font-weight: 400; } +.api-reference .api-enum-value code { padding: 0; background: none; color: #c8dffb; font: inherit; font-family: var(--bs-font-monospace); } +.api-enum-value:has(:target) { background: #253b58; } +.api-enum-value > .api-summary { margin-top: 10px; font-size: 12px; } + +/* Members keep their original IDs and complete signatures. */ +.api-members { display: grid; gap: 14px; } +.api-member { min-width: 0; padding: 22px 24px; border: 1px solid #334257; border-radius: 6px; background: linear-gradient(120deg, #1b2431, #161d27 65%); } +.api-member:target, .api-member:has(:target) { border-color: #91b4df; } +/* Focus from the finder belongs to the member block, not a box around static text. */ +.api-reference :is(.api-member-heading h3, .api-enum-value h3)[tabindex="-1"]:focus { outline: none; } +.api-member:has(.api-member-heading h3:focus) { border-color: #b2cef1; box-shadow: inset 0 0 0 1px #8aafd338; } +.api-enum-value:has(h3:focus) { background: #253b58; box-shadow: inset 0 0 0 1px #91b4df; } +.api-member-heading { display: flex; align-items: flex-start; gap: 14px; } +.api-reference .api-member h3 { min-width: 0; margin: 0; color: #edf4ff; font: 550 17px/1.5 var(--bs-font-monospace); letter-spacing: -.04em; overflow-wrap: anywhere; } +.api-member > .api-summary { margin-top: 12px; } +.api-reference .api-value { display: flex; align-items: baseline; gap: 14px; margin: 0; font-size: 12px; } +.api-value > dt { color: #879bb6; font-weight: 400; } +.api-value > dd { min-width: 0; margin: 0; color: #b8c9df; } +.api-value dd > div { margin-top: 8px; } +.api-signature-section, .api-member-notes, .api-related { margin-top: 18px; } +.api-reference :is(.api-signature-section, .api-member-notes, .api-related) > h4 { margin: 0 0 10px; color: #9cb2cf; font: 500 11px/1.5 var(--bs-body-font-family); } +.api-reference .api-parameters { margin: 0; font-size: 12px; } +.api-parameters > div { display: grid; grid-template-columns: minmax(180px, .8fr) minmax(0, 1fr); gap: 16px; padding: 11px 0; border-top: 1px solid #2a384a; } +.api-parameters dt { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px 12px; min-width: 0; color: #d0dced; font-weight: 400; } +.api-parameters dd { margin: 0; color: #adbbcd; } +.api-parameters dd:empty { display: none; } +.api-parameters > div:has(dd:empty) { grid-template-columns: 1fr; } +.api-parameters :is(dt, dd) > :last-child { margin-bottom: 0; } +.api-member-notes { color: #b7c4d6; font-size: 13px; } +.api-related li { margin: 0; font-size: 12px; } + +/* API overview. */ +.api-start-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; margin: 32px 0 38px; } +.api-start-grid > a { padding: 24px; border: 1px solid #4a627f; border-radius: 6px; background: linear-gradient(125deg, #21344d, #172333); text-decoration: none; } +.api-start-grid > a:hover { border-color: #9dbde6; background: #293e59; } +.api-start-grid span { display: block; margin-bottom: 14px; color: #a5bddc; font-size: 11px; } +.api-start-grid strong { color: #edf5ff; font: 500 18px/1.5 var(--bs-font-monospace); overflow-wrap: anywhere; } +.api-start-grid p { margin: 12px 0 0; color: #b0c1d7; font-size: 13px; } +.api-namespace-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; } +.api-namespace-card { display: block; padding: 20px; border: 1px solid #33445a; border-radius: 5px; background: #182231; color: #dceafa; text-decoration: none; overflow-wrap: anywhere; } +.api-namespace-card:hover { background: #273a53; border-color: #748fb0; color: #fff; } +.api-namespace-card strong { font-size: 14px; font-weight: 500; } + +/* Page-local member lookup stays in navigation until requested. */ +.api-member-access { flex-shrink: 0; margin-top: 14px; padding-top: 14px; border-top: 1px solid #303e52; } +.api-member-access:has(.api-member-launcher[hidden]) { display: none; } +.api-member-launcher { display: flex; align-items: center; justify-content: center; gap: 9px; width: 100%; min-height: 42px; padding: 10px 12px; border: 1px solid #455c79; border-radius: 4px; background: #213249; color: #dceaff; font: 500 12px/1.5 var(--bs-body-font-family); cursor: pointer; transition: background-color 180ms, border-color 180ms; } +.api-member-launcher[hidden] { display: none; } +.api-member-launcher:hover { background: #304a6b; border-color: #8aaacd; } +.api-member-launcher kbd { margin-left: auto; padding: 0; background: none; color: #a7bedb; font: 10px/1.5 var(--bs-font-monospace); } +.api-mobile-tools { display: none; } +.api-menu-member { display: none; } +.api-finder-heading { display: flex; flex-shrink: 0; align-items: flex-start; justify-content: space-between; gap: 20px; padding: 20px 24px 18px; } +.api-finder-heading > div { min-width: 0; } +.api-finder-heading h2 { margin: 0 0 7px; color: var(--zenith-text); font-size: 20px; line-height: 1.35; font-weight: 600; letter-spacing: -.4px; } +.api-finder-heading p { margin: 0; color: #9db4d2; font: 12px/1.6 var(--bs-font-monospace); } +#api-member-close { flex-shrink: 0; min-height: 32px; padding: 6px 8px; border: 1px solid #465974; border-radius: 4px; background: #202d3e; color: #c8daf2; font: 11px/1.5 var(--bs-font-monospace); cursor: pointer; } +#api-member-close:hover { background: #344d6c; } +.api-member-filter { display: flex; flex-shrink: 0; align-items: center; gap: 12px; padding: 15px 24px; border-block: 1px solid #37465c; color: #9db4d2; } +.api-member-filter:focus-within { border-color: #708eb5; } +#api-member-query { width: 100%; min-width: 0; padding: 0; border: 0; outline: 0; background: none; color: #edf5ff; font: 16px/1.6 var(--bs-body-font-family); } +#api-member-query::placeholder { color: #8fa2bc; } +#api-member-query::-webkit-search-cancel-button { display: none; } +#api-member-clear { flex-shrink: 0; width: 30px; height: 30px; padding: 0; border: 0; border-radius: 4px; background: none; color: #9eb7d8; font-size: 12px; cursor: pointer; } +#api-member-clear:hover { background: #293e59; color: #fff; } +#api-member-results > section + section { margin-top: 18px; } +#api-member-results h3 { margin: 5px 12px 8px; color: #94acca; font: 500 11px/1.5 var(--bs-body-font-family); } +#api-member-results ul { margin: 0; padding: 0; list-style: none; } +#api-member-results a { display: block; padding: 11px 12px; border-radius: 4px; color: #e1edfc; font: 12px/1.65 var(--bs-font-monospace); text-decoration: none; overflow-wrap: anywhere; } +#api-member-results a:hover, #api-member-results a:focus-visible { background: #293e59; color: #fff; } +#api-member-results a:focus-visible { outline-offset: -2px; } +.api-finder-empty { margin: 18px 12px 28px; color: #a7b8cd; font-size: 13px; } + +@media (max-width: 1199.98px) { + body.zenith-theme[data-section="api"] > main.container-xxl { grid-template-columns: 230px minmax(0, 1fr); column-gap: 28px; } + .api-type-grid, .api-namespace-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } +} +@media (min-width: 768px) and (max-width: 999.98px) { + .api-type-grid, .api-enum-values, .api-start-grid { grid-template-columns: 1fr; } +} +@media (max-width: 767.98px) { + body.zenith-theme[data-section="api"] > main.container-xxl { grid-template-columns: minmax(0, 1fr); } + body.zenith-theme[data-section="api"] > main > .content { padding-top: 0; } + body.zenith-theme[data-section="api"] > main > .toc-offcanvas { padding: 0; } + .api-browser-home { margin-bottom: 20px; } + .api-type-search input { font-size: 16px; } + .api-reference .api-heading h1 { font-size: 34px; } + .api-member { padding: 18px 16px; } + .api-reference .api-member h3 { font-size: 15px; } + .api-member-heading { gap: 8px; } + body.zenith-theme > main > .content > .api-mobile-tools { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 24px; } + .api-mobile-tools > .contents-toggle { display: inline-flex; margin: 0; } + .api-mobile-tools > .api-member-launcher { width: auto; min-height: 40px; } + .menu-open .api-menu-member { display: flex; justify-content: flex-start; margin-top: 14px; } + .api-member-access kbd { display: none; } + .api-finder-heading { padding: 18px 16px 16px; } + .api-member-filter { padding: 13px 16px; } + .api-start-grid { grid-template-columns: 1fr; } + .api-parameters > div { grid-template-columns: 1fr; gap: 6px; } +} +@media (max-width: 479.98px) { + .api-type-grid, .api-enum-values, .api-namespace-grid { grid-template-columns: 1fr; } + .api-reference .api-heading h1 { font-size: 30px; } +} +@media (prefers-reduced-motion: reduce) { + .api-reference *, .api-browser * { animation: none !important; transition: none !important; } +} diff --git a/documents/templates/public/api.js b/documents/templates/public/api.js new file mode 100644 index 00000000..86aa5757 --- /dev/null +++ b/documents/templates/public/api.js @@ -0,0 +1,117 @@ +// Use DocFX's generated TOC as the source of truth for the custom API browser. +export async function initializeApi() { + const browser = document.getElementById('api-browser'); + if (!browser) return; + + const picker = document.getElementById('api-namespace'); + const filter = document.getElementById('api-type-filter'); + const list = document.getElementById('api-type-list'); + const status = document.getElementById('api-browser-status'); + const scope = document.getElementById('api-type-scope'); + filter.disabled = true; + + function writeNamespace(element, name) { + name.split('.').forEach((part, index) => { + if (index) element.append('.', document.createElement('wbr')); + element.append(part); + }); + } + + try { + const tocUrl = new URL(document.querySelector('meta[name="docfx:tocrel"]').content, location.href); + const response = await fetch(tocUrl); + if (!response.ok) throw new Error('API navigation could not be loaded.'); + const documentToc = new DOMParser().parseFromString(await response.text(), 'text/html'); + const readLink = link => ({ name: link.textContent.trim(), href: new URL(link.getAttribute('href'), tocUrl).href }); + const namespaces = [...documentToc.querySelectorAll('.nav.level1 > li')].map(item => { + const link = item.querySelector(':scope > a'); + return { ...readLink(link), types: [...item.querySelectorAll(':scope > ul > li > a')].map(readLink) }; + }).sort((a, b) => { + const rank = name => name === 'Zenith.NET' ? 0 : name.startsWith('Zenith.NET.') ? 1 : 2; + return rank(a.name) - rank(b.name) || a.name.localeCompare(b.name); + }); + const current = href => new URL(href).pathname === location.pathname; + const activeNamespace = namespaces.find(item => current(item.href) || item.types.some(type => current(type.href))) || namespaces[0]; + picker.replaceChildren(...namespaces.map(item => { + const option = document.createElement('option'); + option.value = item.href; + option.textContent = item.name; + return option; + })); + picker.disabled = false; + filter.disabled = false; + picker.value = activeNamespace.href; + picker.title = activeNamespace.name; + const selectedName = document.getElementById('api-namespace-name'); + selectedName.replaceChildren(); + writeNamespace(selectedName, activeNamespace.name); + picker.addEventListener('change', () => location.assign(picker.value)); + + function renderTypes() { + const query = filter.value.trim().toLowerCase(); + const entries = query + ? namespaces.flatMap(namespace => namespace.types.map(type => ({ ...type, namespace: namespace.name }))) + .filter(type => `${type.name} ${type.namespace}`.toLowerCase().includes(query)) + : activeNamespace.types; + const fragment = document.createDocumentFragment(); + for (const type of entries) { + const item = document.createElement('li'); + const link = document.createElement('a'); + const name = document.createElement('span'); + // Keep identifiers intact while allowing breaks between their words. + type.name.split(/(?<=[a-z])(?=[A-Z])|(?<=[0-9A-Z])(?=[A-Z][a-z])|(?<=\.)/).forEach((part, index) => { + if (index) name.append(document.createElement('wbr')); + name.append(part); + }); + link.href = type.href; + link.title = type.name; + link.append(name); + if (current(type.href)) link.setAttribute('aria-current', 'page'); + if (query) { + const namespace = document.createElement('small'); + writeNamespace(namespace, type.namespace); + link.append(namespace); + } + item.append(link); + fragment.append(item); + } + list.replaceChildren(fragment); + scope.textContent = query ? 'Matching types' : 'Types'; + status.hidden = entries.length > 0; + status.textContent = query ? 'No matching types.' : 'No types in this namespace.'; + } + filter.addEventListener('input', renderTypes); + filter.addEventListener('keydown', event => { + if (event.key === 'Escape') { + filter.value = ''; + renderTypes(); + } else if (event.key === 'ArrowDown') { + event.preventDefault(); + list.querySelector('a')?.focus(); + } + }); + renderTypes(); + const active = list.querySelector('[aria-current="page"]'); + if (active) browser.querySelector('.api-type-scroll').scrollTop = active.offsetTop - 160; + window.addEventListener('pageshow', () => setTimeout(() => { + picker.value = activeNamespace.href; + renderTypes(); + }, 0)); + + const grid = document.getElementById('api-namespace-grid'); + if (grid) { + for (const namespace of namespaces) { + const link = document.createElement('a'); + link.href = namespace.href; + link.className = 'api-namespace-card'; + const name = document.createElement('strong'); + writeNamespace(name, namespace.name); + link.append(name); + grid.append(link); + } + } + } catch { + status.hidden = false; + status.textContent = 'Could not load types. Reload this page to try again.'; + } +} diff --git a/documents/templates/public/home.js b/documents/templates/public/home.js new file mode 100644 index 00000000..91375ffb --- /dev/null +++ b/documents/templates/public/home.js @@ -0,0 +1,190 @@ +// A slowly rotating Canvas geometry study, rendered only while visible. +export function initializeHomeScene() { + const canvas = document.getElementById('home-geometry'); + if (!canvas) return; + const context = canvas.getContext('2d'); + if (!context) return; + const stage = canvas.parentElement; + const preference = window.matchMedia('(prefers-reduced-motion: reduce)'); + const faces = []; + const steps = 144; + const sides = 12; + let yaw = .4; + let pitch = -.45; + let mode = 'surface'; + let pointer; + let visible = false; + let suspended = false; + let frame = 0; + let lastTime = 0; + let speed = 0; + let pauseUntil = 0; + let dirty = true; + let width = 0, height = 0, ratio = 1; + + const normalize = vector => { + const length = Math.hypot(...vector); + return vector.map(value => value / length); + }; + const cross = (a, b) => [a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]]; + const lightDirection = normalize([-.55, -.8, 1]); + const halfDirection = normalize([lightDirection[0], lightDirection[1], lightDirection[2] + 1]); + const dot = (a, b) => a.reduce((sum, value, i) => sum + value * b[i], 0); + const center = t => [(1.2 + .38 * Math.cos(3 * t)) * Math.cos(2 * t), (1.2 + .38 * Math.cos(3 * t)) * Math.sin(2 * t), .58 * Math.sin(3 * t)]; + const point = (step, side) => { + const t = step / steps * Math.PI * 2; + const c = center(t); + const next = center(t + .001); + const tangent = normalize(next.map((v, i) => v - c[i])); + const normal = normalize(cross(tangent, [0, 0, 1])); + const binormal = cross(tangent, normal); + const angle = side / sides * Math.PI * 2; + return c.map((v, i) => v + .26 * (normal[i] * Math.cos(angle) + binormal[i] * Math.sin(angle))); + }; + for (let i = 0; i < steps; i++) { + for (let j = 0; j < sides; j++) { + faces.push([point(i, j), point(i + 1, j), point(i + 1, j + 1), point(i, j + 1)]); + } + } + + function draw() { + if (!width || !height) return; + context.setTransform(ratio, 0, 0, ratio, 0, 0); + context.clearRect(0, 0, width, height); + const cy = Math.cos(yaw), sy = Math.sin(yaw), cp = Math.cos(pitch), sp = Math.sin(pitch); + const rotate = ([x, y, z]) => { + const a = x * cy + z * sy, b = z * cy - x * sy; + return [a, y * cp - b * sp, y * sp + b * cp]; + }; + const scale = Math.min(width, height) * .24; + const project = ([x, y, z]) => { + const perspective = 5 / (5 - z); + return [width / 2 + x * scale * perspective, height / 2 + y * scale * perspective]; + }; + const transformed = faces.map(face => { + const vertices = face.map(rotate); + return { vertices, depth: vertices.reduce((sum, v) => sum + v[2], 0) / 4 }; + }).sort((a, b) => a.depth - b.depth); + for (const { vertices, depth } of transformed) { + const normal = normalize(cross(vertices[3].map((v, i) => v - vertices[0][i]), vertices[1].map((v, i) => v - vertices[0][i]))); + const diffuse = Math.max(0, dot(normal, lightDirection)); + const highlight = Math.pow(Math.max(0, dot(normal, halfDirection)), 28); + const brightness = Math.round(18 + diffuse * 135 + highlight * 70 + (depth + 2) * 5); + const points = vertices.map(project); + context.beginPath(); + points.forEach(([x, y], i) => i ? context.lineTo(x, y) : context.moveTo(x, y)); + context.closePath(); + if (mode === 'surface') { + context.fillStyle = `rgb(${brightness}, ${brightness + 4}, ${brightness + 10})`; + context.fill(); + context.strokeStyle = 'rgba(220,230,244,.07)'; + context.lineWidth = .5; + } else { + context.strokeStyle = `rgba(200,211,226,${.1 + (depth + 1.7) * .12})`; + context.lineWidth = .6; + } + context.stroke(); + } + } + + function schedule() { + if (!frame && visible && !document.hidden && !suspended) frame = requestAnimationFrame(tick); + } + + function tick(time) { + frame = 0; + const elapsed = lastTime ? Math.min((time - lastTime) / 1000, .05) : 0; + lastTime = time; + const rotating = !preference.matches && !pointer && time >= pauseUntil; + if (rotating) { + // Ease back into a roughly 40-second revolution after manual input. + speed = Math.min(.16, speed + elapsed * .2); + yaw = (yaw - speed * elapsed) % (Math.PI * 2); + } + if (dirty || rotating) draw(); + dirty = false; + if (!preference.matches && !pointer) schedule(); + } + + function syncMotion() { + cancelAnimationFrame(frame); + frame = 0; + lastTime = 0; + speed = 0; + if (dirty || !preference.matches && !pointer) schedule(); + } + + function render() { + dirty = true; + schedule(); + } + + preference.addEventListener('change', syncMotion); + + stage.querySelectorAll('[data-scene-mode]').forEach(button => { + button.addEventListener('click', () => { + mode = button.dataset.sceneMode; + stage.querySelectorAll('[data-scene-mode]').forEach(item => item.setAttribute('aria-pressed', String(item === button))); + render(); + }); + }); + canvas.addEventListener('pointerdown', event => { + if (event.button !== 0 || pointer) return; + pointer = { id: event.pointerId, x: event.clientX, y: event.clientY }; + canvas.setPointerCapture(event.pointerId); + canvas.classList.add('is-dragging'); + syncMotion(); + }); + canvas.addEventListener('pointermove', event => { + if (!pointer || pointer.id !== event.pointerId) return; + yaw += (event.clientX - pointer.x) * .008; + pitch += (event.clientY - pointer.y) * .008; + pointer.x = event.clientX; + pointer.y = event.clientY; + render(); + }); + const release = () => { + if (!pointer) return; + pointer = undefined; + canvas.classList.remove('is-dragging'); + syncMotion(); + }; + canvas.addEventListener('pointerup', release); + canvas.addEventListener('pointercancel', release); + canvas.addEventListener('lostpointercapture', release); + canvas.addEventListener('keydown', event => { + const delta = { ArrowLeft: [-.15, 0], ArrowRight: [.15, 0], ArrowUp: [0, -.15], ArrowDown: [0, .15] }[event.key]; + if (!delta) return; + event.preventDefault(); + yaw += delta[0]; + pitch += delta[1]; + pauseUntil = performance.now() + 1000; + speed = 0; + render(); + }); + new ResizeObserver(() => { + ({ width, height } = canvas.getBoundingClientRect()); + ratio = Math.min(devicePixelRatio || 1, 2); + const pixelWidth = Math.round(width * ratio), pixelHeight = Math.round(height * ratio); + if (canvas.width !== pixelWidth || canvas.height !== pixelHeight) { + canvas.width = pixelWidth; + canvas.height = pixelHeight; + } + render(); + }).observe(canvas); + new IntersectionObserver(([entry]) => { + visible = entry.isIntersecting; + syncMotion(); + }).observe(canvas); + document.addEventListener('visibilitychange', syncMotion); + window.addEventListener('pagehide', () => { + suspended = true; + release(); + syncMotion(); + }); + window.addEventListener('pageshow', () => { + suspended = false; + syncMotion(); + }); + syncMotion(); +} diff --git a/documents/templates/public/main.css b/documents/templates/public/main.css index 434fd288..e7ef9f0e 100644 --- a/documents/templates/public/main.css +++ b/documents/templates/public/main.css @@ -1,3777 +1,1423 @@ -a.external[href]::after { - content: none; -} - -.next-article .bi-chevron-right { - display: none; -} - -/** - * Zenith.NET documentation theme. - * Brand-led landing page plus a compact, readable DocFX shell. - */ +@import url("./docfx.min.css") layer(docfx); -/* ========================================================================== - Design tokens - ========================================================================== */ +/* Zenith.NET — a single graphite theme, based on the brand icon. */ +/* Tokens and DocFX / Bootstrap integration */ :root { - --zenith-navy-900: #231e2e; - --zenith-purple-700: #512bd4; - --zenith-magenta-600: #512bd4; - --zenith-blue-500: #536dfe; - --zenith-green-500: #0f9f78; - --zenith-text: #231e2e; - --zenith-text-soft: #655f70; - --zenith-text-faint: #918a9d; - --zenith-surface: #fbfafc; - --zenith-surface-soft: #f3f1f7; - --zenith-surface-tint: #f6f1ff; - --zenith-border: #e1dce8; - --zenith-border-strong: #cec6da; - --zenith-code-surface: #f6f8fc; - --zenith-code-toolbar: #eef2f8; - --zenith-code-border: #d8deea; - --zenith-code-text: #1f2430; - --zenith-code-muted: #687386; - --zenith-code-hover: #e2e7f1; - --zenith-code-accent: #512bd4; - --zenith-code-accent-border: rgba(81, 43, 212, 0.34); - --zenith-code-success: #0f766e; - --zenith-inline-code: #512bd4; - --zenith-inline-code-background: rgba(81, 43, 212, 0.08); - --zenith-table-surface: #ffffff; - --zenith-table-header: #eef2f7; - --zenith-table-stripe: #f8fafc; - --zenith-table-hover: #f1f5fb; - --zenith-table-border: #d8deea; - --zenith-table-text: #4b5565; - --zenith-table-heading: #1f2937; - --zenith-link: #512bd4; - --zenith-link-hover: #7652e8; - --zenith-header-surface: rgba(251, 250, 252, 0.95); - --zenith-header-border: rgba(35, 30, 46, 0.12); - --zenith-nav-text: #70697c; - --zenith-nav-active: #231e2e; - --zenith-search-surface: #f2f0f5; - --zenith-search-border: #e1dce8; - --zenith-search-focus: #7150e8; - --zenith-accent: #512bd4; - --zenith-accent-soft: rgba(81, 43, 212, 0.08); - --zenith-logo-width: 115px; - --zenith-info: var(--zenith-blue-500); - --zenith-success: var(--zenith-green-500); - --zenith-warning: #c76620; - --zenith-danger: #d94f70; - --zenith-syntax-keyword: #af00db; - --zenith-syntax-literal: #0000ff; - --zenith-syntax-string: #a31515; - --zenith-syntax-type: #267f99; - --zenith-syntax-function: #795e26; - --zenith-syntax-variable: #001080; - --zenith-syntax-comment: #008000; - --zenith-syntax-number: #098658; - --zenith-syntax-meta: #9f4f00; - --zenith-syntax-symbol: #b0006d; - --zenith-flow-space: 24px; - --zenith-panel-radius: var(--zenith-radius); - --zenith-control-radius: var(--zenith-radius-small); - --zenith-copy-size: 30px; - --zenith-toolbar-height: 36px; - --zenith-code-padding-block: 12px; - --zenith-code-padding-inline: 14px; - --zenith-table-padding-block: 12px; - --zenith-table-padding-inline: 16px; - --zenith-brand-gradient: linear-gradient(110deg, #512bd4 0%, #7150e8 56%, #34c9f5 100%); - --zenith-shadow-small: 0 2px 8px rgba(41, 27, 69, 0.07); - --zenith-shadow-medium: 0 12px 30px rgba(41, 27, 69, 0.12); - --zenith-radius-small: 5px; - --zenith-radius: 8px; - --zenith-header-height: 78px; - --zenith-header-bar-height: 58px; - --zenith-header-inset: 10px; - --zenith-header-inline-inset: clamp(10px, 1vw, 18px); - --zenith-content-width: 1200px; - --zenith-docs-width: 1760px; - --zenith-page-gutter: clamp(16px, 1.25vw, 40px); - --zenith-column-gap: clamp(20px, 1.5vw, 28px); - --zenith-sidebar-width: clamp(240px, 18vw, 300px); - --zenith-affix-width: 14%; - --zenith-api-sidebar-width: clamp(280px, 21vw, 340px); - --zenith-scrollbar-size: 8px; - --zenith-scrollbar-inset: 2px; - --zenith-scrollbar-edge-gap: 4px; - --zenith-scrollbar-min-thumb: 36px; - --zenith-scrollbar-thumb: color-mix(in srgb, var(--zenith-text-faint) 62%, transparent); - --zenith-scrollbar-thumb-hover: color-mix(in srgb, var(--zenith-text-soft) 82%, transparent); - --zenith-ease: cubic-bezier(0.22, 1, 0.36, 1); - --bs-body-font-family: "Aptos", "Segoe UI Variable Text", sans-serif; - --bs-body-color: var(--zenith-text); - --bs-body-bg: var(--zenith-surface); - --bs-link-color: var(--zenith-link); - --bs-link-color-rgb: 81, 43, 212; - --bs-link-hover-color: var(--zenith-link-hover); - --bs-link-hover-color-rgb: 118, 82, 232; - --bs-border-color: var(--zenith-border); - --bs-border-radius: var(--zenith-radius-small); -} - -[data-bs-theme="dark"] { - --zenith-purple-700: #b9a5ff; - --zenith-magenta-600: #d1c4ff; - --zenith-text: #f5f1fa; - --zenith-text-soft: #b9b1c4; - --zenith-text-faint: #81798d; - --zenith-surface: #100d16; - --zenith-surface-soft: #17121f; - --zenith-surface-tint: #1d1728; - --zenith-border: #312940; - --zenith-border-strong: #463a5a; - --zenith-code-surface: #191621; - --zenith-code-toolbar: #211d2a; - --zenith-code-border: #393243; - --zenith-code-text: #e4dfea; - --zenith-code-muted: #aaa1b5; - --zenith-code-hover: #2d2737; - --zenith-code-accent: #b9a5ff; - --zenith-code-accent-border: rgba(185, 165, 255, 0.42); - --zenith-code-success: #70cdb5; - --zenith-inline-code: #b69cff; - --zenith-inline-code-background: rgba(155, 123, 255, 0.13); - --zenith-shadow-small: 0 2px 8px rgba(0, 0, 0, 0.24); - --zenith-shadow-medium: 0 12px 30px rgba(0, 0, 0, 0.34); - --zenith-table-surface: #17131e; - --zenith-table-header: #211b2b; - --zenith-table-stripe: #1b1624; - --zenith-table-hover: #241d30; - --zenith-table-border: #393044; - --zenith-table-text: #c0b8ca; - --zenith-table-heading: #f1edf6; - --zenith-header-surface: rgba(16, 13, 22, 0.95); - --zenith-link: #b9a5ff; - --zenith-link-hover: #d1c4ff; - --zenith-nav-active: #f7f3ff; - --zenith-search-surface: #191421; - --zenith-search-border: #312940; - --zenith-info: #8fa2ff; - --zenith-success: #70cdb5; - --zenith-warning: #ffb16f; - --zenith-danger: #ff8fa3; - --zenith-syntax-keyword: #c586c0; - --zenith-syntax-literal: #569cd6; - --zenith-syntax-string: #ce9178; - --zenith-syntax-type: #4ec9b0; - --zenith-syntax-function: #dcdcaa; - --zenith-syntax-variable: #9cdcfe; - --zenith-syntax-comment: #6a9955; - --zenith-syntax-number: #b5cea8; - --zenith-syntax-meta: #d7ba7d; - --zenith-syntax-symbol: #c8c8c8; - --bs-body-color: var(--zenith-text); - --bs-body-bg: var(--zenith-surface); + color-scheme: dark; + scroll-behavior: auto; + --zenith-state-duration: 180ms; + --zenith-press-duration: 60ms; + --zenith-panel-duration: 280ms; + --zenith-state-ease: cubic-bezier(.2, 0, .2, 1); + --zenith-canvas: #101216; + --zenith-surface: #181b21; + --zenith-graphite: #262a32; + --zenith-border: #2d323b; + --zenith-text: #f2f3f5; + --zenith-body: #d0d4dc; + --zenith-muted: #a0a8b5; + --zenith-link: #dce5f2; + --zenith-code: #0d0f13; + --zenith-focus: #cad5e5; + --zenith-radius: 10px; + --zenith-header-height: 80px; + --zenith-width: 1560px; + --zenith-sidebar-width: 240px; + --zenith-outline-width: 176px; + --zenith-gap: 48px; + --zenith-gutter: 40px; + --bs-body-font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; + --bs-font-monospace: "SFMono-Regular", Consolas, "Liberation Mono", monospace; + --bs-body-bg: var(--zenith-canvas); + --bs-body-bg-rgb: 16, 18, 22; + --bs-body-color: var(--zenith-body); + --bs-body-color-rgb: 208, 212, 220; + --bs-emphasis-color: var(--zenith-text); + --bs-emphasis-color-rgb: 242, 243, 245; + --bs-heading-color: var(--zenith-text); + --bs-secondary-color: var(--zenith-muted); + --bs-secondary-color-rgb: 160, 168, 181; + --bs-secondary-bg: var(--zenith-graphite); + --bs-secondary-bg-rgb: 38, 42, 50; + --bs-tertiary-color: var(--zenith-muted); + --bs-tertiary-bg: var(--zenith-surface); + --bs-tertiary-bg-rgb: 24, 27, 33; --bs-link-color: var(--zenith-link); - --bs-link-color-rgb: 185, 165, 255; - --bs-link-hover-color: var(--zenith-link-hover); - --bs-link-hover-color-rgb: 209, 196, 255; + --bs-link-color-rgb: 220, 229, 242; + --bs-link-hover-color: var(--zenith-text); + --bs-link-hover-color-rgb: 242, 243, 245; --bs-border-color: var(--zenith-border); + --bs-border-color-translucent: var(--zenith-border); + --bs-border-radius: var(--zenith-radius); + --bs-code-color: var(--zenith-text); + --bs-highlight-color: var(--zenith-text); + --bs-highlight-bg: var(--zenith-graphite); } -/* ========================================================================== - Base and typography - ========================================================================== */ - +/* Page and typography */ html { - scroll-padding-top: calc(var(--zenith-header-height) + 24px); -} - -@supports not selector(::-webkit-scrollbar) { - * { - scrollbar-color: var(--zenith-scrollbar-thumb) transparent; - scrollbar-width: thin; - } -} - -*::-webkit-scrollbar { - width: var(--zenith-scrollbar-size); - height: var(--zenith-scrollbar-size); -} - -*::-webkit-scrollbar-track, -*::-webkit-scrollbar-corner { - background: transparent; -} - -*::-webkit-scrollbar-thumb { - background-color: var(--zenith-scrollbar-thumb); - background-clip: padding-box; - border: var(--zenith-scrollbar-inset) solid transparent; - border-radius: 999px; + width: 100%; + margin: 0; + padding: 0; + background: var(--zenith-canvas); + overflow-x: clip; + overflow-y: auto; + overscroll-behavior-y: none; + scroll-padding-top: var(--zenith-header-height); + scrollbar-color: #626a78 var(--zenith-canvas); + scrollbar-width: thin; } - *::-webkit-scrollbar-thumb:hover { - background-color: var(--zenith-scrollbar-thumb-hover); - } - -body { +body.zenith-theme { + width: 100%; min-width: 0; - padding-top: var(--zenith-header-height) !important; - background: var(--zenith-surface); - color: var(--zenith-text); - font-family: var(--bs-body-font-family); + min-height: 100dvh; + margin: 0; + padding-top: var(--zenith-header-height); + background: var(--zenith-canvas); font-size: 16px; - line-height: 1.68; - letter-spacing: 0; + line-height: 1.75; -webkit-font-smoothing: antialiased; - text-rendering: optimizeLegibility; } ::selection { - background: rgba(198, 0, 189, 0.18); + background: #414b5b; color: var(--zenith-text); } +:focus-visible { + outline: 2px solid var(--zenith-focus); + outline-offset: 3px; +} + a { - color: var(--zenith-link); - text-decoration-color: rgba(81, 43, 212, 0.3); text-underline-offset: 3px; - transition: color 160ms ease, text-decoration-color 160ms ease; + text-decoration-color: #737f91; } - a:hover, - a:focus { - color: var(--zenith-link-hover); - text-decoration: none; - } +a:hover { + text-decoration-color: currentColor; +} -h1, -h2, -h3, -h4, -h5, -h6 { - color: var(--zenith-text); - font-family: "Aptos Display", "Segoe UI Variable Display", "Bahnschrift", sans-serif; - font-weight: 750; - letter-spacing: 0; +article a.external[href]::after { + content: none; } -img { - max-width: 100%; +article { + overflow-wrap: anywhere; } -:focus-visible { - outline: 3px solid rgba(113, 56, 232, 0.42) !important; - outline-offset: 3px; +article :is(h1, h2, h3, h4, h5, h6) { + color: var(--zenith-text); + font-weight: 650; + line-height: 1.3; } -/* ========================================================================== - Global header - ========================================================================== */ +body.zenith-theme > main > .content > article [id] { + scroll-margin-top: 24px; +} -body > header.bg-body, -body > header { - position: fixed !important; - top: var(--zenith-header-inset); - left: 50%; - z-index: 1030; - width: min(calc(100% - (2 * var(--zenith-header-inline-inset))), var(--zenith-docs-width)); - height: var(--zenith-header-bar-height); - background: var(--zenith-header-surface) !important; - border: 1px solid var(--zenith-header-border) !important; - border-radius: var(--zenith-radius); - box-shadow: 0 8px 24px rgba(20, 18, 32, 0.08); - backdrop-filter: blur(16px) saturate(1.25); - -webkit-backdrop-filter: blur(16px) saturate(1.25); - transform: translateX(-50%); - transition: background-color 240ms ease, border-color 240ms ease, box-shadow 240ms ease; +article h1 { + margin: 0 0 24px; + font-size: clamp(32px, 3vw, 42px); + letter-spacing: -1.2px; } - body > header.is-scrolled { - box-shadow: 0 12px 32px rgba(20, 18, 32, 0.13); - } +article h2 { + margin: 40px 0 18px; + padding-bottom: 12px; + border-bottom: 1px solid var(--zenith-border); + font-size: 25px; + letter-spacing: -.5px; +} -[data-bs-theme="dark"] body > header.is-scrolled { - box-shadow: 0 14px 34px rgba(0, 0, 0, 0.38); +article h3 { + margin: 30px 0 14px; + font-size: 20px; } -.zenith-reading-progress { - position: absolute; - right: 8px; - bottom: -1px; - left: 8px; - z-index: 2; - height: 2px; - overflow: hidden; - pointer-events: none; +article :is(h4, h5, h6) { + margin: 24px 0 12px; + font-size: 17px; } - .zenith-reading-progress > span { - display: block; - width: 100%; - height: 100%; - background: var(--zenith-brand-gradient); - box-shadow: 0 0 10px rgba(81, 43, 212, 0.34); - transform: scaleX(0); - transform-origin: left center; - will-change: transform; - } +article :is(p, ul, ol, dl) { + margin-bottom: 20px; +} -@supports (animation-timeline: scroll()) { - .zenith-reading-progress > span { - animation: zenith-reading-progress linear both; - animation-timeline: scroll(root block); - animation-range: 0% 100%; - } +article :is(ul, ol) { + padding-left: 24px; } -[data-bs-theme="dark"] body > header.bg-body, -[data-bs-theme="dark"] body > header { - background: var(--zenith-header-surface) !important; - border-color: var(--zenith-border) !important; +article li { + margin-block: 6px; } -body[data-layout="landing"] > header.bg-body, -body[data-layout="landing"] > header { - background: rgba(251, 250, 252, 0.58) !important; - border-color: rgba(35, 30, 46, 0.08) !important; - box-shadow: 0 8px 24px rgba(41, 27, 69, 0.045); +article strong { + color: var(--zenith-text); + font-weight: 600; } -[data-bs-theme="dark"] body[data-layout="landing"] > header.bg-body, -[data-bs-theme="dark"] body[data-layout="landing"] > header { - background: rgba(16, 13, 22, 0.5) !important; - border-color: rgba(185, 165, 255, 0.1) !important; - box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08); +article :is(img, video, svg) { + max-width: 100%; } -body[data-layout="landing"] > header.is-scrolled { - background: rgba(251, 250, 252, 0.88) !important; - border-color: rgba(35, 30, 46, 0.12) !important; - box-shadow: 0 12px 32px rgba(41, 27, 69, 0.11); +article img { + height: auto; + border-radius: var(--zenith-radius); } -[data-bs-theme="dark"] body[data-layout="landing"] > header.is-scrolled { - background: rgba(16, 13, 22, 0.84) !important; - border-color: rgba(185, 165, 255, 0.16) !important; - box-shadow: 0 14px 34px rgba(0, 0, 0, 0.28); +article blockquote { + margin: 24px 0; + padding: 4px 0 4px 20px; + border-left: 2px solid var(--zenith-muted); + color: var(--zenith-muted); } -.navbar { - width: 100%; - height: 100%; - min-height: 0; - padding: 0 !important; +article blockquote > :last-child { + margin-bottom: 0; } - .navbar > .container-xxl { - align-items: center; - width: 100%; - height: 100%; - max-width: var(--zenith-content-width) !important; - min-height: 0; - margin: 0 auto; - padding: 0 18px !important; - } +hr { + margin: 28px 0; + opacity: 1; + border-color: var(--zenith-border); +} -.navbar-brand { - position: relative; - display: inline-flex; - flex: 0 0 auto; - align-items: center; - margin-right: 10px !important; - padding: 0 !important; +/* Navigation and command search */ +.zenith-theme > .site-header { + position: fixed; + inset: 0 0 auto; + z-index: 1030; + height: var(--zenith-header-height); + min-height: var(--zenith-header-height); + background: rgb(19 24 32 / 98%); + border-bottom: 1px solid #3b4655; + box-shadow: 0 6px 24px #0003; + backdrop-filter: blur(18px); + -webkit-backdrop-filter: blur(18px); } -#logo { - display: block; - width: var(--zenith-logo-width); - height: 36px; - object-fit: contain; - object-position: left center; - transform-origin: left center; - transition: filter 220ms ease, transform 220ms var(--zenith-ease); +.zenith-theme .container-xxl { + max-width: var(--zenith-width); + padding-inline: var(--zenith-gutter); } -.navbar-brand:hover #logo, -.navbar-brand:focus-visible #logo { - filter: drop-shadow(0 5px 10px rgba(81, 43, 212, 0.18)); - transform: translateY(-1px) scale(1.012); +.site-nav { + display: grid; + grid-template-columns: auto auto minmax(0, 1fr); + align-items: center; + gap: 28px; + min-height: var(--zenith-header-height); } -.navbar-brand:active #logo { - transform: scale(0.992); +.site-nav .navbar-brand { + justify-self: start; + margin: 0; + padding: 18px 0; } -.navbar-collapse, -#navbar { - min-width: 0; +.site-nav #logo { + width: auto; + height: 40px; } -#navbar { +#navbar .navbar-nav { display: flex; - flex: 1 1 auto; + flex-direction: row; align-items: center; - justify-content: flex-end; - gap: 6px; + gap: 8px; + margin: 0; + padding: 0; + list-style: none; } - #navbar .navbar-nav { - display: flex; - order: 1; - flex: 0 1 auto; - align-items: center; - gap: 2px; - margin-right: auto; - } - - #navbar .nav-link { - position: relative; - display: inline-flex; - align-items: center; - height: 36px; - padding: 0 12px !important; - color: var(--zenith-nav-text) !important; - border-radius: 0 !important; - font-size: 14px; - font-weight: 600; - line-height: 1; - letter-spacing: 0; - text-decoration: none; - transition: color 180ms ease, background-color 180ms ease, transform 180ms var(--zenith-ease); - } - -[data-bs-theme="dark"] #navbar .nav-link { - color: var(--zenith-text-soft) !important; +#navbar .nav-link { + padding: 11px 19px; + background: #252e3b; + border: 1px solid #47566a; + border-radius: 4px; + color: #e1e9f5; + font: 600 15px/1.4 var(--bs-body-font-family); + letter-spacing: 0; + text-decoration: none; } -#navbar .nav-link::after { - content: ""; - position: absolute; - right: 12px; - bottom: 4px; - left: 12px; - height: 2px; - background: var(--zenith-accent); - opacity: 0; - transform: scaleX(0.3); - transition: opacity 160ms ease, transform 160ms ease; +#navbar .nav-link:hover { + color: #fff; + background: #3c506b; + border-color: #7d98bb; } -#navbar .nav-link:hover, #navbar .nav-link.active { - color: var(--zenith-nav-active) !important; -} - -[data-bs-theme="dark"] #navbar .nav-link:hover, -[data-bs-theme="dark"] #navbar .nav-link.active { - color: var(--zenith-nav-active) !important; + color: #142033; + background: #d7e7fb; + border-color: #d7e7fb; + box-shadow: none; } -#navbar .nav-link:hover::after, -#navbar .nav-link.active::after { - opacity: 1; - transform: scaleX(1); +#navbar .nav-link:focus-visible { + outline-offset: -3px; } -#navbar form.search { - order: 2 !important; - width: 210px; - margin: 0 !important; +#navbar .nav-link.active:focus-visible { + outline-color: #26394f; } - #navbar form.search > i { - left: 12px; - color: var(--zenith-text-faint); - } - - #navbar form.search > input { - width: 100%; - height: 36px; - padding-left: 36px; - background: var(--zenith-search-surface); - color: var(--zenith-text); - border: 1px solid var(--zenith-search-border); - border-radius: 6px; - box-shadow: none; - font-size: 13px; - } - - #navbar form.search.zenith-search { - position: relative; - display: flex; - width: 36px; - min-width: 36px; - height: 36px; - align-items: center; - overflow: hidden; - border-radius: 6px; - transition: width 300ms var(--zenith-ease), box-shadow 180ms ease; - } +/* The site owns its actions and has a single appearance. */ +#navbar .icons { display: none; } - #navbar form.search.zenith-search.is-expanded { - width: 230px; - box-shadow: 0 8px 22px rgba(20, 15, 30, 0.1); - } - - #navbar form.search.zenith-search > i { - display: none; - } - - #navbar form.search.zenith-search > input { - position: absolute; - inset: 0; - z-index: 0; - width: 100%; - padding-right: 12px; - padding-left: 38px; - opacity: 0; - pointer-events: none; - transform: translateX(8px); - transition: opacity 180ms ease, transform 300ms var(--zenith-ease), border-color 180ms ease, background-color 180ms ease; - } - - #navbar form.search.zenith-search.is-expanded > input { - opacity: 1; - pointer-events: auto; - transform: translateX(0); - } - -.zenith-search-toggle { - position: relative; - z-index: 1; - display: inline-flex; - width: 36px; - height: 36px; - flex: 0 0 36px; +.site-actions { + display: flex; align-items: center; - justify-content: center; - padding: 0; - color: var(--zenith-text-soft); - background: transparent; - border: 1px solid transparent; - border-radius: 6px; - font-size: 15px; - transition: color 180ms ease, background-color 180ms ease, border-color 180ms ease, transform 220ms var(--zenith-ease); + justify-content: flex-end; + gap: 12px; } - .zenith-search-toggle:hover, - .zenith-search-toggle:focus-visible { - color: var(--zenith-accent); - background: transparent; - border-color: transparent; - } - -#navbar form.search.zenith-search.is-expanded .zenith-search-toggle { - color: var(--zenith-accent); - border-color: transparent; - transform: rotate(-8deg) scale(0.94); +.search-launcher { + display: flex; + align-items: center; + gap: 10px; + min-height: 44px; + padding: 0 14px; + border: 1px solid #52647b; + border-radius: 4px; + background: #212d3d; + color: #edf3fb; + font: 500 14px/1 var(--bs-body-font-family); + cursor: pointer; } -#navbar form.search.zenith-search.is-loading .zenith-search-toggle { - color: var(--zenith-text-faint); +.search-launcher > i { font-size: 15px; } +.search-launcher:hover { background: #344965; border-color: #8baad1; } + +.search-launcher kbd { + margin-left: 6px; + padding: 5px 7px; + border: 1px solid #536781; + border-radius: 2px; + background: #182231; + color: #bfd2eb; + font: 11px/1 var(--bs-font-monospace); + letter-spacing: 0; } -.navbar .icons { - order: 3 !important; - display: flex; - flex: 0 0 auto; - align-items: center; - gap: 6px; +.source-link { + display: grid; + place-items: center; + width: 44px; + min-height: 44px; + border: 1px solid #3e4b5e; + border-radius: 4px; + background: #202936; + color: #d2deee; + font-size: 19px; + text-decoration: none; } - .navbar .icons .zenith-theme-toggle { - order: 1; - } +.source-link:hover { color: #fff; background: #354862; } - .navbar .icons > a.btn { - order: 2; - } +.menu-toggle { + display: none; + width: 40px; + height: 44px; + padding: 10px; + border: 0; + background: none; + color: var(--zenith-text); +} - .navbar .icons .btn, - .navbar .icons > a.btn { - display: inline-flex !important; - align-items: center; - justify-content: center; - min-width: 36px; - height: 36px; - padding: 0 9px !important; - color: var(--zenith-text-soft) !important; - background: transparent !important; - border: 0 !important; - border-radius: 6px !important; - box-shadow: none !important; - transition: color 180ms ease, background-color 180ms ease, transform 180ms var(--zenith-ease) !important; - } +.menu-toggle span { + display: block; + height: 1px; + margin: 6px 0; + background: currentColor; + transition: transform var(--zenith-state-duration) var(--zenith-state-ease); +} - .zenith-search-toggle > i, - .navbar .icons .btn > i, - .navbar .icons > a.btn > i { - display: inline-flex; - width: 16px; - height: 16px; - align-items: center; - justify-content: center; - font-size: 16px; - line-height: 1; - transform-origin: center; - } - - .zenith-search-toggle > i::before, - .navbar .icons .btn > i::before, - .navbar .icons > a.btn > i::before { - display: block; - line-height: 1; - vertical-align: 0; - } - - .navbar .icons .zenith-theme-toggle > i { - transition: color 180ms ease, transform 220ms var(--zenith-ease); - } +.menu-open .menu-toggle span:first-child { transform: translateY(3.5px) rotate(45deg); } +.menu-open .menu-toggle span:last-child { transform: translateY(-3.5px) rotate(-45deg); } - .navbar .icons .btn.zenith-theme-toggle:hover, - .navbar .icons .btn.zenith-theme-toggle:focus-visible { - color: var(--zenith-accent) !important; - background: transparent !important; - transform: none !important; - } +.site-search { + width: min(720px, calc(100% - 32px)); + max-width: none; + max-height: calc(100dvh - 64px); + margin: min(12vh, 100px) auto auto; + padding: 0; + overflow: hidden; + border: 1px solid #555f70; + border-radius: 4px; + background: #171b22; + color: var(--zenith-text); + box-shadow: 0 32px 120px #0009; +} - .navbar .icons .zenith-theme-toggle:hover > i { - transform: rotate(12deg) scale(1.08); - } +.site-search::backdrop { + background: #07090dbd; + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); +} - .navbar .icons .btn:hover, - .navbar .icons > a.btn:hover { - color: var(--zenith-accent) !important; - background: var(--zenith-accent-soft) !important; - transform: translateY(-1px); - } +.site-search[open] { + display: flex; + flex-direction: column; + transform-origin: 50% 0; + animation: zenith-panel-in var(--zenith-panel-duration) cubic-bezier(.16, 1, .3, 1); +} - .navbar .icons > a.btn:hover, - .navbar .icons > a.btn:focus-visible { - color: var(--zenith-accent) !important; - background: transparent !important; - transform: none !important; - } +.site-search[open]::backdrop { + animation: zenith-backdrop-in var(--zenith-panel-duration) ease-out; +} - .navbar .icons > a.btn > i { - transition: color 180ms ease, transform 220ms var(--zenith-ease); - } +.site-search.is-closing { animation: zenith-panel-out 160ms ease-in both; } +.site-search.is-closing::backdrop { animation: zenith-backdrop-in 160ms ease-in reverse both; } - .navbar .icons > a.btn:hover > i { - transform: scale(1.08); - } +html:has(.site-search[open]), +body:has(.site-search[open]) { overflow: hidden; } - .navbar .icons .zenith-theme-toggle.is-theme-leaving > i { - animation: zenith-theme-icon-leave 120ms ease-in forwards; - } +.search-input-row { + display: grid; + flex: 0 0 auto; + grid-template-columns: 20px minmax(0, 1fr) 36px; + align-items: center; + gap: 18px; + min-height: 88px; + padding: 20px 24px; + border-bottom: 1px solid #3a4351; +} - .navbar .icons .zenith-theme-toggle.is-theme-entering > i { - animation: zenith-theme-icon-enter 260ms var(--zenith-ease) both; - } +.search-input-row > i { color: #a6b2c4; font-size: 20px; } +.search-input-row:focus-within { border-bottom-color: #75849a; } -@keyframes zenith-theme-icon-leave { - to { - opacity: 0; - transform: rotate(70deg) scale(0.52); - } +#site-search-input { + width: 100%; + min-width: 0; + padding: 6px 0; + border: 0; + outline: none; + background: none; + color: var(--zenith-text); + font: 400 21px/1.5 var(--bs-body-font-family); } -@keyframes zenith-theme-icon-enter { - from { - opacity: 0; - transform: rotate(-70deg) scale(0.52); - } - - 68% { - opacity: 1; - transform: rotate(8deg) scale(1.12); - } +#site-search-input::placeholder { color: #99a3b3; } +#site-search-input::-webkit-search-cancel-button { display: none; } - to { - opacity: 1; - transform: rotate(0) scale(1); - } +#search-close { + min-height: 32px; + padding: 4px 6px; + border: 1px solid #424c5b; + border-radius: 3px; + background: #202630; + color: #b4bfce; + font: 11px/1.5 var(--bs-font-monospace); + cursor: pointer; } -.dropdown-menu { - padding: 5px !important; - background: var(--zenith-surface) !important; - border: 1px solid var(--zenith-border) !important; - border-radius: 7px !important; - box-shadow: var(--zenith-shadow-medium) !important; +.search-scroll { + flex: 1 1 auto; + min-height: 0; + max-height: min(55vh, 520px); + padding: 18px 12px 12px; + overflow-y: auto; + overscroll-behavior: contain; + scrollbar-width: thin; } -.dropdown-item { - color: var(--zenith-text) !important; - border-radius: 5px !important; +#search-status { + margin: 0 12px 12px; + color: #a0acbc; + font: 12px/1.5 var(--bs-body-font-family); } - .dropdown-item:hover, - .dropdown-item:focus { - color: var(--zenith-purple-700) !important; - background: rgba(113, 56, 232, 0.08) !important; - } - -/* ========================================================================== - Landing layout reset - ========================================================================== */ +#site-search-results { margin: 0; padding: 0; list-style: none; } -body[data-layout="landing"] { - overflow-x: clip; - padding-top: 0 !important; +.search-shortcuts > a, +#site-search-results a { + display: block; + padding: 14px 16px; + border-radius: 3px; + color: var(--zenith-text); + text-decoration: none; + overflow-wrap: anywhere; } - body[data-layout="landing"] > main.container-xxl { - width: 100%; - max-width: none !important; - margin: 0 !important; - padding: 0 !important; - } - - body[data-layout="landing"] main > .content { - width: 100%; - max-width: none; - margin: 0; - padding: 0; - } +.search-shortcuts > a, +.search-result-heading { + display: flex; + align-items: baseline; + justify-content: space-between; + gap: 20px; +} - body[data-layout="landing"] .actionbar, - body[data-layout="landing"] .next-article, - body[data-layout="landing"] main > .affix { - display: none !important; - } +.search-shortcuts > a:hover, +.search-shortcuts > a:focus-visible, +#site-search-results a:hover, +#site-search-results a:focus-visible { background: #2b3441; } - body[data-layout="landing"] article { - width: 100%; - max-width: none; - margin: 0; - padding: 0; - } +.search-result-heading strong { font-size: 16px; font-weight: 500; } +.site-search small { flex-shrink: 0; color: #a5b4c8; font: 10px/1.5 var(--bs-font-monospace); text-transform: uppercase; } +#site-search-results p { margin: 7px 0 0; color: #9faaba; font-size: 12px; line-height: 1.6; } -.landing-page { +.search-more { width: 100%; + padding: 12px; + border: 0; + background: #222a35; color: var(--zenith-text); + font-size: 13px; + cursor: pointer; +} + +.search-footer { + display: flex; + flex: 0 0 auto; + gap: 24px; + padding: 12px 24px; + border-top: 1px solid #303846; + color: #929eaf; + font-size: 11px; } -.landing-shell { - width: calc(100% - clamp(36px, 4vw, 64px)); - max-width: 1440px; - margin: 0 auto; +.search-footer kbd { padding: 0 4px; background: none; color: #c2ccda; font-size: 11px; } + +.form-control { + min-height: 40px; + background: var(--zenith-canvas); + border-color: var(--zenith-border); + border-radius: var(--zenith-radius); + color: var(--zenith-text); + font-size: 14px; } -.landing-page p { - color: var(--zenith-text-soft); +.form-control:focus { + background: var(--zenith-canvas); + border-color: var(--zenith-focus); + color: var(--zenith-text); + box-shadow: none; } -/* ========================================================================== - Landing hero - ========================================================================== */ +.form-control::placeholder, .filter > i { color: var(--zenith-muted); opacity: 1; } -.hero-copy { +/* Document shell: navigation, article, and on-page outline */ +body.zenith-theme > main.container-xxl { + display: grid; + grid-template-columns: var(--zenith-sidebar-width) minmax(0, 1fr) var(--zenith-outline-width); + column-gap: var(--zenith-gap); + align-items: start; + flex: 1; + padding-block: 0; +} + +body.zenith-theme > main.container-xxl > .content { + display: block; + grid-column: 2; + width: 100%; min-width: 0; - padding: 24px 0; + margin: 0; + padding-block: 36px 80px; } - .hero-copy h1 { - max-width: 660px; - margin: 0 0 22px; - color: var(--zenith-navy-900); - border: 0; - font-size: 53px; - font-weight: 800; - line-height: 1.04; - letter-spacing: 0; - } +body.zenith-theme > main.container-xxl > :is(.toc-offcanvas, .affix) { + position: sticky; + top: var(--zenith-header-height); + width: 100%; + min-width: 0; + max-width: none; + max-height: calc(100dvh - var(--zenith-header-height)); + padding: 0; + scrollbar-width: thin; +} -[data-bs-theme="dark"] .hero-copy h1 { - color: #f3f6ff; +body.zenith-theme > main.container-xxl > .affix { + grid-column: 3; + padding-top: 42px; } -.hero-copy h1 span { - color: var(--zenith-magenta-600); - background: var(--zenith-brand-gradient); - -webkit-background-clip: text; - background-clip: text; - -webkit-text-fill-color: transparent; +body.zenith-theme > main.container-xxl > .toc-offcanvas { + height: calc(100dvh - var(--zenith-header-height)); + padding: 32px 20px 28px 0; + border-right: 1px solid var(--zenith-border); } -.hero-lede { - max-width: 590px; - margin: 0 0 26px; - font-size: 17px; - line-height: 1.75; +.zenith-theme #tocOffcanvas { + --bs-offcanvas-bg: var(--zenith-surface); + --bs-offcanvas-width: min(320px, 90vw); + --bs-offcanvas-color: var(--zenith-body); + --bs-offcanvas-transition: transform 280ms cubic-bezier(.16, 1, .3, 1); } -.hero-actions { +.zenith-theme #tocOffcanvas .offcanvas-body { display: flex; - align-items: center; - flex-wrap: wrap; - gap: 12px; + flex-direction: column; } -.landing-button { - display: inline-flex; - align-items: center; - justify-content: center; - min-height: 46px; - padding: 0 19px; - border: 1px solid transparent; - border-radius: 6px; +#toc { + flex: 1; + min-height: 0; font-size: 14px; - font-weight: 750; - line-height: 1; - text-decoration: none !important; - white-space: nowrap; - transition: color 170ms ease, background 170ms ease, border-color 170ms ease, box-shadow 170ms ease, transform 170ms ease; -} - -.landing-button-primary { - color: #ffffff !important; - background: var(--zenith-brand-gradient); - box-shadow: 0 8px 18px rgba(181, 12, 189, 0.22); -} - - .landing-button-primary:hover { - color: #ffffff !important; - box-shadow: 0 11px 24px rgba(181, 12, 189, 0.3); - transform: translateY(-2px); - } - -.landing-button-secondary { - color: var(--zenith-navy-900) !important; - background: rgba(255, 255, 255, 0.86); - border-color: rgba(30, 44, 76, 0.13); - box-shadow: var(--zenith-shadow-small); -} - -[data-bs-theme="dark"] .landing-button-secondary { - color: var(--zenith-text) !important; - background: rgba(27, 29, 38, 0.9); - border-color: var(--zenith-border-strong); -} - -.landing-button-secondary:hover { - color: var(--zenith-purple-700) !important; - background: var(--zenith-surface); - border-color: rgba(113, 56, 232, 0.36); - transform: translateY(-2px); -} - -.backend-support { - display: flex; - align-items: center; - flex-wrap: wrap; - gap: 8px; - margin-top: 30px; -} - -.backend-label { - margin-right: 3px; - color: var(--zenith-text-faint); - font-size: 11px; - font-weight: 650; -} - -.backend-pill { - display: inline-flex; - align-items: center; - min-height: 26px; - padding: 3px 10px; - color: #384966; - background: rgba(255, 255, 255, 0.82); - border: 1px solid rgba(26, 46, 79, 0.09); - border-radius: 999px; - font-size: 10px; - font-weight: 750; - line-height: 1; -} - -[data-bs-theme="dark"] .backend-pill { - color: var(--zenith-text-soft); - background: rgba(24, 26, 34, 0.82); - border-color: var(--zenith-border); -} - -/* ========================================================================== - Documentation shell - ========================================================================== */ - -body:not([data-layout="landing"]) > main.container-xxl { - display: grid; - grid-template-columns: var(--zenith-sidebar-width) minmax(0, 1fr) var(--zenith-affix-width); - width: 100%; - max-width: var(--zenith-docs-width) !important; - min-height: calc(100vh - var(--zenith-header-height)); - margin: 0 auto; - padding: 0 var(--zenith-page-gutter) !important; - column-gap: var(--zenith-column-gap); } -body:is([data-yaml-mime="ManagedReference"], [data-zenith-api]) > main.container-xxl { - grid-template-columns: var(--zenith-api-sidebar-width) minmax(0, 1fr) var(--zenith-api-sidebar-width); +#toc .filter { + margin-bottom: 22px; } -body:not([data-layout="landing"]) > main.container-xxl > .toc-offcanvas { - width: 100% !important; - max-width: none; +#toc > .overflow-y-auto { + padding-right: 0; } -body:not([data-layout="landing"]) main > .content { - grid-column: 2; - min-width: 0; - width: auto; - margin-right: 0 !important; - margin-left: 0 !important; - padding: 24px 0 70px; +#toc li { + margin-block: 3px; + border: 0; } -body:not([data-layout="landing"]) main > .affix { - grid-column: 3; - min-width: 0; - width: 100% !important; +#toc li > a { + display: block; max-width: 100%; - padding-top: 16px; -} - -body[data-yaml-mime="ManagedReference"]:not([data-search]) > main.container-xxl > .affix { - position: sticky; - top: var(--zenith-header-height); - align-self: start; - height: calc(100vh - var(--zenith-header-height)); - max-height: none; - overflow: visible; -} - -.actionbar { - min-height: 34px; - margin-bottom: 18px; -} - -.breadcrumb { - margin: 0; - padding: 0; - background: transparent; - font-size: 12px; -} - -.breadcrumb-item, -.breadcrumb-item a { - color: var(--zenith-text-faint); - text-decoration: none !important; -} - - .breadcrumb-item.active, - .breadcrumb-item a:hover { - color: var(--zenith-purple-700); - } - - .breadcrumb-item + .breadcrumb-item::before { - color: var(--zenith-border-strong); - } - -body:not([data-layout="landing"]) article { - width: 100%; - margin: 0 auto; -} - -article > h1:first-child, -article > h1:first-of-type { - margin-top: 0; -} - -article h1 { - margin: 0 0 18px; - padding: 0 0 16px; - border-bottom: 1px solid var(--zenith-border); - font-size: 36px; - font-weight: 800; - line-height: 1.18; -} - -article h2 { - position: relative; - margin: 42px 0 17px; - padding: 0 0 10px; - border-bottom: 1px solid var(--zenith-border); - font-size: 25px; - line-height: 1.25; -} - - article h2::after { - content: ""; - position: absolute; - bottom: -1px; - left: 0; - width: 52px; - height: 2px; - background: var(--zenith-brand-gradient); - border-radius: 2px; - transform: scaleX(1); - transform-origin: left center; - transition: transform 520ms var(--zenith-ease); - } - -html.zenith-motion-ready article h2.zenith-reveal:not(.is-visible)::after { - transform: scaleX(0); - transition: none; -} - -html.zenith-motion-ready article h2.is-visible::after { - transform: scaleX(1); -} - -article h3 { - margin: 30px 0 12px; - font-size: 19px; - line-height: 1.35; -} - -article h4 { - margin: 24px 0 10px; - font-size: 16px; -} - -article p, -article li, -article dd, -article td { - color: var(--zenith-text-soft); -} - -article p { - margin-bottom: 16px; + padding: 8px 11px; + border-radius: 6px; + color: var(--zenith-muted); + text-decoration: none; + line-height: 1.5; } -article strong { +#toc li > a:hover { + background: var(--zenith-surface); color: var(--zenith-text); - font-weight: 750; -} - -article ul, -article ol { - padding-left: 1.35rem; -} - -article li { - margin: 5px 0; -} - - article li::marker { - color: var(--zenith-purple-700); - } - -article img:not(.svg) { - border-radius: 7px; -} - -article a:not(.btn):not(.landing-button) { - font-weight: 600; -} - -article .anchorjs-link { - display: none !important; -} - -article hr { - margin: 34px 0; - border-color: var(--zenith-border); - opacity: 1; } -article blockquote { - margin: 22px 0; - padding: 14px 18px; - color: var(--zenith-text-soft); - background: var(--zenith-surface-tint); - border-left: 3px solid var(--zenith-purple-700); - border-radius: 0 6px 6px 0; +#toc li.active:not(.expander) > a { + background: var(--zenith-graphite); + color: var(--zenith-text); + font-weight: 500; } - article blockquote > :last-child { - margin-bottom: 0; - } - -code { - padding: 0.14em 0.38em; - color: var(--zenith-inline-code); - background: var(--zenith-inline-code-background); - border-radius: 4px; - font-family: "Cascadia Code", "Cascadia Mono", Consolas, monospace; - font-size: 0.88em; +#toc li.expander > a { + color: var(--zenith-text); + font-weight: 500; } -article pre, -.codewrapper pre { - position: relative; - margin: 20px 0; - padding: 22px 24px; - overflow: auto; - color: var(--zenith-code-text); - background: var(--zenith-code-surface) !important; - border: 1px solid var(--zenith-code-border) !important; - border-radius: 6px !important; - box-shadow: none; - font-family: "Cascadia Code", "Cascadia Mono", Consolas, monospace; +#toc .toc-group-title { + display: block; + margin-top: 8px; + padding: 4px 11px; + color: var(--zenith-text); font-size: 13px; - line-height: 1.7; -} - -.doc-code-frame { - position: relative; - margin: var(--zenith-flow-space) 0; - overflow: hidden; - color: var(--zenith-code-text); - background: var(--zenith-code-surface); - border: 1px solid var(--zenith-code-border); - border-radius: var(--zenith-panel-radius); - transition: border-color 180ms ease, box-shadow 220ms ease; -} - - .doc-code-frame::before { - content: ""; - position: absolute; - top: 0; - right: 0; - left: 0; - z-index: 2; - height: 2px; - pointer-events: none; - background: var(--zenith-brand-gradient); - opacity: 0; - transform: scaleX(0.35); - transform-origin: left center; - transition: opacity 180ms ease, transform 360ms var(--zenith-ease); - } - - .doc-code-frame:hover, - .doc-code-frame:focus-within { - border-color: var(--zenith-code-accent-border); - box-shadow: 0 10px 26px rgba(35, 30, 46, 0.08); - } - -[data-bs-theme="dark"] .doc-code-frame:hover, -[data-bs-theme="dark"] .doc-code-frame:focus-within { - box-shadow: 0 12px 28px rgba(0, 0, 0, 0.22); -} - -.doc-code-frame:hover::before, -.doc-code-frame:focus-within::before { - opacity: 0.86; - transform: scaleX(1); -} - -.doc-code-toolbar { - display: flex; - height: var(--zenith-toolbar-height); - align-items: center; - padding: 0 4px 0 12px; - color: var(--zenith-code-muted); - background: var(--zenith-code-toolbar); - border-bottom: 1px solid var(--zenith-code-border); + font-weight: 600; + line-height: 1.5; } -.doc-code-language { - font-family: "Cascadia Code", "Cascadia Mono", Consolas, monospace; - font-size: 10px; - font-weight: 700; - text-transform: uppercase; -} +.contents-toggle { display: none; } -.doc-code-copy { - display: inline-flex; - width: var(--zenith-copy-size); - min-width: var(--zenith-copy-size); - height: var(--zenith-copy-size); +.contents-toggle, .contents-close { align-items: center; justify-content: center; - margin-left: auto; - padding: 0; - color: var(--zenith-code-muted); - background: var(--zenith-code-surface); - border: 1px solid var(--zenith-code-border); - border-radius: var(--zenith-control-radius); - font-family: Aptos, "Segoe UI Variable Text", sans-serif; - font-size: 12px; - font-weight: 600; + gap: 8px; + min-height: 40px; + padding: 8px 12px; + border: 1px solid #43536a; + border-radius: 4px; + background: #202b3a; + color: #e1ebf8; + font: 500 13px/1.5 var(--bs-body-font-family); cursor: pointer; - transition: color 160ms ease, background-color 160ms ease, border-color 160ms ease, transform 160ms var(--zenith-ease); -} - - .doc-code-copy:active { - transform: scale(0.92); - } - - .doc-code-copy i { - font-size: 13px; - } - - .doc-code-copy:hover { - color: var(--zenith-code-accent); - background: var(--zenith-code-hover); - border-color: var(--zenith-code-accent-border); - } - - .doc-code-copy.is-copied { - color: var(--zenith-code-success); - background: rgba(15, 118, 110, 0.1); - border-color: rgba(15, 118, 110, 0.28); - } - - .doc-code-copy.is-copied i { - animation: zenith-copy-confirm 320ms var(--zenith-ease) both; - } - - .doc-code-copy.is-failed { - color: #b42318; - background: rgba(180, 35, 24, 0.08); - border-color: rgba(180, 35, 24, 0.24); - } - -article .doc-code-frame > pre, -.codewrapper .doc-code-frame > pre { - margin: 0; - padding: var(--zenith-code-padding-block) var(--zenith-code-padding-inline); - background: transparent !important; - border: 0 !important; - border-radius: 0 !important; - box-shadow: none; -} - -article pre code, -.codewrapper pre code { - padding: 0; - color: inherit; - background: transparent; - border-radius: 0; - font-size: inherit; -} - -.shiki, -.shiki span { - color: var(--shiki-light, var(--zenith-code-text)); - background-color: transparent !important; - font-style: var(--shiki-light-font-style, inherit); - font-weight: var(--shiki-light-font-weight, inherit); - text-decoration: var(--shiki-light-text-decoration, inherit); -} - -[data-bs-theme="dark"] .shiki, -[data-bs-theme="dark"] .shiki span { - color: var(--shiki-dark, var(--zenith-code-text)); - font-style: var(--shiki-dark-font-style, inherit); - font-weight: var(--shiki-dark-font-weight, inherit); - text-decoration: var(--shiki-dark-text-decoration, inherit); -} - -.codewrapper { - margin: 18px 0; -} - - .codewrapper .btn-copy, - pre .btn-copy { - color: var(--zenith-code-muted) !important; - background: var(--zenith-code-toolbar) !important; - border: 1px solid var(--zenith-code-border) !important; - border-radius: 5px !important; - } - -.hljs-keyword, -.hljs-selector-tag, -.hljs-section, -.hljs-link { - color: var(--zenith-syntax-keyword); -} - -.hljs-literal { - color: var(--zenith-syntax-literal); -} - -.hljs-string, -.hljs-symbol, -.hljs-bullet, -.hljs-addition, -.hljs-template-tag, -.hljs-template-variable { - color: var(--zenith-syntax-string); -} - -.hljs-title, -.hljs-name, -.hljs-type, -.hljs-attribute, -.hljs-built_in { - color: var(--zenith-syntax-type); -} - - .hljs-title.function_, - .hljs-function > .hljs-title, - .hljs-property, - .hljs-attr { - color: var(--zenith-syntax-function); - } - -.hljs-variable, -.hljs-params, -.hljs-subst { - color: var(--zenith-syntax-variable); -} - -.hljs-comment, -.hljs-quote, -.hljs-deletion { - color: var(--zenith-syntax-comment); -} - -.hljs-number { - color: var(--zenith-syntax-number); -} - -.hljs-meta, -.hljs-meta-keyword, -.hljs-doctag { - color: var(--zenith-syntax-meta); -} - -.hljs-symbol, -.hljs-regexp { - color: var(--zenith-syntax-symbol); -} - -.hljs-operator, -.hljs-punctuation { - color: var(--zenith-code-muted); } -/* ========================================================================== - Tables, alerts, tabs, and API surfaces - ========================================================================== */ +.contents-close { display: inline-flex; width: 40px; } +.contents-toggle:hover, .contents-close:hover { background: #344965; border-color: #8baad1; } -.doc-table-frame { - position: relative; - margin: var(--zenith-flow-space) 0; - overflow: hidden; - background: var(--zenith-table-surface); - border: 1px solid var(--zenith-table-border); - border-radius: var(--zenith-panel-radius); - transition: border-color 180ms ease, box-shadow 220ms ease; +#tocOffcanvas .offcanvas-header { + justify-content: space-between; + min-height: var(--zenith-header-height); + padding: 12px 20px; + border-bottom: 1px solid var(--zenith-border); } - .doc-table-frame:hover, - .doc-table-frame:focus-within { - border-color: color-mix(in srgb, var(--zenith-purple-700) 34%, var(--zenith-table-border)); - box-shadow: 0 10px 24px rgba(35, 30, 46, 0.06); - } - - .doc-table-frame::after { - content: ""; - position: absolute; - top: 0; - right: 0; - bottom: 0; - z-index: 2; - width: 22px; - pointer-events: none; - background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--zenith-table-surface) 94%, transparent)); - opacity: 0; - transition: opacity 180ms ease; - } - - .doc-table-frame.is-scrollable:not(.is-scroll-end)::after { - opacity: 1; - } - - .doc-table-frame > .table-responsive { - margin: 0; - overflow-x: auto; - border: 0; - border-radius: 0; - } +#tocOffcanvas .offcanvas-title { color: var(--zenith-text); font-size: 16px; font-weight: 600; } -article .doc-table-frame table, -article .doc-table-frame .table { - --bs-table-color: var(--zenith-table-text); - --bs-table-bg: var(--zenith-table-surface); - --bs-table-border-color: var(--zenith-table-border); - --bs-table-striped-bg: var(--zenith-table-stripe); - --bs-table-hover-bg: var(--zenith-table-hover); - width: 100%; - min-width: 560px; - margin: 0; - color: var(--zenith-table-text); - background: var(--zenith-table-surface); - border: 0; - border-collapse: collapse; - border-radius: 0; - font-size: 14px; - line-height: 1.5; +#affix { + font-size: 13px; + line-height: 1.55; } - article .doc-table-frame table > :not(caption) > * { - border: 0; - } - - article .doc-table-frame table > :not(caption) > * > * { - box-shadow: none; - } - -article .doc-table-frame th { - padding: var(--zenith-table-padding-block) var(--zenith-table-padding-inline); - color: var(--zenith-table-heading); - background: var(--zenith-table-header); - border: 0; - border-right: 1px solid var(--zenith-table-border); - border-bottom: 1px solid var(--zenith-table-border); +#affix h5 { + display: block; + margin: 0 0 14px; + padding: 0 0 6px; + color: var(--zenith-muted); font-size: 12px; - font-weight: 700; - text-align: left; + font-weight: 500; + letter-spacing: 0; text-transform: none; - vertical-align: bottom; } -article .doc-table-frame td { - padding: var(--zenith-table-padding-block) var(--zenith-table-padding-inline); - background: var(--zenith-table-surface); - border: 0; - border-right: 1px solid var(--zenith-table-border); - border-bottom: 1px solid var(--zenith-table-border); - vertical-align: middle; - transition: background-color 160ms ease, color 160ms ease; -} - - article .doc-table-frame th:last-child, - article .doc-table-frame td:last-child { - border-right: 0; - } - -article .doc-table-frame tbody tr:nth-child(even) td { - background: var(--zenith-table-stripe); +#affix a { + display: block; + padding-block: 3px; + text-decoration: none; } -article .doc-table-frame tbody tr:last-child td { - border-bottom: 0; +#affix a:hover { + text-decoration: underline; } -article .doc-table-frame tbody tr:hover td { - background: var(--zenith-table-hover); +body.zenith-theme > footer { + flex: 0 0 auto; + height: auto; + padding: 0; + background: var(--zenith-canvas); + font-size: 12px; } -article .doc-table-frame tbody td:first-child { - color: var(--zenith-table-heading); - font-weight: 650; +.zenith-theme > footer > div { + justify-content: space-between; + gap: 24px; + min-height: 88px; + padding-block: 24px; } -article .doc-table-frame td > code:only-child { - white-space: nowrap; +.footer-brand { + display: flex; + align-items: center; + gap: 10px; + color: var(--zenith-text); + font-weight: 500; } -.alert { - position: relative; - margin: var(--zenith-flow-space) 0; - padding: 16px 18px; - color: var(--zenith-text-soft); - background: var(--zenith-surface-soft); - border: 1px solid var(--zenith-border); - border-left-width: 4px; - border-radius: var(--zenith-panel-radius); - font-size: 14px; - transition: border-color 180ms ease, box-shadow 220ms ease, transform 220ms var(--zenith-ease); -} - - .alert:hover, - .alert:focus-within { - box-shadow: 0 8px 22px rgba(35, 30, 46, 0.07); - transform: translateY(-1px); - } - -[data-bs-theme="dark"] .alert:hover, -[data-bs-theme="dark"] .alert:focus-within { - box-shadow: 0 10px 24px rgba(0, 0, 0, 0.2); -} - -.alert > h5, -.alert > .alert-title { - margin-bottom: 5px; - color: var(--zenith-text); - font-size: 13px; - font-weight: 850; -} - -.alert-info, -.alert-note { - background: color-mix(in srgb, var(--zenith-info) 8%, transparent); - border-left-color: var(--zenith-info); -} - -.alert-tip, -.alert-success { - background: color-mix(in srgb, var(--zenith-success) 8%, transparent); - border-left-color: var(--zenith-success); -} - -.alert-warning, -.alert-important { - background: color-mix(in srgb, var(--zenith-warning) 8%, transparent); - border-left-color: var(--zenith-warning); -} - -.alert-danger, -.alert-caution { - background: color-mix(in srgb, var(--zenith-danger) 8%, transparent); - border-left-color: var(--zenith-danger); -} - -.tabGroup { - margin: var(--zenith-flow-space) 0; - border: 1px solid var(--zenith-border); - border-radius: var(--zenith-panel-radius); - overflow: hidden; -} - - .tabGroup > ul.nav-tabs { - padding: 0 10px; - background: var(--zenith-surface-soft); - border-bottom: 1px solid var(--zenith-border); - } - - .tabGroup > ul.nav-tabs > li > a { - padding: 10px 12px; - color: var(--zenith-text-soft); - border: 0; - border-bottom: 2px solid transparent; - font-size: 13px; - text-decoration: none; - } - - .tabGroup > ul.nav-tabs > li.active > a, - .tabGroup > ul.nav-tabs > li > a:hover { - color: var(--zenith-purple-700); - border-bottom-color: var(--zenith-purple-700); - } - - .tabGroup > section { - padding: 18px; - } - -article .inheritance, -article .implements, -article .inheritedMembers, -article .derivedClasses { - color: var(--zenith-text-soft); -} - -article dl.typelist, -article dl.parameters, -article dl.returns { - margin: 18px 0; -} - -article dl dt { - color: var(--zenith-text); - font-weight: 750; -} - -article .section { - scroll-margin-top: calc(var(--zenith-header-height) + 20px); -} - -article h3[id], -article a[data-uid] + h3 { - padding-top: 5px; -} - -/* ========================================================================== - Side navigation and in-page navigation - ========================================================================== */ - -#sidetoggle { - position: sticky; - top: var(--zenith-header-height); - align-self: start; - height: calc(100vh - var(--zenith-header-height)); - overflow: hidden; - border-right: 1px solid var(--zenith-border); -} - - #sidetoggle > div { - height: 100%; - } - -.sidefilter { - padding: 18px 14px 10px 0; -} - -.toc-filter { - position: relative; -} - - .toc-filter > input, - #toc_filter_input { - width: 100%; - height: 34px; - padding: 7px 12px 7px 33px; - color: var(--zenith-text); - background: var(--zenith-surface-soft); - border: 1px solid var(--zenith-border); - border-radius: 6px; - box-shadow: none; - font-size: 12px; - } - - .toc-filter .filter-icon { - position: absolute; - top: 50%; - left: 11px; - z-index: 1; - display: inline-flex; - width: 16px; - height: 16px; - align-items: center; - justify-content: center; - color: var(--zenith-text-faint); - line-height: 1; - transform: translateY(-50%); - } - -.sidetoc { - height: calc(100% - 62px); - padding: 4px 12px 30px 0; - overflow: auto; -} - -.toc { - padding: 0 16px 28px; - font-size: 13px; -} - -#toc.zenith-scroll-host > .overflow-y-auto, -main > .affix.zenith-scroll-host > #affix { - scrollbar-width: none; -} - -#toc > .overflow-y-auto { - overflow-x: hidden !important; -} - -#toc.zenith-scroll-host > .overflow-y-auto::-webkit-scrollbar, -main > .affix.zenith-scroll-host > #affix::-webkit-scrollbar { - display: none; - width: 0; - height: 0; -} - -.zenith-scroll-host { - position: relative; -} - -.zenith-overlay-scrollbar { - position: absolute; - right: var(--zenith-scrollbar-inset); - z-index: 8; - width: var(--zenith-scrollbar-size); - opacity: 0; - pointer-events: none; - touch-action: none; - transition: opacity 160ms ease; -} - -main > .affix > .zenith-overlay-scrollbar { - right: calc(-1 * (var(--zenith-scrollbar-size) + var(--zenith-scrollbar-edge-gap))); -} - -.zenith-overlay-scrollbar > span { - position: absolute; - top: 0; - right: var(--zenith-scrollbar-inset); - left: var(--zenith-scrollbar-inset); - min-height: var(--zenith-scrollbar-min-thumb); - background: var(--zenith-scrollbar-thumb); - border-radius: 999px; - cursor: grab; - transition: background-color 160ms ease; -} - -.zenith-scroll-host.has-scroll-range:hover > .zenith-overlay-scrollbar, -.zenith-scroll-host.has-scroll-range:focus-within > .zenith-overlay-scrollbar, -.zenith-scroll-host.has-scroll-range.is-scrolling > .zenith-overlay-scrollbar, -.zenith-overlay-scrollbar.is-dragging { - opacity: 1; - pointer-events: auto; -} - - .zenith-overlay-scrollbar > span:hover, - .zenith-overlay-scrollbar.is-dragging > span { - background: var(--zenith-scrollbar-thumb-hover); - } - - .zenith-overlay-scrollbar.is-dragging > span { - cursor: grabbing; - } - -.zenith-overlay-scrollbar:focus-visible { - outline: 0; -} - - .zenith-overlay-scrollbar:focus-visible > span { - background: var(--zenith-scrollbar-thumb-hover); - box-shadow: 0 0 0 1px var(--zenith-accent); - } - -#toc > form.filter { - position: relative; - margin: 16px 0 18px; -} - - #toc > form.filter input { - height: 36px; - padding-left: 36px; - color: var(--zenith-text); - background: var(--zenith-search-surface); - border-color: var(--zenith-search-border); - border-radius: 6px; - box-shadow: none; - font-size: 13px; - } - - #navbar form.search > input:focus, - #toc > form.filter input:focus, - .toc-filter > input:focus, - #toc_filter_input:focus { - outline: 0 !important; - color: var(--zenith-text); - background: var(--zenith-surface); - border-color: var(--zenith-search-focus); - box-shadow: inset 0 0 0 1px rgba(81, 43, 212, 0.22); - } - - #toc > form.filter i { - position: absolute; - top: 50%; - left: 12px; - z-index: 1; - display: inline-flex; - width: 16px; - height: 16px; - align-items: center; - justify-content: center; - color: var(--zenith-text-faint); - line-height: 1; - transform: translateY(-50%); - } - -.toc ul { - margin: 0; - padding-left: 0; - list-style: none; -} - -.toc li > a { - white-space: nowrap; -} - -#toc > .overflow-y-auto > ul > li > a wbr { - display: none; -} - -.toc ul ul { - margin: 3px 0 9px 10px; - padding-left: 11px; - border-left: 1px solid var(--zenith-border); -} - -.toc li { - position: relative; -} - - .toc li > a { - position: relative; - display: block; - margin: 1px 0; - padding: 6px 9px; - color: var(--zenith-text-soft); - border-radius: 5px; - font-weight: 550; - line-height: 1.35; - text-decoration: none !important; - transition: color 160ms ease, background-color 160ms ease, box-shadow 180ms ease, transform 180ms var(--zenith-ease); - } - - .toc li > a:hover { - color: var(--zenith-purple-700); - background: rgba(113, 56, 232, 0.06); - } - - .toc li.active:not(.expander) > a, - .toc li > a.active { - color: var(--zenith-nav-active); - background: transparent; - font-weight: 750; - box-shadow: none; - text-decoration: none !important; - } - - .toc li.active:not(.expander) > a::before, - .toc li > a.active::before { - content: ""; - position: absolute; - top: 50%; - bottom: auto; - left: 0; - width: 2px; - height: 14px; - background: var(--zenith-purple-700); - border-radius: 2px; - transform: translateY(-50%); - } - - .toc li.expander > a { - color: var(--zenith-text); - font-weight: 700; - } - -.toc > div > ul > li:first-child > a { - color: var(--zenith-purple-700); - font-size: 11px; - font-weight: 800; - text-transform: uppercase; -} - -.toc .expand-stub { - position: absolute; - top: 0; - left: 0; - z-index: 1; - display: block; - width: 14px; - height: 31px; - color: var(--zenith-text-faint); - cursor: pointer; -} - - .toc .expand-stub::before { - position: absolute; - top: 50%; - left: 50%; - display: block; - width: 14px; - height: 14px; - margin: 0; - line-height: 14px; - text-align: center; - transform: translate(-50%, -50%); - transform-origin: center; - transition: color 160ms ease, transform 220ms var(--zenith-ease); - } - -.toc li.expanded > .expand-stub::before { - transform: translate(-50%, -50%) rotate(90deg); -} - -#affix { - position: static; - top: auto; - max-height: calc(100vh - var(--zenith-header-height) - 32px); - padding-left: 0; - overflow: auto; - border-left: 0; -} - - #affix::before { - content: none; - } - - #affix > h5 { - display: block; - width: 100%; - margin: 0 0 14px; - padding: 0 0 12px; - color: var(--zenith-text-faint); - border-bottom: 1px solid var(--zenith-border) !important; - font-size: 10px; - font-weight: 850; - text-transform: uppercase; - } - - #affix ul { - margin: 0; - padding: 0; - border-left: 0; - list-style: none; - } - - #affix a { - position: relative; - display: block; - overflow: hidden; - margin: 1px 0; - padding: 6px 9px; - color: var(--zenith-text-faint); - border: 0; - border-radius: 6px; - font-size: 12px; - line-height: 1.4; - text-decoration: none !important; - text-overflow: ellipsis; - white-space: nowrap; - transition: color 160ms ease, background-color 160ms ease, box-shadow 180ms ease, transform 180ms var(--zenith-ease); - } - - #affix a.link-body-emphasis { - font-weight: 600; - } - - #affix a.link-secondary { - padding-left: 18px; - font-size: 11px; - font-weight: 400; - } - - #affix a wbr { - display: none; - } - -body[data-yaml-mime="ManagedReference"] #affix { - position: static; - overflow-x: hidden; - overflow-y: auto; -} - -#affix a:hover { - color: var(--zenith-purple-700); - background: rgba(113, 56, 232, 0.06); -} - -#affix a.active, -#affix a.is-active { - color: var(--zenith-nav-active) !important; - background: transparent; - font-weight: 700; - box-shadow: none; -} - - #affix a.active::before, - #affix a.is-active::before { - content: ""; - position: absolute; - top: 50%; - bottom: auto; - left: 0; - width: 2px; - height: 14px; - background: var(--zenith-purple-700); - border-radius: 2px; - transform: translateY(-50%); - } - -#affix a.link-secondary.active::before, -#affix a.link-secondary.is-active::before { - left: 8px; -} - -[data-bs-theme="dark"] .toc li > a:hover, -[data-bs-theme="dark"] #affix a:hover { - color: #d1c4ff !important; -} - -[data-bs-theme="dark"] .toc li.active:not(.expander) > a, -[data-bs-theme="dark"] .toc li > a.active, -[data-bs-theme="dark"] #affix a.active, -[data-bs-theme="dark"] #affix a.is-active { - color: var(--zenith-nav-active) !important; -} - -.doc-code-frame pre > .code-action { - display: none !important; -} - -@media (max-width: 575.98px) { - article .doc-code-frame > pre { - padding: 12px; - } - - .doc-code-toolbar { - padding-left: 12px; - } -} - -/* ========================================================================== - Search, footer, pagination - ========================================================================== */ - -#search-results { - width: 100%; - max-width: var(--zenith-docs-width) !important; - min-height: 65vh; - margin: 0 auto; - padding: 42px var(--zenith-page-gutter) !important; -} - -body[data-search] > main.container-xxl { - display: none !important; -} - -body[data-search] #search-results { - display: grid; - grid-template-columns: var(--zenith-sidebar-width) minmax(0, 1fr) var(--zenith-affix-width); - column-gap: var(--zenith-column-gap); -} - -body:is([data-yaml-mime="ManagedReference"], [data-zenith-api])[data-search] #search-results { - grid-template-columns: var(--zenith-api-sidebar-width) minmax(0, 1fr) var(--zenith-api-sidebar-width); -} - -body[data-search] #search-results > * { - grid-column: 2; - min-width: 0; -} - -#search-results > .sr-items { - display: grid; - grid-template-columns: minmax(0, 1fr); - gap: var(--zenith-column-gap); -} - -#search-results .sr-item { - min-width: 0; - padding: 18px 20px; - background: var(--zenith-surface); - border: 1px solid var(--zenith-border); - border-radius: var(--zenith-panel-radius); - animation: zenith-reveal-in 420ms var(--zenith-ease) backwards; - transition: border-color 160ms ease, box-shadow 200ms ease, transform 200ms var(--zenith-ease); -} - - #search-results .sr-item:nth-child(2) { - animation-delay: 35ms; - } - - #search-results .sr-item:nth-child(3) { - animation-delay: 70ms; - } - - #search-results .sr-item:nth-child(4) { - animation-delay: 105ms; - } - - #search-results .sr-item:nth-child(5) { - animation-delay: 140ms; - } - - #search-results .sr-item:nth-child(n + 6) { - animation-delay: 175ms; - } - - #search-results .sr-item:hover { - border-color: rgba(113, 56, 232, 0.36); - box-shadow: var(--zenith-shadow-small); - transform: translateY(-2px); - } - -#search-results .item-title { - overflow-wrap: anywhere; - color: var(--zenith-purple-700); - font-size: 17px; - font-weight: 750; - text-decoration: none; -} - -#search-results .item-href { - overflow-wrap: anywhere; - color: var(--zenith-text-faint); - font-size: 11px; -} - -#search-results .item-brief { - overflow-wrap: anywhere; - color: var(--zenith-text-soft); - font-size: 14px; -} - -html.zenith-motion-ready .zenith-reveal.is-visible { - animation: zenith-reveal-in 720ms var(--zenith-ease) var(--zenith-reveal-delay, 0ms) backwards; -} - -html.zenith-motion-ready .zenith-reveal[data-reveal-from="left"].is-visible { - animation-name: zenith-reveal-left; -} - -html.zenith-motion-ready .zenith-reveal[data-reveal-from="right"].is-visible { - animation-name: zenith-reveal-right; -} - -@keyframes zenith-copy-confirm { - 0% { - transform: scale(0.72); - } - - 58% { - transform: scale(1.16); - } - - 100% { - transform: scale(1); - } -} - -@keyframes zenith-reveal-in { - from { - opacity: 0; - transform: translateY(18px) scale(0.985); - } - - to { - opacity: 1; - transform: translateY(0); - } -} - -@keyframes zenith-reveal-left { - from { - opacity: 0; - transform: translateX(-24px) scale(0.985); - } - - to { - opacity: 1; - transform: translateX(0); - } -} - -@keyframes zenith-reveal-right { - from { - opacity: 0; - transform: translateX(24px) scale(0.985); - } - - to { - opacity: 1; - transform: translateX(0); - } -} - -@keyframes zenith-reading-progress { - from { - transform: scaleX(0); - } - - to { - transform: scaleX(1); - } -} - -.next-article { - width: 100%; - margin: 26px auto 0; - padding-top: 18px; - border-color: var(--zenith-border) !important; -} - - .next-article a { - text-decoration: none !important; - } - -body > footer { - position: relative; - z-index: 2; - color: var(--zenith-text-faint) !important; - background: var(--zenith-surface-soft); - border-color: var(--zenith-border) !important; - font-size: 12px; -} - - body > footer .container-xxl { - max-width: var(--zenith-content-width) !important; - padding: 0 18px !important; - } - - body > footer a { - color: var(--zenith-purple-700); - } - -/* ========================================================================== - Responsive behavior - ========================================================================== */ - -@media (max-width: 1180px) { - #navbar form.search { - width: 165px; - } - - .hero-copy h1 { - font-size: 46px; - } - - body:not([data-layout="landing"]) > main.container-xxl { - grid-template-columns: var(--zenith-sidebar-width) minmax(0, 1fr); - column-gap: 20px; - } - - body:is([data-yaml-mime="ManagedReference"], [data-zenith-api]) > main.container-xxl { - grid-template-columns: minmax(320px, 28%) minmax(0, 1fr); - } - - body[data-search] #search-results { - grid-template-columns: var(--zenith-sidebar-width) minmax(0, 1fr); - column-gap: 20px; - } - - body:is([data-yaml-mime="ManagedReference"], [data-zenith-api])[data-search] #search-results { - grid-template-columns: minmax(320px, 28%) minmax(0, 1fr); - } - - body:not([data-layout="landing"]) main > .affix { - display: none !important; - } -} - -@media (max-width: 991.98px) { - :root { - --zenith-header-height: 70px; - --zenith-header-bar-height: 54px; - --zenith-header-inset: 8px; - } - - #logo { - width: 109px; - height: 34px; - } - - .navbar-brand { - margin-right: 18px !important; - } - - #navbar .nav-link { - padding: 0 8px !important; - font-size: 13px; - } - - #navbar .nav-link::after { - right: 8px; - left: 8px; - } - - #navbar form.search { - display: none; - } - - .hero-copy { - max-width: 690px; - margin: 0 auto; - text-align: center; - } - - .hero-copy h1, - .hero-lede { - margin-right: auto; - margin-left: auto; - } - - .hero-actions, - .backend-support { - justify-content: center; - } - - body:not([data-layout="landing"]) > main.container-xxl { - grid-template-columns: var(--zenith-sidebar-width) minmax(0, 1fr); - padding-right: 14px !important; - padding-left: 14px !important; - column-gap: 18px; - } - - body:is([data-yaml-mime="ManagedReference"], [data-zenith-api]) > main.container-xxl { - grid-template-columns: minmax(320px, 34%) minmax(0, 1fr); - } - - body[data-search] #search-results { - grid-template-columns: var(--zenith-sidebar-width) minmax(0, 1fr); - column-gap: 18px; - } - - body:is([data-yaml-mime="ManagedReference"], [data-zenith-api])[data-search] #search-results { - grid-template-columns: minmax(320px, 34%) minmax(0, 1fr); - } -} - -@media (max-width: 767.98px) { - :root { - --zenith-header-height: 64px; - --zenith-header-bar-height: 64px; - --zenith-header-inset: 0px; - --zenith-header-inline-inset: 0px; - } - - body > header.bg-body, - body > header { - top: 0; - left: 0; - width: 100%; - height: auto; - min-height: var(--zenith-header-height); - border: 0 !important; - border-bottom: 1px solid var(--zenith-header-border) !important; - border-radius: 0; - box-shadow: 0 1px 6px rgba(20, 28, 58, 0.04); - transform: none; - } - - .navbar > .container-xxl { - min-height: var(--zenith-header-bar-height); - } - - .navbar .navbar-toggler, - .navbar button[data-bs-toggle="collapse"] { - color: var(--zenith-text); - border: 0 !important; - border-radius: 6px !important; - } - - .navbar-collapse { - position: absolute; - top: var(--zenith-header-bar-height); - right: 0; - left: 0; - padding: 10px 18px 16px; - background: var(--zenith-surface); - border-bottom: 1px solid var(--zenith-border); - box-shadow: var(--zenith-shadow-medium); - } - - #navbar { - display: flex; - align-items: stretch; - flex-direction: column; - gap: 8px; - } - - #navbar .navbar-nav { - order: 1; - width: 100%; - align-items: stretch; - flex-direction: column; - gap: 2px; - } - - #navbar .nav-link { - padding: 10px 12px !important; - border-radius: 5px !important; - } - - #navbar .nav-link::after { - display: none; - } - - #navbar form.search { - display: block; - order: 2 !important; - width: 100%; - } - - #navbar form.search.zenith-search { - display: flex; - width: 36px; - } - - #navbar form.search.zenith-search.is-expanded { - width: 100%; - } - - .navbar .icons { - order: 3 !important; - justify-content: flex-start; - } - - .landing-shell { - width: calc(100% - 28px); - } - - .hero-copy h1 { - font-size: 40px; - line-height: 1.08; - } - - .hero-lede { - font-size: 16px; - } - - body:not([data-layout="landing"]) > main.container-xxl { - display: block; - padding: 0 16px !important; - } - - body:not([data-layout="landing"]) main > .content { - padding-top: 18px; - } - - body[data-search] #search-results { - display: block; - } - - #sidetoggle { - position: static; - height: auto; - border-right: 0; - } - - .sidetoc { - height: auto; - } - - article h1 { - font-size: 31px; - } - - article h2 { - font-size: 23px; - } -} - -@media (max-width: 575.98px) { - #logo { - width: 102px; - height: 32px; - } - - .navbar > .container-xxl { - padding-right: 12px !important; - padding-left: 12px !important; - } - - .hero-copy h1 { - font-size: 34px; - } - - .hero-actions .landing-button { - width: 100%; - } - - .backend-label { - width: 100%; - } - - article h1 { - font-size: 28px; - } - - article h2 { - margin-top: 35px; - font-size: 21px; - } - - article pre, - .codewrapper pre { - padding: 18px; - font-size: 11px; - } -} - -@media (prefers-reduced-motion: reduce) { - *, - *::before, - *::after { - scroll-behavior: auto !important; - animation-duration: 0.01ms !important; - animation-iteration-count: 1 !important; - transition-duration: 0.01ms !important; - } - - .zenith-reading-progress > span { - animation: none !important; - transform: scaleX(0) !important; - transition: none !important; - } - - html.zenith-motion-ready .zenith-reveal { - opacity: 1 !important; - transform: none !important; - } -} - -@media print { - body { - padding-top: 0 !important; - } - - body > header, - #sidetoggle, - main > .affix, - body > footer, - .next-article { - display: none !important; - } - - body:not([data-layout="landing"]) > main.container-xxl { - display: block; - max-width: none !important; - padding: 0 !important; - } - - article { - max-width: none !important; - } -} - -/* ========================================================================== - Renderer Console V2 - ========================================================================== */ - -.render-hero { - --render-viewport-surface: #17131f; - --render-viewport-toolbar: #211b2b; - --render-viewport-border: rgba(53, 43, 66, 0.46); - --render-viewport-text: #f1edf6; - --render-viewport-muted: #aaa1b5; - --render-viewport-shadow: 0 24px 58px rgba(0, 0, 0, 0.26), 0 3px 12px rgba(0, 0, 0, 0.18); - position: relative; - min-height: calc(620px + var(--zenith-header-height)); - overflow: hidden; - color: #ffffff; - background: #100d16; -} - -.render-hero-inner { - position: relative; - z-index: 2; - display: grid; - grid-template-columns: minmax(0, 0.9fr) minmax(470px, 1.1fr); - gap: clamp(28px, 3vw, 48px); - min-height: calc(620px + var(--zenith-header-height)); - align-items: center; - padding-top: calc(48px + var(--zenith-header-height)); - padding-bottom: 48px; -} - -.render-hero .hero-copy { - width: 100%; - max-width: 650px; - margin: 0; - padding: 0; - text-align: left; - animation: none; -} - - .render-hero .hero-copy h1, - .render-hero .hero-lede, - .render-hero .hero-actions, - .render-hero .backend-support { - animation: render-hero-copy-in 720ms var(--zenith-ease) both; - } - - .render-hero .hero-copy h1 { - animation-delay: 80ms; - } - -.render-hero .hero-lede { - animation-delay: 170ms; -} - -.render-hero .hero-actions { - animation-delay: 260ms; -} - -.render-hero .backend-support { - animation-delay: 350ms; -} - -.render-viewport { - position: relative; - width: 100%; - min-width: 0; - overflow: hidden; - color: var(--render-viewport-text); - background: var(--render-viewport-surface); - border: 1px solid var(--render-viewport-border); - border-radius: 6px; - box-shadow: var(--render-viewport-shadow); - animation: render-scene-in 820ms var(--zenith-ease) 210ms both; -} - - .render-viewport::before { - content: ""; - position: absolute; - top: -1px; - right: 0; - left: 0; - z-index: 3; - height: 1px; - pointer-events: none; - background: linear-gradient(90deg, #512bd4, #7c4dff 52%, #34c9f5); - } - -.render-viewport-toolbar { - position: relative; - z-index: 2; - display: flex; - height: 38px; - align-items: center; - gap: 12px; - padding: 0 8px 0 13px; - color: var(--render-viewport-muted); - background: var(--render-viewport-toolbar); - border-bottom: 1px solid var(--render-viewport-border); - font-family: "Cascadia Code", "Cascadia Mono", Consolas, monospace; - font-size: 10px; - line-height: 1; -} - -.render-viewport-title, -.render-viewport-details { - display: inline-flex; - align-items: center; - gap: 7px; - white-space: nowrap; -} - -.render-viewport-title { - color: var(--render-viewport-text); - font-weight: 700; - text-transform: uppercase; -} - -.zenith-carousel-status { - position: absolute; - width: 1px; - height: 1px; - margin: -1px; - padding: 0; - overflow: hidden; - clip: rect(0 0 0 0); - white-space: nowrap; - border: 0; -} - -.render-viewport-title > i { - color: var(--zenith-purple-700); - font-size: 12px; -} - -.render-viewport-details { - margin-left: auto; -} - -.render-viewport-open { - display: inline-flex; - width: 28px; - height: 28px; - align-items: center; - justify-content: center; - color: var(--render-viewport-muted) !important; - border-radius: 4px; - text-decoration: none !important; - transition: color 160ms ease, background-color 160ms ease; -} - - .render-viewport-open:hover, - .render-viewport-open:focus-visible { - color: var(--render-viewport-text) !important; - background: rgba(255, 255, 255, 0.08); - } - -.render-carousel-controls { - display: inline-flex; - align-items: center; - gap: 2px; -} - -.render-viewport-canvas { - position: relative; - aspect-ratio: 16 / 9; - overflow: hidden; - background: #dce6f2; -} - - .render-viewport-canvas > a { - display: block; - width: 100%; - height: 100%; - color: transparent; - text-decoration: none; - } - -.render-carousel-slide { - position: absolute; - inset: 0; - z-index: 0; - opacity: 0; - pointer-events: none; - transition: opacity 480ms ease; -} - - .render-carousel-slide.is-active { - z-index: 1; - opacity: 1; - pointer-events: auto; - } - -.render-carousel-control { - display: none; - width: 28px; - height: 28px; - align-items: center; - justify-content: center; - padding: 0; - color: var(--render-viewport-muted); - background: transparent; - border: 1px solid transparent; - border-radius: 4px; - transition: color 160ms ease, background-color 160ms ease, border-color 160ms ease; -} - - .render-carousel-control:hover, - .render-carousel-control:focus-visible { - color: var(--render-viewport-text); - background: rgba(255, 255, 255, 0.08); - border-color: rgba(255, 255, 255, 0.12); - } - -.render-carousel-progress { - position: absolute; - right: 0; - bottom: 0; - left: 0; - z-index: 3; - display: none; - height: 3px; - overflow: hidden; - pointer-events: none; - background: rgba(16, 13, 22, 0.26); -} - - .render-carousel-progress > span { - display: block; - width: 100%; - height: 100%; - background: linear-gradient(90deg, #7847ff, #43d8ff); - box-shadow: 0 0 8px rgba(124, 77, 255, 0.42); - transform: scaleX(0); - transform-origin: left center; - } - - .render-carousel-progress > span.is-timing { - animation: render-carousel-timing 6500ms linear forwards; - animation-play-state: paused; - } - -.render-viewport.is-carousel-ready .render-carousel-control, -.render-viewport.is-carousel-ready .render-carousel-progress { - display: flex; -} - -.render-viewport.is-carousel-playing .render-carousel-progress > span.is-timing { - animation-play-state: running; -} - -.render-hero-media { - display: block; - width: 100%; - height: 100%; - max-width: none; - object-fit: cover; - object-position: center; - border: 0 !important; - border-radius: 0 !important; - outline: 0; - box-shadow: none; -} - -@media (max-width: 767.98px) { - .render-carousel-control { - width: 26px; - height: 26px; - } - - .render-carousel-control[data-carousel-toggle] { - display: none !important; - } - - .render-carousel-progress { - display: none !important; - } -} - -@media (prefers-reduced-motion: reduce) { - .render-carousel-slide, - .render-carousel-control { - transition: none !important; - } - - .render-carousel-control[data-carousel-toggle] { - display: none !important; - } - - .render-carousel-progress { - display: none !important; - } -} - -@keyframes render-carousel-timing { - from { - transform: scaleX(0); - } - - to { - transform: scaleX(1); - } -} - -.render-hero .hero-copy h1 { - max-width: 650px; - margin: 0 0 24px; - padding: 0 0 6px; - color: #f4faf8; - font-size: 62px; - font-weight: 760; - line-height: 1.08; - overflow: visible; - text-shadow: 0 2px 24px rgba(0, 0, 0, 0.28); -} - - .render-hero .hero-copy h1 span { - display: block; - width: fit-content; - margin-top: -4px; - padding: 10px 0; - color: #43d8ff; - background: none; - white-space: nowrap; - -webkit-text-fill-color: currentColor; - } - -@media (min-width: 992px) { - .render-hero .hero-copy h1 { - font-size: clamp(41px, calc(4.4643vw - 3.2857px), 62px); - } -} - -.render-hero .hero-lede { - max-width: 620px; - margin-bottom: 30px; - padding-bottom: 2px; - color: #c5bdce; - font-size: 17px; - line-height: 1.8; - overflow: visible; -} - -.render-hero .landing-button-primary { - color: #ffffff !important; - background: #512bd4; - box-shadow: none; -} - - .render-hero .landing-button-primary:hover { - color: #ffffff !important; - background: #6844df; - box-shadow: 0 12px 28px rgba(81, 43, 212, 0.3); - } - -.render-hero .landing-button-secondary { - color: #f8f5fc !important; - background: rgba(16, 13, 22, 0.5); - border-color: rgba(222, 213, 235, 0.36); - box-shadow: none; - backdrop-filter: blur(8px); -} - - .render-hero .landing-button-secondary:hover { - color: #ffffff !important; - background: rgba(43, 32, 57, 0.84); - border-color: rgba(67, 216, 255, 0.7); - } - -.render-hero .backend-support { - gap: 7px; - margin-top: 34px; -} - -.render-hero .backend-label { - color: #8b8298; - font-family: "Cascadia Code", "Cascadia Mono", Consolas, monospace; - font-size: 9px; - line-height: 1; - letter-spacing: 0; -} - -.render-hero .backend-pill { - --backend-dot: #58b947; - --backend-dot-glow: #58b947; - --backend-dot-ring: transparent; - min-height: 25px; - gap: 7px; - color: #d2cadb; - background: rgba(16, 13, 22, 0.58); - border-color: rgba(206, 194, 221, 0.24); - border-radius: 4px; - font-family: "Cascadia Code", "Cascadia Mono", Consolas, monospace; - font-size: 9px; - font-weight: 650; - backdrop-filter: blur(8px); -} - - .render-hero .backend-pill::before { - content: ""; - width: 6px; - height: 6px; - flex: 0 0 6px; - background: var(--backend-dot); - border-radius: 50%; - box-shadow: inset 0 0 0 1px var(--backend-dot-ring), 0 0 8px color-mix(in srgb, var(--backend-dot-glow) 48%, transparent); - } - -.render-hero .backend-metal { - --backend-dot: linear-gradient(135deg, #ffffff 0%, #a6afb9 48%, #e4e8ec 100%); - --backend-dot-glow: #c9d0d7; - --backend-dot-ring: rgba(74, 82, 92, 0.38); -} - -.render-hero .backend-vulkan { - --backend-dot: #b8202d; - --backend-dot-glow: #d63b45; -} - -.toc .nav > li > a:hover, -.toc .nav > li.active > a, -.toc .nav > li > a.active { - color: var(--zenith-purple-700); -} - -.toc .nav > li > a:hover { - background: rgba(81, 43, 212, 0.07); -} - -.toc .nav > li.active > a, -.toc .nav > li > a.active { - background: transparent; -} - -@keyframes render-scene-in { - from { - opacity: 0; - transform: translateX(24px) scale(0.985); - } - - to { - opacity: 1; - transform: translateX(0) scale(1); - } -} - -@keyframes render-hero-copy-in { - from { - opacity: 0; - transform: translateY(16px); - } - - to { - opacity: 1; - transform: translateY(0); - } -} - -@media (max-width: 991.98px) { - .render-hero, - .render-hero-inner { - min-height: 0; - } - - .render-hero-inner { - grid-template-columns: minmax(0, 1fr); - gap: 42px; - padding-top: calc(56px + var(--zenith-header-height)); - padding-bottom: 64px; - } - - .render-hero .hero-copy { - max-width: none; - } - - .render-viewport { - width: min(760px, 100%); - margin: 0 auto; - } - - .render-hero .hero-actions, - .render-hero .backend-support { - justify-content: flex-start; - } -} - -@media (max-width: 767.98px) { - .render-hero-inner { - gap: 34px; - padding-top: calc(48px + var(--zenith-header-height)); - padding-bottom: 54px; - } - - .render-hero .hero-copy h1 { - font-size: 43px; - } -} - -@media (max-width: 575.98px) { - .render-hero .hero-copy h1 { - font-size: 34px; - line-height: 1.04; - } - - .render-hero .hero-copy h1 span { - margin-top: 0; - padding: 6px 0 7px; - } - - .render-hero .hero-lede { - font-size: 15px; - } - - .render-hero .backend-label { - width: 100%; - } - - .render-viewport-toolbar { - gap: 8px; - padding-left: 10px; - font-size: 9px; - } -} - -@media (max-width: 374.98px) { - .render-hero .hero-copy h1 span { - font-size: 32px; - } - - .render-viewport-details > :not(.render-viewport-position) { - display: none; - } -} - -@media (max-width: 349.98px) { - .render-hero .hero-copy h1 span { - font-size: 29px; - } -} - -/* ========================================================================== - Layout and border refinement - ========================================================================== */ - -.landing-button { - gap: 9px; -} - -@media (min-width: 768px) { - .navbar > .container-xxl { - max-width: none !important; - padding-right: 18px !important; - padding-left: 18px !important; - transform: none; - } - - .navbar-brand { - margin-right: 10px !important; - } - - #navbar { - gap: 6px; - } - - #navbar .navbar-nav { - margin-right: auto !important; - } - - #navbar form.search { - margin-left: 0 !important; - } - - .navbar .icons { - margin-left: 0 !important; - margin-right: 0 !important; - } -} - -article pre code.hljs, -.codewrapper pre code.hljs { - padding: 0 !important; - overflow: visible; - color: inherit; - background: transparent !important; -} - -/* ========================================================================== - Theme-aware landing hero - ========================================================================== */ - -:root:not([data-bs-theme="dark"]) .render-hero { - --render-viewport-surface: #ffffff; - --render-viewport-toolbar: rgba(248, 247, 250, 0.96); - --render-viewport-border: rgba(52, 43, 69, 0.15); - --render-viewport-text: #342b45; - --render-viewport-muted: #746b7e; - --render-viewport-shadow: 0 18px 46px rgba(41, 27, 69, 0.1), 0 2px 8px rgba(41, 27, 69, 0.06); - color: #231e2e; - background-color: #fbfafc; - background-image: none; +.footer-caption { + color: var(--zenith-muted); + font-weight: 400; } -:root:not([data-bs-theme="dark"]) .render-viewport-open:hover, -:root:not([data-bs-theme="dark"]) .render-viewport-open:focus-visible { - background: rgba(81, 43, 212, 0.08); +.footer-links { + display: flex; + gap: 24px; } -[data-bs-theme="dark"] .render-hero { - background-color: #100d16; - background-image: linear-gradient(135deg, rgba(155, 123, 255, 0.1) 0%, rgba(155, 123, 255, 0.025) 38%, rgba(67, 216, 255, 0.06) 78%, transparent 100%); +.footer-links a { + color: var(--zenith-muted); + text-decoration: none; } -:root:not([data-bs-theme="dark"]) .render-hero .hero-copy h1 { - color: #2b2435; - text-shadow: none; +.footer-links a:hover { + color: var(--zenith-text); } - :root:not([data-bs-theme="dark"]) .render-hero .hero-copy h1 span { - color: #512bd4; - } +/* Code, tables, notices, and generated API content */ +article :not(pre) > code { + padding: 2px 5px; + border-radius: 4px; + background: var(--zenith-graphite); + color: var(--zenith-text); + font-size: .875em; +} -:root:not([data-bs-theme="dark"]) .render-hero .hero-lede { - color: #655d70; +article pre { + position: relative; + margin-block: 24px; + padding: 20px; + border: 1px solid var(--zenith-border); + border-radius: var(--zenith-radius); + background: var(--zenith-code); + color: var(--zenith-body); + font-size: 14px; + line-height: 1.65; + scrollbar-width: thin; + box-shadow: 0 8px 24px rgb(0 0 0 / 12%), inset 0 1px rgb(255 255 255 / 3%); } -:root:not([data-bs-theme="dark"]) .render-hero .landing-button-secondary { - color: #342b45 !important; - background: rgba(255, 255, 255, 0.72); - border-color: rgba(52, 43, 69, 0.22); +article pre[data-language] { + padding-top: 52px; } - :root:not([data-bs-theme="dark"]) .render-hero .landing-button-secondary:hover { - color: #512bd4 !important; - background: rgba(255, 255, 255, 0.94); - border-color: rgba(81, 43, 212, 0.46); - } +article pre[data-language]::before { + content: attr(data-language); + position: absolute; + inset: 0 0 auto; + height: 36px; + padding: 8px 14px; + border-bottom: 1px solid var(--zenith-border); + background: #22262e; + color: var(--zenith-muted); + font-family: var(--bs-body-font-family); + font-size: 11px; +} -:root:not([data-bs-theme="dark"]) .render-hero .backend-label { - color: #746b7e; +.zenith-theme article pre code.hljs { + display: block; + padding: 0; + overflow: visible; + background: transparent; + color: var(--zenith-body); } -:root:not([data-bs-theme="dark"]) .render-hero .backend-pill { - color: #40374b; - background: rgba(255, 255, 255, 0.68); - border-color: rgba(64, 52, 81, 0.2); +article pre .code-action { + display: inline-flex; + top: 0; + right: 4px; + z-index: 1; + padding: 5px 9px; + opacity: 1; + font-size: 14px; } -/* ========================================================================== - Reference-inspired landing sections - ========================================================================== */ +.zenith-theme article :is(.hljs-keyword, .hljs-selector-tag, .hljs-meta) { color: #b9b5e7; } +.zenith-theme article :is(.hljs-title, .hljs-built_in, .hljs-type) { color: #a8cce4; } +.zenith-theme article :is(.hljs-string, .hljs-regexp, .hljs-addition) { color: #b8cba6; } +.zenith-theme article :is(.hljs-number, .hljs-literal, .hljs-symbol) { color: #d7bf9a; } +.zenith-theme article :is(.hljs-attr, .hljs-attribute, .hljs-variable, .hljs-params) { color: #d0d4dc; } +.zenith-theme article :is(.hljs-comment, .hljs-quote) { color: #969fac; } +.zenith-theme article .hljs-deletion { color: #e5a4aa; } +.zenith-theme article :is(.hljs-section, .hljs-name) { color: #c6d7e9; } +.line-highlight { background: var(--zenith-graphite); } -body[data-layout="landing"] > footer { - display: none; +article .table-responsive { + margin-block: 24px; + border: 1px solid var(--zenith-border); + border-radius: var(--zenith-radius); + scrollbar-width: thin; } -.landing-page .features-section { - padding: 72px 0 104px; +article .table { + --bs-table-color: var(--zenith-body); + --bs-table-bg: var(--zenith-canvas); + --bs-table-border-color: var(--zenith-border); + --bs-table-striped-bg: var(--zenith-surface); + --bs-table-striped-color: var(--zenith-body); + --bs-table-hover-bg: var(--zenith-surface); + --bs-table-hover-color: var(--zenith-text); + margin: 0; + font-size: 14px; } -.landing-page .section-heading, -.landing-page .resources-heading { - max-width: 760px; - margin: 0 auto 56px; - text-align: center; +article .table > :not(caption) > * > * { + padding: 12px 16px; + border-width: 0 0 1px; } -.landing-page .section-kicker { - display: block; - margin-bottom: 14px; - color: var(--zenith-purple-700); - font-family: "Cascadia Code", "Cascadia Mono", Consolas, monospace; - font-size: 10px; - font-weight: 800; - line-height: 1; - letter-spacing: 0; +article .table th { + background: var(--zenith-surface); + color: var(--zenith-text); + font-weight: 600; } -.landing-page .section-heading h2, -.landing-page .architecture-copy h2, -.landing-page .resources-heading h2 { - margin: 0; - padding: 0; - color: #182746; - border: 0; - font-size: 39px; - font-weight: 800; - line-height: 1.08; - letter-spacing: 0; +article .table tbody tr:last-child > * { + border-bottom: 0; } - .landing-page .section-heading h2 span, - .landing-page .architecture-copy h2 span { - padding: 6px 5px 7px; - color: #512bd4; - background: linear-gradient(100deg, #512bd4, #c416b9); - -webkit-background-clip: text; - background-clip: text; - -webkit-text-fill-color: transparent; - } +article .alert { + --zenith-notice: #a8cce4; + margin-block: 24px; + padding: 16px 20px; + border: 1px solid var(--zenith-border); + border-left: 3px solid var(--zenith-notice); + border-radius: var(--zenith-radius); + background: var(--zenith-surface); + color: var(--zenith-body); +} - .landing-page .section-heading h2 > span { - display: block; - width: fit-content; - margin-inline: auto; - } +article .alert-warning { --zenith-notice: #d7bf9a; } +article .alert-danger { --zenith-notice: #e5a4aa; } +article .alert-success { --zenith-notice: #b8cba6; } - .landing-page .architecture-copy h2 > span { - display: inline-block; - margin-left: -5px; - } +article .alert > h5 { + margin: 0 0 8px; + color: var(--zenith-notice); + font-size: 14px; +} - .landing-page .section-heading h2 > .anchorjs-link { - display: none; - } +article .alert > :last-child { + margin-bottom: 0; +} -.landing-page h2::after { - content: none; +article .tabGroup .nav-link { + color: var(--zenith-muted); + font-size: 14px; } -.landing-page .section-heading p { - max-width: 680px; - margin: 18px auto 0; - color: #6b7180; - font-size: 15px; - line-height: 1.65; +article .tabGroup .nav-link.active, +article .tabGroup > section.card { + background: var(--zenith-surface); + border-color: var(--zenith-border); + color: var(--zenith-text); +} + +article pre.mermaid { + padding: 24px; + text-align: center; + background: var(--zenith-surface); } -[data-bs-theme="dark"] .landing-page .section-heading h2, -[data-bs-theme="dark"] .landing-page .architecture-copy h2, -[data-bs-theme="dark"] .landing-page .resources-heading h2 { - color: #f4f1fa; +article :is(.memberName, .header-action, .xref) { + overflow-wrap: anywhere; } -[data-bs-theme="dark"] .landing-page .section-heading p { - color: #aca4b7; +/* Home: typography and an interactive geometry study */ +body.zenith-theme[data-layout="landing"] > main.container-xxl { + display: block; + max-width: 1560px; } -.landing-page .feature-grid { +body.zenith-theme[data-layout="landing"] > main.container-xxl > .content { padding: 0; } +.home-page { padding-block: 12px 76px; } + +.render-hero { + position: relative; display: grid; - grid-template-columns: repeat(4, minmax(0, 1fr)); - gap: 22px; + grid-template-columns: 1fr 1fr; + gap: 28px; + align-items: start; + min-height: 540px; } -.landing-page .feature-card { - display: flex; - min-height: 214px; - flex-direction: column; - padding: 26px 24px; - justify-content: flex-start; - background: rgba(255, 255, 255, 0.84); - border: 1px solid #e4e6ee; - border-radius: var(--zenith-panel-radius); - box-shadow: 0 8px 24px rgba(31, 43, 74, 0.045); - transition: border-color 180ms ease, box-shadow 180ms ease, transform 180ms ease; +.render-copy { position: relative; z-index: 1; padding-top: 48px; } + +.render-copy h1 { + margin: 0 0 24px; + font-size: clamp(46px, 5.1vw, 80px); + font-weight: 600; + letter-spacing: -.035em; + line-height: 1.08; } - .landing-page .feature-card::before { - display: none; - } +.render-copy h1 span { color: #bdd7f7; } +.render-description { max-width: 460px; color: #c1cad7; font-size: 18px; line-height: 1.65; } - .landing-page .feature-card:hover { - background: #ffffff; - border-color: rgba(81, 43, 212, 0.24); - box-shadow: 0 12px 30px rgba(31, 43, 74, 0.08); - transform: translateY(-2px); - } +.hero-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 28px; } +.backend-note { margin: 24px 0 0; color: #98a4b4; font-size: 13px; } -.landing-page .feature-icon { +.build-button { display: inline-flex; - width: 40px; - height: 40px; align-items: center; justify-content: center; - margin-bottom: 22px; - border: 0; - border-radius: var(--zenith-panel-radius); - font-size: 18px; + min-height: 50px; + padding: 13px 24px; + background: #d7e7fb; + color: #132036; + font: 600 14px/1.5 var(--bs-body-font-family); + text-decoration: none; + border-radius: 4px; } -.landing-page .feature-icon-violet { - color: #512bd4; - background: #f1edff !important; -} +.build-button:hover { color: #101216; background: #f1f7ff; box-shadow: inset 0 0 0 1px #ffffff80; } +.build-button:focus-visible { outline-color: #101216; outline-offset: -4px; } +.build-button.secondary { background: #2a3a50; color: #eff5ff; } +.build-button.secondary:hover { background: #425e80; } +.build-button.secondary:focus-visible { outline-color: #eff5ff; } -.landing-page .feature-icon-pink { - color: #d31491; - background: #fff0f8 !important; +.geometry-stage { + position: relative; + min-width: 0; + height: 540px; + background: radial-gradient(ellipse at 55% 42%, #789ac82b 0, transparent 65%); } -.landing-page .feature-icon-blue { - color: #1671e9; - background: #edf5ff !important; +#home-geometry { + display: block; + width: 100%; + height: calc(100% - 76px); + touch-action: pan-y; + cursor: grab; } -.landing-page .feature-icon-cyan { - color: #087f9c; - background: #e9faff !important; -} +#home-geometry.is-dragging { cursor: grabbing; } -.landing-page .feature-card h3 { - margin: 0 0 8px; - padding: 0; - color: #172a4d; - font-size: 18px; - line-height: 1.3; +.scene-toolbar { + position: absolute; + bottom: 16px; + left: 50%; + transform: translateX(-50%); + white-space: nowrap; } -.landing-page .feature-card p { - margin: 0; - color: #697184; - font-size: 14px; - line-height: 1.6; +.scene-options { + display: flex; + gap: 4px; + padding: 4px; + border: 1px solid #52617a; + border-radius: 6px; + background: #1c2634; } -[data-bs-theme="dark"] .landing-page .feature-card { - background: rgba(25, 20, 34, 0.88); - border-color: #352c45; - box-shadow: none; +.scene-options button { + min-height: 36px; + padding: 8px 12px; + border: 0; + border-radius: 3px; + background: #28364a; + color: #b8c7dd; + font: 500 12px/1.5 var(--bs-body-font-family); + cursor: pointer; } - [data-bs-theme="dark"] .landing-page .feature-card:hover { - background: #20182b; - border-color: rgba(155, 123, 255, 0.38); - box-shadow: 0 12px 30px rgba(4, 3, 7, 0.28); - } - - [data-bs-theme="dark"] .landing-page .feature-card h3 { - color: #f4f1fa; - } +.scene-options button:hover { background: #415777; color: #fff; } +.scene-options button[aria-pressed="true"] { color: #162033; background: #d8e8fb; } - [data-bs-theme="dark"] .landing-page .feature-card p { - color: #aaa3b4; - } +.home-paths { + padding-top: 38px; + border-top: 1px solid #343b47; +} -.architecture-section { - padding: 96px 0; +.paths-intro { display: flex; align-items: baseline; justify-content: space-between; gap: 24px; margin-bottom: 28px; } +.paths-intro h2 { + margin: 0; + padding: 0; + border: 0; + font-size: clamp(28px, 3vw, 38px); + line-height: 1.15; + letter-spacing: -1.5px; +} + +.paths-intro p { margin: 0; color: var(--zenith-muted); font-size: 13px; line-height: 1.8; } +.path-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px; } +.path-card { position: relative; display: flex; flex-direction: column; min-width: 0; min-height: 310px; padding: 26px; border: 1px solid #3b4a60; border-radius: 7px; background: linear-gradient(130deg, #202b3b, #171e29 70%); color: #eaf2fc; text-decoration: none; } +.path-triangle { border-color: #6885aa; background: linear-gradient(130deg, #2a405e, #19283c 75%); } +.path-label { display: flex; justify-content: space-between; color: #9cb5d6; font: 11px/1.5 var(--bs-font-monospace); } +.path-label > span { color: #6f89ac; } +.path-art { position: absolute; top: 48px; right: 22px; width: 136px; height: 76px; opacity: .8; pointer-events: none; transition: opacity 240ms; } +.path-card h3 { margin: 90px 0 12px; color: #edf5ff; font-size: 24px; font-weight: 550; letter-spacing: -.65px; } +.path-card p { max-width: 310px; margin: 0 0 24px; color: #aabbd1; font-size: 13px; line-height: 1.8; } +.path-cta { align-self: flex-start; margin-top: auto; padding: 8px 12px; border: 1px solid #4e6583; border-radius: 4px; background: #263a55; color: #e4f0ff; font-size: 12px; font-weight: 600; transition: background-color 180ms, border-color 180ms; } +.path-triangle .path-cta { background: #c9def8; border-color: #c9def8; color: #17273d; } +.path-card:hover { border-color: #abc9ef; color: #fff; box-shadow: inset 0 0 32px #b3d3ff0a; } +.path-card:hover .path-art { opacity: 1; } +.path-card:hover .path-cta { border-color: #9dbce4; background: #385678; } +.path-triangle:hover .path-cta { background: #e6f2ff; color: #13233a; } + +/* Learning hub */ +.learning-entry { + position: relative; + display: block; + min-width: 0; + padding: 28px; + border: 1px solid var(--zenith-border); + border-radius: 12px; + background: linear-gradient(140deg, #22262e 0, #181b21 72%); + color: var(--zenith-text); + text-decoration: none; + box-shadow: inset 0 1px rgb(255 255 255 / 3%); } -.architecture-grid { - display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); - align-items: center; - gap: clamp(48px, 6vw, 88px); +.learning-entry:hover { border-color: #7f91aa; color: var(--zenith-text); box-shadow: inset 0 0 0 1px #c3d6f029, inset 0 0 36px #c3d6f009; } +.learning-entry h2 { margin: 0 0 10px; padding: 0; border: 0; font-size: 22px; letter-spacing: -.6px; } +.learning-entry p { margin: 0 0 24px; color: var(--zenith-muted); font-size: 14px; line-height: 1.7; } +.entry-action { display: inline-flex; align-items: center; color: var(--zenith-text); font-size: 12px; font-weight: 500; } + +body.zenith-theme[data-page-kind="hub"] > main.container-xxl { + grid-template-columns: var(--zenith-sidebar-width) minmax(0, 1fr); } -.architecture-copy .section-kicker { - margin-bottom: 14px; - text-align: left; +.learn-hub { + max-width: 1040px; } -.architecture-copy h2 { - max-width: 560px; +.learn-hub > h1 { + margin-bottom: 12px; + font-size: clamp(34px, 3.3vw, 48px); + letter-spacing: -1.5px; } -.architecture-copy > p { - max-width: 610px; - margin: 20px 0 28px; - color: #626a7a; - font-size: 15px; - line-height: 1.7; +.page-intro { + max-width: 640px; + color: var(--zenith-muted); + font-size: 16px; + line-height: 1.8; } -.architecture-points { +.learning-entries { display: grid; - gap: 12px; + grid-template-columns: 1.45fr 1fr; + gap: 18px; + margin-top: 32px; } - .architecture-points > a { - display: grid; - grid-template-columns: 26px minmax(0, 1fr); - gap: 12px; - align-items: center; - padding: 14px 16px; - color: #172a4d; - background: rgba(255, 255, 255, 0.82); - border: 1px solid rgba(81, 43, 212, 0.1); - border-radius: 8px; - text-decoration: none; - transition: border-color 160ms ease, transform 160ms ease; - } - - .architecture-points > a:hover { - border-color: rgba(81, 43, 212, 0.32); - transform: translateX(3px); - } - - .architecture-points .architecture-step { - display: inline-flex; - width: 26px; - height: 26px; - align-items: center; - justify-content: center; - color: var(--zenith-purple-700); - background: rgba(81, 43, 212, 0.08); - border: 1px solid rgba(81, 43, 212, 0.18); - border-radius: 50%; - font-family: "Cascadia Code", "Cascadia Mono", Consolas, monospace; - font-size: 9px; - font-weight: 800; - line-height: 1; - } - - .architecture-points span, - .architecture-points strong, - .architecture-points small { - display: block; - } - - .architecture-points strong { - margin-bottom: 3px; - font-size: 13px; - } - - .architecture-points small { - color: #777d8c; - font-size: 11px; - line-height: 1.45; - } - -[data-bs-theme="dark"] .architecture-copy > p { - color: #aaa3b4; +.triangle-entry { + display: grid; + grid-template-columns: 1fr 34%; + align-items: center; + gap: 8px; + background: radial-gradient(ellipse at right top, #373f4e 0, #242931 45%, #1c2027 100%); + border-color: #465060; } -[data-bs-theme="dark"] .architecture-points > a { - color: #f4f1fa; - background: rgba(31, 24, 43, 0.88); - border-color: #3b304d; +.triangle-entry .entry-action { + padding: 8px 12px; + border: 1px solid #737f924d; + border-radius: 6px; + background: #d5dfef0d; } -[data-bs-theme="dark"] .architecture-points small { - color: #9e96aa; +.triangle-diagram { + width: 100%; + overflow: visible; } -.resources-section { - padding: 90px 0 96px; +/* Shared illustration motion: a stable wireframe, moving light, then a soft highlight. */ +.card-art { --diagram-line: #adc6e7; --diagram-light: #edf6ff; --diagram-duration: 1500ms; --diagram-ease: cubic-bezier(.35, 0, .25, 1); pointer-events: none; } +.card-art .art-wire { --art-rest-opacity: .7; fill: none; stroke: var(--diagram-line); stroke-width: 1.35; opacity: var(--art-rest-opacity); } +.card-art .art-detail { --art-rest-opacity: .22; fill: none; stroke: var(--diagram-line); stroke-width: 1; opacity: var(--art-rest-opacity); } +.card-art .art-face { fill: #b8d8ff; stroke: none; opacity: .055; } +.card-art .art-node { fill: var(--diagram-light); stroke: none; transform-box: fill-box; transform-origin: center; } +.card-art .art-code-base { fill: none; stroke: var(--diagram-line); stroke-width: 3.5; opacity: .45; } +.card-art .art-flow { fill: none; stroke: var(--diagram-light); stroke-width: 1.8; stroke-linecap: round; stroke-dasharray: 20 80; stroke-dashoffset: 100; opacity: 0; } +.card-art .art-code-flow { stroke-width: 3.5; } +.card-art .art-cursor { fill: none; stroke: var(--diagram-light); stroke-width: 2; opacity: 0; } +.illustrated-link:is(:hover, :focus-visible) .art-flow { animation: diagram-flow var(--diagram-duration) var(--diagram-ease) var(--art-delay, 0ms) both; } +.illustrated-link:is(:hover, :focus-visible) .art-node { animation: diagram-node var(--diagram-duration) var(--diagram-ease) var(--art-delay, 0ms) both; } +.illustrated-link:is(:hover, :focus-visible) .art-face { animation: diagram-face var(--diagram-duration) var(--diagram-ease) 180ms both; } +.illustrated-link:is(:hover, :focus-visible) .art-mark { animation: diagram-mark var(--diagram-duration) var(--diagram-ease) 180ms both; } +.illustrated-link:is(:hover, :focus-visible) .art-cursor { animation: diagram-cursor var(--diagram-duration) var(--diagram-ease) 360ms both; } +@keyframes diagram-flow { + 0% { opacity: 0; stroke-dashoffset: 100; } + 18%, 65% { opacity: .95; } + 100% { opacity: 0; stroke-dashoffset: -100; } +} +@keyframes diagram-node { + 0%, 100% { transform: scale(1); filter: none; } + 35% { transform: scale(1.18); filter: drop-shadow(0 0 4px #c6e0ff); } +} +@keyframes diagram-face { + 0%, 100% { opacity: .055; } + 48% { opacity: .2; } +} +@keyframes diagram-mark { + 0%, 100% { opacity: var(--art-rest-opacity); } + 48% { opacity: .95; } +} +@keyframes diagram-cursor { + 0%, 35%, 100% { opacity: 0; } + 50%, 78% { opacity: .9; } +} + +.samples-entry > i { + position: absolute; + top: 24px; + right: 24px; + color: #a8b4c5; + font-size: 21px; } -.landing-page .resources-heading { - margin-bottom: 50px; +.samples-entry h2 { + padding-right: 38px; } - .landing-page .resources-heading h2 { - font-size: 36px; - } - -.resource-grid { - display: grid; - grid-template-columns: repeat(3, minmax(0, 1fr)); - gap: 22px; +.learn-hub .hub-section-title { + margin: 44px 0 6px; + padding: 0; + border: 0; + font-size: 22px; } -.resource-card { - display: flex; - min-height: 244px; - flex-direction: column; - padding: 28px; - overflow: hidden; - color: #ffffff !important; - border-radius: 8px; - box-shadow: 0 14px 30px rgba(31, 43, 91, 0.12); - text-decoration: none !important; - transition: transform 170ms ease, box-shadow 170ms ease; +.section-description { + color: var(--zenith-muted); + font-size: 14px; } - .resource-card:hover { - color: #ffffff !important; - box-shadow: 0 18px 38px rgba(31, 43, 91, 0.18); - transform: translateY(-4px); - } - -.resource-card-docs { - background: linear-gradient(135deg, #512bd4, #7542ed); +.concept-list { + border-top: 1px solid var(--zenith-border); } -.resource-card-nuget { - background: linear-gradient(135deg, #d10ba7, #ec35bd); +.concept-list > a { + display: grid; + grid-template-columns: 36px minmax(0, 1fr); + align-items: center; + gap: 16px; + padding: 19px 8px; + border-bottom: 1px solid var(--zenith-border); + text-decoration: none; } -.resource-card-community { - background: linear-gradient(135deg, #0869b8, #2689dc); +.concept-list > a:hover { + background: #ffffff04; } -.resource-icon { +.concept-list > a > i:first-child { display: inline-flex; - width: 38px; - height: 38px; align-items: center; justify-content: center; - margin-bottom: 26px; - background: rgba(255, 255, 255, 0.16); + width: 36px; + height: 36px; + border: 1px solid #343c49; border-radius: 8px; - font-size: 18px; -} - -.resource-title { - display: block; - margin: 0 0 9px; - padding: 0; - color: #ffffff; - font-size: 18px; - font-weight: 800; -} - -.resource-card p { - margin: 0 0 24px; - color: rgba(255, 255, 255, 0.82); - font-size: 13px; - line-height: 1.6; + background: #222730; + color: #bbc6d6; } -.resource-card > strong { - display: inline-flex; - align-items: center; - gap: 8px; - margin-top: auto; - color: #ffffff; - font-size: 13px; +.concept-list strong { + font-size: 14px; + font-weight: 500; } -/* Keep every landing section on one continuous theme canvas. */ -.landing-page { - --landing-canvas: #fbfafc; - --landing-atmosphere: linear-gradient(145deg, rgba(81, 43, 212, 0.055) 0%, rgba(81, 43, 212, 0.012) 46%, rgba(22, 113, 233, 0.04) 100%); - --landing-grid-row: rgba(81, 43, 212, 0.034); - --landing-grid-column: rgba(52, 201, 245, 0.03); - --landing-footer-text: #667187; - --landing-footer-heading-primary: #512bd4; - --landing-footer-heading-secondary: #d31491; - --landing-footer-link: #60708a; - --landing-footer-link-hover: #512bd4; - --landing-footer-icon: #512bd4; - --landing-footer-icon-bg: rgba(81, 43, 212, 0.08); - --landing-footer-icon-bg-hover: rgba(81, 43, 212, 0.15); - --landing-footer-rule: rgba(24, 39, 70, 0.1); - background-color: var(--landing-canvas); - background-image: var(--landing-atmosphere), linear-gradient(var(--landing-grid-row) 1px, transparent 1px), linear-gradient(90deg, var(--landing-grid-column) 1px, transparent 1px); - background-size: 100% 100%, 64px 64px, 64px 64px; -} - -:root:not([data-bs-theme="dark"]) .landing-page .render-hero { - background-color: transparent; - background-image: none; -} - -[data-bs-theme="dark"] .landing-page { - --landing-canvas: #100d16; - --landing-atmosphere: linear-gradient(145deg, rgba(155, 123, 255, 0.055) 0%, rgba(155, 123, 255, 0.012) 46%, rgba(67, 216, 255, 0.035) 100%); - --landing-grid-row: rgba(155, 123, 255, 0.038); - --landing-grid-column: rgba(67, 216, 255, 0.03); - --landing-footer-text: #9f98ab; - --landing-footer-heading-primary: #b9a5ff; - --landing-footer-heading-secondary: #ff70c0; - --landing-footer-link: #aaa3b8; - --landing-footer-link-hover: #d1c4ff; - --landing-footer-icon: #b9a5ff; - --landing-footer-icon-bg: rgba(155, 123, 255, 0.1); - --landing-footer-icon-bg-hover: rgba(155, 123, 255, 0.18); - --landing-footer-rule: rgba(222, 213, 235, 0.1); -} - - [data-bs-theme="dark"] .landing-page .render-hero { - background-color: transparent; - background-image: none; - } - -.landing-page .features-section, -.landing-page .architecture-section, -.landing-page .resources-section { - background: transparent; +.concept-list small { + display: block; + margin-top: 2px; + color: var(--zenith-muted); + font-size: 12px; } -.landing-footer { - padding: 78px 0 34px; - color: var(--landing-footer-text); - background: transparent; +/* Surface feedback: color and inset light, without moving hit targets. */ +#navbar .nav-link, +#toc li > a, +.build-button, +.path-card, +.search-launcher, +.source-link, +.contents-toggle, +.contents-close, +.menu-toggle, +.scene-options button, +#search-close, +.search-more, +.learning-entry, +.concept-list > a, +.footer-links a, +.search-shortcuts > a, +#site-search-results a { + transition-property: background-color, border-color, color, box-shadow; + transition-duration: var(--zenith-state-duration); + transition-timing-function: var(--zenith-state-ease); +} + +#navbar .nav-link:active, +#toc li > a:active, +.build-button:active, +.path-card:active, +.search-launcher:active, +.source-link:active, +.contents-toggle:active, +.contents-close:active, +.menu-toggle:active, +.scene-options button:active, +#search-close:active, +.search-more:active, +.learning-entry:active, +.concept-list > a:active, +.search-shortcuts > a:active, +#site-search-results a:active { + transition-duration: var(--zenith-press-duration); + box-shadow: inset 0 2px 5px #0005; +} + +#navbar .nav-link:active { background: #1b2839; color: #dce8f8; } +#navbar .nav-link.active:hover { background: #e8f3ff; } +#navbar .nav-link.active:active { background: #bfd3ed; color: #142033; } +.build-button:active { background: #afc6e3; color: #132036; } +.build-button.secondary:active { background: #1d2a3b; color: #eff5ff; } +.search-launcher:active, .source-link:active, .path-card:active { background: #182536; border-color: #647b99; } +.scene-options button:active { background: #192637; color: #e4edf9; } +.scene-options button[aria-pressed="true"]:active { background: #b4cae7; color: #162033; } +.learning-entry:active { border-color: #586a82; } +.concept-list > a:active, #toc li > a:active { background: #1a2432; } +.search-shortcuts > a:active, #site-search-results a:active { background: #1c2838; } +#search-close:hover, .search-more:hover { background: #34455c; color: #fff; } +#search-close:active, .search-more:active { background: #192534; } +.menu-toggle:hover { background: #ffffff0a; } +.menu-toggle:active { background: #ffffff12; } + +/* Light travels over the surface; the control itself never lifts on hover. */ +:is(.build-button, .path-card, .search-launcher, .source-link, .contents-toggle, .learning-entry), +#navbar .nav-link { + position: relative; + overflow: hidden; + isolation: isolate; } -.landing-footer-grid { - display: grid; - grid-template-columns: minmax(0, 1.45fr) minmax(180px, 0.7fr) minmax(180px, 0.7fr); - gap: 72px; - padding-bottom: 58px; +:is(.build-button, .path-card, .search-launcher, .source-link, .contents-toggle, .learning-entry)::before, +#navbar .nav-link::before { + content: ""; + position: absolute; + inset: 0; + z-index: -1; + background: linear-gradient(110deg, transparent 20%, #e2edff26 48%, transparent 76%); + transform: translateX(-120%); + pointer-events: none; } -.landing-footer-logo { - display: block; - width: auto; - height: 48px; -} +@media (hover: hover) { + :is(.build-button, .path-card, .search-launcher, .source-link, .contents-toggle, .learning-entry):hover::before, + #navbar .nav-link:hover::before { + animation: zenith-sweep 620ms cubic-bezier(.2, .65, .3, 1); + } -.landing-footer-brand p { - max-width: 480px; - margin: 24px 0 28px; - color: var(--landing-footer-text); - font-size: 15px; - line-height: 1.7; } -.landing-footer-github { - display: inline-flex; - width: 42px; - height: 42px; - align-items: center; - justify-content: center; - color: var(--landing-footer-icon) !important; - background: var(--landing-footer-icon-bg); - border-radius: 8px; - font-size: 20px; -} +.concept-list > a > i:first-child { transition: background-color 240ms, border-color 240ms, color 240ms; } +.concept-list > a:is(:hover, :focus-visible) > i:first-child { background: #324761; border-color: #738eaf; color: #eef6ff; } - .landing-footer-github:hover { - color: var(--landing-footer-link-hover) !important; - background: var(--landing-footer-icon-bg-hover); - } +.motion-enter { animation: zenith-reveal 480ms cubic-bezier(.16, 1, .3, 1) var(--entrance-delay, 0ms) backwards; } -.landing-footer-column { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 14px; +@keyframes zenith-sweep { + to { transform: translateX(120%); } } -.landing-footer-heading { - display: block; - margin: 0 0 10px; - padding: 0; - color: var(--landing-footer-heading-primary); - font-size: 14px; - font-weight: 800; +@keyframes zenith-reveal { + from { opacity: 0; transform: translateY(12px); } + to { opacity: 1; transform: none; } } -.landing-footer-column:last-child .landing-footer-heading { - color: var(--landing-footer-heading-secondary); +@keyframes zenith-panel-in { + from { opacity: 0; transform: translateY(-10px) scale(.98); } + to { opacity: 1; transform: none; } } -.landing-footer-column a { - color: var(--landing-footer-link); - font-size: 14px; - text-decoration: none; +@keyframes zenith-panel-out { + to { opacity: 0; transform: translateY(-6px) scale(.99); } } - .landing-footer-column a:hover { - color: var(--landing-footer-link-hover); - } - -.landing-footer-bottom { - display: flex; - align-items: center; - justify-content: space-between; - padding-top: 30px; - border-top: 1px solid var(--landing-footer-rule); - font-family: "Cascadia Code", "Cascadia Mono", Consolas, monospace; - font-size: 12px; +@keyframes zenith-backdrop-in { + from { opacity: 0; } + to { opacity: 1; } } - .landing-footer-bottom > span:last-child { - display: flex; - gap: 28px; +/* Responsive layout */ +@media (max-width: 1199.98px) { + :root { + --zenith-sidebar-width: 220px; + --zenith-gap: 28px; + --zenith-gutter: 24px; } - .landing-footer-bottom a { - color: var(--landing-footer-link); - text-decoration: none; + body.zenith-theme > main.container-xxl { + grid-template-columns: var(--zenith-sidebar-width) minmax(0, 1fr); } - .landing-footer-bottom a:hover { - color: var(--landing-footer-link-hover); - } - -@media (max-width: 991.98px) { - .landing-page .features-section, - .architecture-section, - .resources-section { - padding-top: 78px; - padding-bottom: 82px; + body.zenith-theme > main.container-xxl > .affix { + display: none; } - .landing-page .feature-grid, - .resource-grid { - grid-template-columns: repeat(2, minmax(0, 1fr)); - } +} - .architecture-grid { +@media (min-width: 768px) and (max-width: 899.98px) { + .learning-entries { grid-template-columns: 1fr; - gap: 46px; - } - - .architecture-copy { - max-width: 760px; - width: 100%; - margin: 0 auto; - } - - .landing-footer-grid { - grid-template-columns: minmax(0, 1fr) 180px 180px; - gap: 36px; } } @media (max-width: 767.98px) { - .landing-page .section-heading, - .landing-page .resources-heading { - margin-bottom: 38px; + :root { + --zenith-header-height: 64px; + --zenith-gutter: 20px; + } + + .site-nav { grid-template-columns: 1fr auto; gap: 12px; } + .site-header.menu-open { height: auto; } + .site-nav .navbar-brand { padding-block: 14px; } + .site-nav #logo { height: 36px; } + .site-actions { gap: 8px; } + .search-launcher { justify-content: center; width: 40px; padding: 0; } + .search-launcher > span, .search-launcher kbd, .source-link { display: none; } + .menu-toggle { display: block; } + .site-menu { + position: absolute; + inset: var(--zenith-header-height) 0 auto; + padding: 16px var(--zenith-gutter) 20px; + border-bottom: 1px solid #3b4655; + background: #131820; + opacity: 0; + visibility: hidden; + clip-path: inset(0 0 100%); + transition: clip-path var(--zenith-panel-duration) cubic-bezier(.16, 1, .3, 1), opacity 180ms, visibility var(--zenith-panel-duration); + } + .menu-open .site-menu { opacity: 1; visibility: visible; clip-path: inset(0); } + #navbar .navbar-nav { gap: 8px; } + #navbar .nav-link { padding: 11px 23px; } + .site-search { width: calc(100% - 24px); margin-top: 16px; max-height: calc(100dvh - 32px); } + .search-input-row { gap: 12px; min-height: 76px; padding: 16px; } + #site-search-input { font-size: 16px; } + .search-scroll { max-height: calc(100dvh - 172px); } + .search-footer { padding: 12px 16px; } + + .form-control { + font-size: 16px; } - .landing-page .section-heading h2, - .landing-page .architecture-copy h2, - .landing-page .resources-heading h2 { - font-size: 31px; - } - - .landing-page .feature-grid, - .resource-grid { - grid-template-columns: 1fr; + body.zenith-theme > main.container-xxl { + grid-template-columns: minmax(0, 1fr); + padding-top: 20px; } - .landing-page .feature-card { - min-height: 0; + body.zenith-theme[data-page-kind="hub"] > main.container-xxl { + grid-template-columns: minmax(0, 1fr); } - .landing-footer-grid { - grid-template-columns: 1fr 1fr; + body.zenith-theme > main.container-xxl > .content { + grid-column: 1; + grid-row: 1; + padding-top: 0; } - .landing-footer-brand { - grid-column: 1 / -1; + body.zenith-theme > main.container-xxl > .toc-offcanvas { + grid-column: 1; + grid-row: 1; + position: static; + width: 0; + height: 0; + overflow: visible; + padding: 0; + border: 0; } -} -@media (max-width: 575.98px) { - .landing-page .features-section, - .architecture-section, - .resources-section { - padding-top: 64px; - padding-bottom: 68px; + #tocOffcanvas .offcanvas-body { + padding: 20px; } - .landing-page .feature-card, - .resource-card { - padding: 24px; - } + body.zenith-theme > main > .content > .contents-toggle { display: inline-flex; margin-bottom: 24px; } - .architecture-points > a { - padding: 13px 14px; + article h2 { + font-size: 23px; } - .landing-footer { - padding-top: 62px; + article pre { + padding-inline: 14px; + font-size: 13px; } - .landing-footer-grid { - grid-template-columns: 1fr; - gap: 42px; - padding-bottom: 44px; + .home-page { padding-block: 8px 44px; } + .render-hero { grid-template-columns: 1fr; min-height: 0; gap: 8px; } + .render-copy { padding-top: 24px; } + .render-copy h1 { font-size: clamp(38px, 8.8vw, 56px); letter-spacing: -.03em; } + .render-description { max-width: 460px; font-size: 16px; } + .hero-actions { margin-top: 24px; } + .build-button { min-height: 48px; padding-inline: 18px; } + .geometry-stage { height: 360px; } + .scene-toolbar { bottom: 12px; } + .scene-options button { padding-inline: 10px; } + .home-paths { padding-top: 30px; } + .paths-intro { display: block; margin-bottom: 22px; } + .paths-intro h2 { margin-bottom: 12px; font-size: 32px; } + .path-grid { grid-template-columns: 1fr; gap: 14px; } + .path-card { min-height: 240px; padding: 24px; } + .path-card h3 { margin-top: 48px; font-size: 23px; } + .path-art { top: 48px; width: 96px; height: 54px; opacity: .6; } + .path-card p { max-width: 420px; } + .learning-entries { grid-template-columns: 1fr; } + .learning-entry { padding: 24px; } + .triangle-diagram { max-width: 128px; justify-self: end; } + .zenith-theme > footer > div { flex-wrap: wrap; gap: 20px; } + .footer-links { gap: 20px; } + .concept-list > a { gap: 12px; } +} + +@view-transition { navigation: none; } + +@media (prefers-reduced-motion: reduce) { + html { scroll-behavior: auto; } + *, *::before, *::after, *::backdrop { + animation: none !important; + transition: none !important; } +} - .landing-footer-brand, - .landing-footer-column { - grid-column: auto; +@media print { + body.zenith-theme { padding-top: 0; } + body.zenith-theme > main.container-xxl { + display: block; + padding: 0; } - .landing-footer-bottom { - align-items: flex-start; - flex-direction: column; - gap: 16px; + .zenith-theme > main > :is(.toc-offcanvas, .affix), + article .code-action { + display: none !important; } } diff --git a/documents/templates/public/main.js b/documents/templates/public/main.js index 7ddb5fa4..4ee8a43a 100644 --- a/documents/templates/public/main.js +++ b/documents/templates/public/main.js @@ -1,1107 +1,122 @@ -const shikiModuleUrl = 'https://esm.sh/shiki@4.3.1'; -const slangGrammarUrl = 'https://raw.githubusercontent.com/shader-slang/slang-vscode-extension/v2.0.10/syntaxes/slang.tmLanguage.json'; -const shikiLanguageAliases = { - bash: 'bash', - console: 'shellsession', - cs: 'csharp', - csharp: 'csharp', - json: 'json', - powershell: 'powershell', - shell: 'bash', - slang: 'slang', - text: 'text', - txt: 'text', - xml: 'xml', - yaml: 'yaml', - yml: 'yaml' -}; - -let fallbackHighlighter; -let shikiHighlighter; - -const loadShiki = () => { - shikiHighlighter ??= Promise.all([ - import(shikiModuleUrl), - fetch(slangGrammarUrl, { cache: 'force-cache' }).then(response => { - if (!response.ok) throw new Error(`Unable to load Slang grammar: HTTP ${response.status}`); - return response.json(); - }) - ]).then(([{ createHighlighter }, slangGrammar]) => { - slangGrammar.name = 'slang'; - - return createHighlighter({ - themes: ['light-plus', 'dark-plus'], - langs: ['bash', 'csharp', 'json', 'powershell', 'shellsession', 'xml', 'yaml', slangGrammar] - }); - }); - - return shikiHighlighter; -}; - -const highlightCode = async (code, language) => { - const source = code.textContent; - const pre = code.closest('pre'); - - try { - const highlighter = await loadShiki(); - const highlighted = highlighter.codeToHtml(source, { - lang: shikiLanguageAliases[language] || 'text', - themes: { light: 'light-plus', dark: 'dark-plus' }, - defaultColor: false - }); - const template = document.createElement('template'); - template.innerHTML = highlighted; - const shikiPre = template.content.querySelector('pre'); - const shikiCode = shikiPre?.querySelector('code'); - if (!pre || !shikiPre || !shikiCode) throw new Error('Shiki returned invalid markup.'); - - code.innerHTML = shikiCode.innerHTML; - code.classList.remove('hljs'); - code.dataset.highlighted = 'yes'; - code.dataset.shiki = 'true'; - pre.classList.add('shiki', 'shiki-themes', 'light-plus', 'dark-plus'); - - for (const property of shikiPre.style) { - if (property.startsWith('--shiki-')) { - pre.style.setProperty(property, shikiPre.style.getPropertyValue(property)); - } - } - } catch (error) { - console.warn('Shiki highlighting failed; using the DocFX highlighter.', error); - code.textContent = source; - code.classList.remove('hljs'); - code.removeAttribute('data-highlighted'); - - try { - fallbackHighlighter?.highlightElement(code); - } catch { - code.dataset.highlighted = 'yes'; - } - } -}; - +import { initializeSearch } from './search.js'; +import { initializeHomeScene } from './home.js'; +import { initializeMotion } from './motion.js'; +import { initializeApi } from './api.js'; +import { initializeMemberFinder } from './member-finder.js'; + +// Retain DocFX's generated navigation, reference pages, and code tools. +// The master template sets the fixed dark appearance before the first paint. export default { + defaultTheme: 'dark', configureHljs: hljs => { - fallbackHighlighter = hljs; hljs.registerAliases(['slang'], { languageName: 'cpp' }); + hljs.registerAliases(['console'], { languageName: 'shell' }); }, - iconLinks: [ - { - icon: 'github', - href: 'https://github.com/qian-o/Zenith.NET', - title: 'GitHub' + mermaid: { + theme: 'base', + themeVariables: { + darkMode: true, + background: '#181b21', + primaryColor: '#262a32', + primaryTextColor: '#f2f3f5', + primaryBorderColor: '#626a78', + secondaryColor: '#181b21', + secondaryTextColor: '#f2f3f5', + secondaryBorderColor: '#626a78', + tertiaryColor: '#343943', + tertiaryTextColor: '#f2f3f5', + tertiaryBorderColor: '#626a78', + lineColor: '#a4abb7', + textColor: '#f2f3f5', + edgeLabelBackground: '#181b21', + fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif' } - ], + }, start: () => { - const rootPath = document.querySelector('meta[name="docfx:rel"]')?.content || ''; - const reducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)'); - const observeUntil = (target, options, initialize, timeout = 5000) => { - if (initialize() || !target) return; - - let timeoutId; - const observer = new MutationObserver(() => { - if (!initialize()) return; - observer.disconnect(); - window.clearTimeout(timeoutId); - }); - observer.observe(target, options); - timeoutId = window.setTimeout(() => observer.disconnect(), timeout); - }; - document.body.toggleAttribute('data-zenith-api', /\/api(?:\/|$)/i.test(window.location.pathname)); - - const initializeThemeCycle = () => { - const themes = [ - { value: 'light', label: 'Light', icon: 'bi-sun' }, - { value: 'dark', label: 'Dark', icon: 'bi-moon' }, - { value: 'auto', label: 'Auto', icon: 'bi-circle-half' } - ]; - const systemTheme = window.matchMedia('(prefers-color-scheme: dark)'); - const navbar = document.getElementById('navbar'); - if (!navbar) return; - - const enhanceThemeToggle = () => { - const dropdown = navbar.querySelector('.icons .dropdown'); - const currentToggle = dropdown?.querySelector('.dropdown-toggle'); - if (!dropdown || !currentToggle) return false; - - const themeToggle = document.createElement('button'); - const icon = document.createElement('i'); - let animationTimer; - - themeToggle.type = 'button'; - themeToggle.className = 'btn border-0 zenith-theme-toggle'; - icon.setAttribute('aria-hidden', 'true'); - themeToggle.append(icon); - dropdown.replaceWith(themeToggle); - - const getTheme = () => { - const storedTheme = window.localStorage.getItem('theme'); - return themes.find(theme => theme.value === storedTheme) || themes[2]; - }; - - const getNextTheme = theme => themes[(themes.indexOf(theme) + 1) % themes.length]; - - const renderTheme = theme => { - const nextTheme = getNextTheme(theme); - icon.className = `bi ${theme.icon}`; - themeToggle.dataset.theme = theme.value; - themeToggle.title = `${theme.label} theme; switch to ${nextTheme.label}`; - themeToggle.setAttribute( - 'aria-label', - `${theme.label} theme. Switch to ${nextTheme.label}.` - ); - }; - - const applyTheme = theme => { - const resolvedTheme = theme.value === 'auto' - ? (systemTheme.matches ? 'dark' : 'light') - : theme.value; - window.localStorage.setItem('theme', theme.value); - document.documentElement.dataset.bsTheme = resolvedTheme; - renderTheme(theme); - }; - - const switchTheme = () => { - const nextTheme = getNextTheme(getTheme()); - window.clearTimeout(animationTimer); - - if (reducedMotion.matches) { - applyTheme(nextTheme); - return; - } - - themeToggle.disabled = true; - themeToggle.classList.remove('is-theme-entering'); - themeToggle.classList.add('is-theme-leaving'); - animationTimer = window.setTimeout(() => { - applyTheme(nextTheme); - themeToggle.classList.remove('is-theme-leaving'); - themeToggle.classList.add('is-theme-entering'); - animationTimer = window.setTimeout(() => { - themeToggle.classList.remove('is-theme-entering'); - themeToggle.disabled = false; - }, 260); - }, 120); - }; - - themeToggle.addEventListener('click', switchTheme); - systemTheme.addEventListener('change', () => { - const theme = getTheme(); - if (theme.value === 'auto') applyTheme(theme); - }); - applyTheme(getTheme()); - return true; - }; - - observeUntil(navbar, { childList: true, subtree: true }, enhanceThemeToggle); - }; - - const initializeExpandableSearch = () => { - const form = document.querySelector('#navbar form.search'); - const input = form?.querySelector('#search-query'); - const nativeIcon = form?.querySelector(':scope > i'); - if (!form || !input || form.classList.contains('zenith-search')) return; - - const toggle = document.createElement('button'); - const icon = document.createElement('i'); - toggle.type = 'button'; - toggle.className = 'zenith-search-toggle'; - toggle.setAttribute('aria-controls', input.id); - toggle.setAttribute('aria-expanded', 'false'); - toggle.setAttribute('aria-label', 'Open search'); - toggle.title = 'Search'; - icon.className = 'bi bi-search'; - icon.setAttribute('aria-hidden', 'true'); - toggle.append(icon); - nativeIcon?.setAttribute('aria-hidden', 'true'); - form.prepend(toggle); - form.classList.add('zenith-search'); - const searchPlaceholder = input.placeholder || 'Search'; - - const updateAvailability = () => { - const ready = !input.disabled; - const expanded = form.classList.contains('is-expanded'); - form.classList.toggle('is-loading', !ready); - form.setAttribute('aria-busy', String(!ready)); - toggle.setAttribute('aria-label', expanded ? 'Close search' : 'Open search'); - toggle.title = ready ? (expanded ? 'Close search' : 'Search') : 'Search is loading'; - icon.className = 'bi bi-search'; - input.placeholder = ready ? searchPlaceholder : 'Search is loading...'; - }; - const availabilityObserver = new MutationObserver(updateAvailability); - availabilityObserver.observe(input, { attributes: true, attributeFilter: ['disabled'] }); - updateAvailability(); - let pendingFocusObserver; - - const setExpanded = (expanded, focusInput = false) => { - if (!expanded) { - pendingFocusObserver?.disconnect(); - pendingFocusObserver = undefined; - } - form.classList.toggle('is-expanded', expanded); - toggle.setAttribute('aria-expanded', String(expanded)); - toggle.setAttribute('aria-label', expanded ? 'Close search' : 'Open search'); - toggle.title = input.disabled ? 'Search is loading' : (expanded ? 'Close search' : 'Search'); - - if (!focusInput) return; - const focusWhenReady = () => { - if (input.disabled) return false; - input.focus({ preventScroll: true }); - return true; - }; - if (focusWhenReady()) return; - - pendingFocusObserver?.disconnect(); - pendingFocusObserver = new MutationObserver(() => { - if (!form.classList.contains('is-expanded')) { - pendingFocusObserver?.disconnect(); - pendingFocusObserver = undefined; - return; + // Keep heading IDs for deep links and the outline, without AnchorJS controls. + for (const heading of document.querySelectorAll('article h2, article h3, article h4')) { + heading.classList.add('no-anchor'); + } + // Learn has one small, always-visible group. Keep API trees interactive. + const toc = document.getElementById('toc'); + if (toc && document.body.dataset.section === 'learn') { + const flattenGroups = () => { + if (!toc.querySelector(':scope > .overflow-y-auto')) return false; + for (const group of toc.querySelectorAll('li.expander')) { + group.classList.add('expanded'); + group.querySelector(':scope > .expand-stub')?.remove(); + const link = group.querySelector(':scope > a[href="#"]'); + if (link) { + const heading = document.createElement('span'); + heading.className = 'toc-group-title'; + heading.textContent = link.textContent; + group.replaceChild(heading, link); } - if (!focusWhenReady()) return; - pendingFocusObserver?.disconnect(); - pendingFocusObserver = undefined; - }); - pendingFocusObserver.observe(input, { attributes: true, attributeFilter: ['disabled'] }); - }; - - const clearSearch = () => { - if (!input.value) return; - input.value = ''; - input.dispatchEvent(new Event('input', { bubbles: true })); - }; - - toggle.addEventListener('click', () => { - const expanded = form.classList.contains('is-expanded'); - if (expanded) { - clearSearch(); - setExpanded(false); - toggle.focus({ preventScroll: true }); - } else { - setExpanded(true, true); } - }); - - input.addEventListener('focus', () => setExpanded(true)); - input.addEventListener('keydown', event => { - if (event.key !== 'Escape') return; - event.preventDefault(); - clearSearch(); - setExpanded(false); - toggle.focus({ preventScroll: true }); - }); - document.addEventListener('pointerdown', event => { - if (!form.classList.contains('is-expanded') || form.contains(event.target)) return; - if (!input.value && !document.body.hasAttribute('data-search')) setExpanded(false); - }); - - if (input.value || document.body.hasAttribute('data-search')) setExpanded(true); - }; - - const initializeReadingMotion = () => { - const header = document.querySelector('body > header'); - if (!header) return; - - const progress = document.createElement('div'); - const progressValue = document.createElement('span'); - progress.className = 'zenith-reading-progress'; - progress.setAttribute('aria-hidden', 'true'); - progress.append(progressValue); - header.append(progress); - - const hasScrollTimeline = window.CSS?.supports?.('animation-timeline: scroll()') === true; - - const updateScrollState = () => { - const scrollRange = Math.max(1, document.documentElement.scrollHeight - window.innerHeight); - const value = Math.min(1, Math.max(0, window.scrollY / scrollRange)); - if (!hasScrollTimeline) progressValue.style.transform = `scaleX(${value.toFixed(4)})`; - header.classList.toggle('is-scrolled', window.scrollY > 8); + return true; }; - - window.addEventListener('scroll', updateScrollState, { passive: true }); - window.addEventListener('resize', updateScrollState, { passive: true }); - updateScrollState(); - }; - - const initializeOverlayScrollbars = () => { - const initialized = new WeakSet(); - const hideTimers = new WeakMap(); - const updates = new WeakMap(); - - const attach = (scroller, host) => { - if (!scroller || !host) return; - if (initialized.has(scroller)) { - updates.get(scroller)?.(); - return; - } - initialized.add(scroller); - host.classList.add('zenith-scroll-host'); - - const track = document.createElement('span'); - const thumb = document.createElement('span'); - track.className = 'zenith-overlay-scrollbar'; - track.setAttribute('role', 'scrollbar'); - track.setAttribute('aria-label', host.id === 'toc' - ? 'Table of contents scrollbar' - : 'In this article scrollbar'); - track.setAttribute('aria-orientation', 'vertical'); - track.setAttribute('aria-valuemin', '0'); - if (!scroller.id) scroller.id = `${host.id || 'zenith'}-scroll-region`; - track.setAttribute('aria-controls', scroller.id); - track.append(thumb); - host.append(track); - - const update = () => { - const hostRect = host.getBoundingClientRect(); - const scrollerRect = scroller.getBoundingClientRect(); - const trackStyle = window.getComputedStyle(track); - const scrollbarSize = Number.parseFloat( - trackStyle.getPropertyValue('--zenith-scrollbar-size') - ) || track.offsetWidth; - const edgeGap = Number.parseFloat( - trackStyle.getPropertyValue('--zenith-scrollbar-edge-gap') - ) || (scrollbarSize / 2); - const minThumbHeight = Number.parseFloat( - trackStyle.getPropertyValue('--zenith-scrollbar-min-thumb') - ) || (scrollbarSize * 4.5); - const trackHeight = Math.max(0, scroller.clientHeight - (edgeGap * 2)); - const scrollRange = Math.max(0, scroller.scrollHeight - scroller.clientHeight); - const thumbHeight = scrollRange - ? Math.max(minThumbHeight, trackHeight * (scroller.clientHeight / scroller.scrollHeight)) - : trackHeight; - const thumbRange = Math.max(0, trackHeight - thumbHeight); - const thumbOffset = scrollRange ? (scroller.scrollTop / scrollRange) * thumbRange : 0; - - track.style.top = `${scrollerRect.top - hostRect.top + edgeGap}px`; - track.style.height = `${trackHeight}px`; - track.tabIndex = scrollRange > 1 ? 0 : -1; - track.setAttribute('aria-valuemax', `${Math.round(scrollRange)}`); - track.setAttribute('aria-valuenow', `${Math.round(scroller.scrollTop)}`); - thumb.style.height = `${thumbHeight}px`; - thumb.style.transform = `translateY(${thumbOffset}px)`; - host.classList.toggle('has-scroll-range', scrollRange > 1); - }; - updates.set(scroller, update); - - const showWhileScrolling = () => { - host.classList.add('is-scrolling'); - window.clearTimeout(hideTimers.get(host)); - hideTimers.set(host, window.setTimeout(() => { - host.classList.remove('is-scrolling'); - }, 700)); - update(); - }; - - scroller.addEventListener('scroll', showWhileScrolling, { passive: true }); - window.addEventListener('resize', update, { passive: true }); - const resizeObserver = typeof ResizeObserver === 'undefined' - ? null - : new ResizeObserver(update); - resizeObserver?.observe(scroller); - resizeObserver?.observe(host); - new MutationObserver(update).observe(scroller, { childList: true, subtree: true }); - - track.addEventListener('keydown', event => { - const lineStep = scroller.clientHeight / 10; - const pageStep = scroller.clientHeight; - const scrollRange = Math.max(0, scroller.scrollHeight - scroller.clientHeight); - const target = { - ArrowUp: scroller.scrollTop - lineStep, - ArrowDown: scroller.scrollTop + lineStep, - PageUp: scroller.scrollTop - pageStep, - PageDown: scroller.scrollTop + pageStep, - Home: 0, - End: scrollRange - }[event.key]; - if (target === undefined) return; - - event.preventDefault(); - scroller.scrollTop = Math.min(scrollRange, Math.max(0, target)); + if (!flattenGroups()) { + const observer = new MutationObserver(() => { + if (flattenGroups()) observer.disconnect(); }); - - track.addEventListener('pointerdown', event => { - if (!host.classList.contains('has-scroll-range')) return; - event.preventDefault(); - - const trackRect = track.getBoundingClientRect(); - const thumbRect = thumb.getBoundingClientRect(); - const startY = event.clientY; - let startScrollTop = scroller.scrollTop; - const thumbRange = Math.max(1, trackRect.height - thumbRect.height); - const scrollRange = Math.max(0, scroller.scrollHeight - scroller.clientHeight); - - if (event.target !== thumb) { - const targetOffset = Math.min( - thumbRange, - Math.max(0, event.clientY - trackRect.top - (thumbRect.height / 2)) - ); - scroller.scrollTop = (targetOffset / thumbRange) * scrollRange; - startScrollTop = scroller.scrollTop; - } - - track.classList.add('is-dragging'); - track.setPointerCapture(event.pointerId); - const move = moveEvent => { - scroller.scrollTop = startScrollTop - + ((moveEvent.clientY - startY) / thumbRange) * scrollRange; - }; - const stop = () => { - track.classList.remove('is-dragging'); - track.removeEventListener('pointermove', move); - track.removeEventListener('pointerup', stop); - track.removeEventListener('pointercancel', stop); - }; - track.addEventListener('pointermove', move); - track.addEventListener('pointerup', stop); - track.addEventListener('pointercancel', stop); - }); - update(); - }; - - const initialize = () => { - const tocScroller = document.querySelector('#toc > .overflow-y-auto'); - attach(tocScroller, document.querySelector('#toc')); - - const affix = document.querySelector('#affix'); - attach(affix, affix?.parentElement); - }; - - const observer = new MutationObserver(initialize); - for (const host of document.querySelectorAll('#toc, main > .affix')) { - observer.observe(host, { childList: true, subtree: true }); - } - initialize(); - }; - - const copyText = async (text) => { - try { - await navigator.clipboard.writeText(text); - return; - } catch { - const textarea = document.createElement('textarea'); - textarea.value = text; - textarea.setAttribute('readonly', ''); - textarea.style.position = 'fixed'; - textarea.style.opacity = '0'; - document.body.append(textarea); - textarea.select(); - - const copied = document.execCommand('copy'); - textarea.remove(); - if (!copied) throw new Error('Copy failed'); - } - }; - - const copyResetTimers = new WeakMap(); - const setCopyButtonState = (button, state) => { - const defaultLabel = button.dataset.copyLabel || button.getAttribute('aria-label') || 'Copy'; - const icon = button.querySelector('i'); - const feedback = { - idle: { icon: 'bi bi-copy', label: defaultLabel }, - copied: { icon: 'bi bi-check2', label: 'Copied' }, - failed: { icon: 'bi bi-x-lg', label: 'Copy failed' } - }[state]; - - button.dataset.copyLabel = defaultLabel; - button.classList.toggle('is-copied', state === 'copied'); - button.classList.toggle('is-failed', state === 'failed'); - button.setAttribute('aria-label', feedback.label); - button.title = feedback.label; - if (icon) icon.className = feedback.icon; - - const activeTimer = copyResetTimers.get(button); - if (activeTimer) window.clearTimeout(activeTimer); - - if (state === 'idle') { - copyResetTimers.delete(button); - } else { - copyResetTimers.set(button, window.setTimeout(() => { - copyResetTimers.delete(button); - setCopyButtonState(button, 'idle'); - }, 2000)); + observer.observe(toc, { childList: true, subtree: true }); } - }; + } - const copyWithFeedback = async (button, text) => { - try { - await copyText(text); - setCopyButtonState(button, 'copied'); - } catch { - setCopyButtonState(button, 'failed'); + initializeSearch(); + initializeHomeScene(); + initializeApi(); + initializeMemberFinder(); + initializeMotion(); + + const menu = document.getElementById('menu-toggle'); + const header = document.querySelector('.site-header'); + const closeMenu = () => { + menu.setAttribute('aria-expanded', 'false'); + header.classList.remove('menu-open'); + }; + menu?.addEventListener('click', () => { + const open = menu.getAttribute('aria-expanded') !== 'true'; + menu.setAttribute('aria-expanded', String(open)); + header.classList.toggle('menu-open', open); + }); + document.addEventListener('click', event => { + if (header?.classList.contains('menu-open') && !header.contains(event.target)) closeMenu(); + }); + document.addEventListener('keydown', event => { + if (event.key === 'Escape' && header?.classList.contains('menu-open')) { + closeMenu(); + menu.focus(); } - }; - - const brand = document.querySelector('.navbar-brand'); - if (brand && !brand.hasAttribute('aria-label')) { - brand.setAttribute('aria-label', 'Zenith.NET home'); - } - initializeThemeCycle(); - initializeExpandableSearch(); + }); + window.matchMedia('(min-width: 768px)').addEventListener('change', event => { + if (event.matches && menu) closeMenu(); + }); + if (menu) window.addEventListener('pagehide', closeMenu); - const languageNames = { + const languages = { bash: 'Shell', - csharp: 'C#', - cs: 'C#', console: 'Console', + cs: 'C#', + csharp: 'C#', json: 'JSON', powershell: 'PowerShell', shell: 'Shell', slang: 'Slang', + text: 'Text', xml: 'XML', yaml: 'YAML', yml: 'YAML' }; - const createCodeFrame = pre => { - const code = pre.querySelector('code'); - if (!code) return null; - - const languageClass = [...code.classList].find(name => name.startsWith('language-') || name.startsWith('lang-')); - const language = languageClass?.replace(/^language-|^lang-/, '').toLowerCase() || 'text'; - const existingFrame = pre.closest('.doc-code-frame'); - if (existingFrame) return { code, language }; - const frame = document.createElement('div'); - const toolbar = document.createElement('div'); - const languageLabel = document.createElement('span'); - const copy = document.createElement('button'); - - frame.className = 'doc-code-frame'; - toolbar.className = 'doc-code-toolbar'; - languageLabel.className = 'doc-code-language'; - languageLabel.textContent = languageNames[language] || language.toUpperCase(); - copy.type = 'button'; - copy.className = 'doc-code-copy'; - copy.setAttribute('aria-label', 'Copy code block'); - copy.innerHTML = ''; - setCopyButtonState(copy, 'idle'); - - pre.parentNode.insertBefore(frame, pre); - frame.append(toolbar, pre); - toolbar.append(languageLabel); - toolbar.append(copy); - pre.querySelector(':scope > .code-action')?.remove(); - - copy.addEventListener('click', async () => { - await copyWithFeedback(copy, code.textContent); - }); - - return { code, language }; - }; - - for (const pre of document.querySelectorAll('body:not([data-layout="landing"]) article pre')) { - const controls = createCodeFrame(pre); - if (controls) void highlightCode(controls.code, controls.language); - } - - for (const table of document.querySelectorAll('body:not([data-layout="landing"]) article table')) { - if (table.closest('.doc-table-frame')) continue; - - const frame = document.createElement('div'); - frame.className = 'doc-table-frame'; - const responsive = table.closest('.table-responsive'); - const target = responsive || table; - target.parentNode.insertBefore(frame, target); - frame.append(target); - } - - const initializeTableScrollCues = () => { - const frames = [...document.querySelectorAll('.doc-table-frame')]; - if (!frames.length) return; - - const observedScrollers = new WeakSet(); - const updates = new WeakMap(); - const resizeObserver = typeof ResizeObserver === 'undefined' - ? null - : new ResizeObserver(entries => { - for (const entry of entries) updates.get(entry.target)?.(); - }); - - const initializeFrame = frame => { - const scroller = frame.querySelector('.table-responsive'); - if (!scroller || observedScrollers.has(scroller)) return false; - observedScrollers.add(scroller); + for (const code of document.querySelectorAll('article pre > code')) { + const language = [...code.classList] + .find(name => /^(?:lang|language)-/.test(name)) + ?.replace(/^(?:lang|language)-/, '') || 'text'; - const update = () => { - const maxScroll = Math.max(0, scroller.scrollWidth - scroller.clientWidth); - frame.classList.toggle('is-scrollable', maxScroll > 1); - frame.classList.toggle('is-scroll-end', scroller.scrollLeft >= maxScroll - 1); - }; - - scroller.addEventListener('scroll', update, { passive: true }); - if (!resizeObserver) window.addEventListener('resize', update, { passive: true }); - updates.set(scroller, update); - resizeObserver?.observe(scroller); - - const table = scroller.querySelector('table'); - if (table) { - updates.set(table, update); - resizeObserver?.observe(table); - } - update(); - return true; - }; - - const pendingFrames = new Set(frames); - const initializePendingFrames = () => { - for (const frame of pendingFrames) { - if (initializeFrame(frame)) pendingFrames.delete(frame); - } - if (!pendingFrames.size) mutationObserver.disconnect(); - }; - const mutationObserver = new MutationObserver(initializePendingFrames); - - for (const frame of pendingFrames) { - mutationObserver.observe(frame, { childList: true, subtree: true }); - } - initializePendingFrames(); - }; - - const initializeTutorialCarousel = () => { - const carousel = document.querySelector('[data-tutorial-carousel]'); - if (!carousel) return; - - const slides = [...carousel.querySelectorAll('.render-carousel-slide')]; - const title = carousel.querySelector('[data-carousel-title]'); - const position = carousel.querySelector('[data-carousel-position]'); - const status = carousel.querySelector('[data-carousel-status]'); - const progress = carousel.querySelector('[data-carousel-progress]'); - const openLink = carousel.querySelector('[data-carousel-open]'); - const toggleButton = carousel.querySelector('[data-carousel-toggle]'); - const previousButton = carousel.querySelector('[data-carousel-prev]'); - const nextButton = carousel.querySelector('[data-carousel-next]'); - const mobileViewport = window.matchMedia('(max-width: 767.98px)'); - const autoPlayDuration = 6500; - let activeIndex = Math.max(0, slides.findIndex(slide => slide.classList.contains('is-active'))); - let autoPlayTimer = 0; - let autoPlayRemaining = autoPlayDuration; - let autoPlayStartedAt = 0; - let isAutoPlayPaused = false; - let isVisible = true; - let touchStartX = 0; - let touchStartY = 0; - - if (slides.length < 2 || !title || !position || !progress || !openLink || !toggleButton || !previousButton || !nextButton) return; - - const prepareSlide = index => { - const image = slides[index]?.querySelector('img[data-src]'); - if (!image?.dataset.src) return; - - image.src = image.dataset.src; - image.removeAttribute('data-src'); - }; - - const stopAutoPlay = () => { - window.clearTimeout(autoPlayTimer); - autoPlayTimer = 0; - if (autoPlayStartedAt) { - autoPlayRemaining = Math.max(0, autoPlayRemaining - (performance.now() - autoPlayStartedAt)); - autoPlayStartedAt = 0; - } - carousel.classList.remove('is-carousel-playing'); - }; - - const canAutoPlay = () => !isAutoPlayPaused && - !reducedMotion.matches && - !mobileViewport.matches && - !document.hidden && - isVisible && - !carousel.matches(':hover') && - !carousel.matches(':focus-within'); - - const scheduleAutoPlay = () => { - if (!canAutoPlay()) { - stopAutoPlay(); - return; - } - if (autoPlayTimer) return; - - autoPlayStartedAt = performance.now(); - carousel.classList.add('is-carousel-playing'); - autoPlayTimer = window.setTimeout(() => { - autoPlayTimer = 0; - autoPlayStartedAt = 0; - autoPlayRemaining = autoPlayDuration; - showSlide(activeIndex + 1); - }, Math.max(16, autoPlayRemaining)); - }; - - const showSlide = (index, announce = false) => { - stopAutoPlay(); - activeIndex = (index + slides.length) % slides.length; - prepareSlide(activeIndex); - prepareSlide((activeIndex + 1) % slides.length); - - for (const [slideIndex, slide] of slides.entries()) { - const isActive = slideIndex === activeIndex; - slide.classList.toggle('is-active', isActive); - slide.setAttribute('aria-hidden', String(!isActive)); - if (isActive) { - slide.setAttribute('aria-current', 'true'); - } else { - slide.removeAttribute('aria-current'); - } - slide.tabIndex = isActive ? 0 : -1; - } - - const activeSlide = slides[activeIndex]; - const activeTitle = activeSlide.dataset.carouselTitle || `Tutorial ${activeIndex + 1}`; - title.textContent = activeTitle; - position.textContent = `${activeIndex + 1} / ${slides.length}`; - openLink.href = activeSlide.href; - openLink.setAttribute('aria-label', `Open ${activeTitle} tutorial`); - if (announce && status) { - status.textContent = `${activeTitle}, slide ${activeIndex + 1} of ${slides.length}`; - } - - autoPlayRemaining = autoPlayDuration; - progress.classList.remove('is-timing'); - void progress.offsetWidth; - progress.classList.add('is-timing'); - scheduleAutoPlay(); - }; - - const updateToggleButton = () => { - const label = isAutoPlayPaused ? 'Start automatic slide rotation' : 'Pause automatic slide rotation'; - toggleButton.setAttribute('aria-label', label); - toggleButton.title = label; - toggleButton.innerHTML = ``; - }; - - toggleButton.addEventListener('click', () => { - isAutoPlayPaused = !isAutoPlayPaused; - updateToggleButton(); - if (isAutoPlayPaused) { - stopAutoPlay(); - } else { - autoPlayRemaining = autoPlayDuration; - scheduleAutoPlay(); - } - }); - previousButton.addEventListener('click', () => showSlide(activeIndex - 1, true)); - nextButton.addEventListener('click', () => showSlide(activeIndex + 1, true)); - - carousel.addEventListener('keydown', event => { - if (event.key !== 'ArrowLeft' && event.key !== 'ArrowRight') return; - - event.preventDefault(); - showSlide(activeIndex + (event.key === 'ArrowRight' ? 1 : -1), true); - }); - carousel.addEventListener('mouseenter', stopAutoPlay); - carousel.addEventListener('mouseleave', scheduleAutoPlay); - carousel.addEventListener('focusin', stopAutoPlay); - carousel.addEventListener('focusout', () => window.requestAnimationFrame(scheduleAutoPlay)); - carousel.addEventListener('touchstart', event => { - const touch = event.changedTouches[0]; - touchStartX = touch.clientX; - touchStartY = touch.clientY; - stopAutoPlay(); - }, { passive: true }); - carousel.addEventListener('touchend', event => { - const touch = event.changedTouches[0]; - const deltaX = touch.clientX - touchStartX; - const deltaY = touch.clientY - touchStartY; - if (Math.abs(deltaX) >= 44 && Math.abs(deltaX) > Math.abs(deltaY)) { - showSlide(activeIndex + (deltaX < 0 ? 1 : -1), true); - } else { - scheduleAutoPlay(); - } - }, { passive: true }); - - document.addEventListener('visibilitychange', scheduleAutoPlay); - reducedMotion.addEventListener('change', scheduleAutoPlay); - mobileViewport.addEventListener('change', scheduleAutoPlay); - - if ('IntersectionObserver' in window) { - const observer = new IntersectionObserver(entries => { - isVisible = entries[0]?.isIntersecting ?? true; - scheduleAutoPlay(); - }, { threshold: 0.2 }); - observer.observe(carousel); - } - - carousel.classList.add('is-carousel-ready'); - showSlide(activeIndex); - }; - - const initializeRevealMotion = () => { - const selectors = document.body.matches('[data-layout="landing"]') - ? [ - '.section-heading', - '.feature-card', - '.architecture-copy', - '.resources-heading', - '.resource-card', - '.landing-footer-grid > *' - ] - : [ - 'article h1:first-of-type', - 'article h2', - 'article .alert', - 'article .doc-code-frame', - 'article .doc-table-frame', - 'article .tabGroup' - ]; - const targets = [...document.querySelectorAll(selectors.join(','))] - .filter(element => element.getClientRects().length); - if (!targets.length || reducedMotion.matches) { - targets.forEach(element => element.classList.add('is-visible')); - return; - } - - for (const [index, target] of targets.entries()) { - target.classList.add('zenith-reveal'); - target.style.setProperty('--zenith-reveal-delay', `${Math.min(index % 4, 3) * 45}ms`); - if (document.body.matches('[data-layout="landing"]')) { - const direction = target.matches('.architecture-grid > .architecture-copy:first-child') - ? 'left' - : target.matches('.architecture-grid > .architecture-copy:last-child') - ? 'right' - : 'up'; - target.dataset.revealFrom = direction; - } - } - document.documentElement.classList.add('zenith-motion-ready'); - - const pending = new Set(targets); - const revealVisibleTargets = () => { - const revealBoundary = window.innerHeight * 0.92; - for (const target of pending) { - const rect = target.getBoundingClientRect(); - if (rect.top >= revealBoundary || rect.bottom <= 0) continue; - - target.classList.add('is-visible'); - pending.delete(target); - } - - if (!pending.size) { - window.removeEventListener('scroll', revealVisibleTargets); - window.removeEventListener('resize', revealVisibleTargets); - } - }; - - window.addEventListener('scroll', revealVisibleTargets, { passive: true }); - window.addEventListener('resize', revealVisibleTargets, { passive: true }); - revealVisibleTargets(); - }; - - initializeReadingMotion(); - initializeOverlayScrollbars(); - initializeTableScrollCues(); - initializeTutorialCarousel(); - - const initializeAffix = () => { - const links = [...document.querySelectorAll('#affix a[href^="#"]')]; - const targetGroups = new Map(); - const targetIndexes = new Map(); - - for (const link of links) { - const targetId = decodeURIComponent(link.hash.slice(1)); - if (!targetGroups.has(targetId)) { - targetGroups.set(targetId, [...document.querySelectorAll(`[id="${CSS.escape(targetId)}"]`)]); - } + if (language !== 'mermaid') { + code.parentElement.dataset.language = languages[language] || language; } - - const affixLinks = links - .map(link => { - const targetId = decodeURIComponent(link.hash.slice(1)); - const targetIndex = targetIndexes.get(targetId) || 0; - const targets = targetGroups.get(targetId) || []; - const target = targets[targetIndex] || targets[0]; - targetIndexes.set(targetId, targetIndex + 1); - - if (target && targetIndex > 0) { - const uniqueId = `${targetId}--${targetIndex + 1}`; - target.id = uniqueId; - link.setAttribute('href', `#${uniqueId}`); - } - - return { link, target }; - }) - .filter(item => { - const isVisible = item.target?.getClientRects().length; - if (!isVisible) item.link.closest('li')?.style.setProperty('display', 'none'); - return isVisible; - }); - if (!affixLinks.length) return false; - - const updateAffix = () => { - const scrollPaddingTop = Number.parseFloat( - window.getComputedStyle(document.documentElement).scrollPaddingTop - ) || 0; - let current = affixLinks[0]; - let start = 0; - let end = affixLinks.length - 1; - - while (start <= end) { - const middle = Math.floor((start + end) / 2); - const item = affixLinks[middle]; - const scrollMarginTop = Number.parseFloat( - window.getComputedStyle(item.target).scrollMarginTop - ) || 0; - const targetOffset = scrollPaddingTop + scrollMarginTop + 1; - - if (item.target.getBoundingClientRect().top <= targetOffset) { - current = item; - start = middle + 1; - } else { - end = middle - 1; - } - } - - for (const item of affixLinks) { - item.link.classList.toggle('is-active', item === current); - } - }; - - window.addEventListener('scroll', updateAffix, { passive: true }); - updateAffix(); - return true; - }; - - const normalizePath = path => path.replace(/\/index\.html$/, '/'); - const siteRootPath = normalizePath(new URL(rootPath || './', window.location.href).pathname); - const currentPath = normalizePath(window.location.pathname); - for (const link of document.querySelectorAll('#navbar .nav-link')) { - const linkPath = normalizePath(new URL(link.href, window.location.href).pathname); - const isHome = linkPath === siteRootPath && currentPath === siteRootPath; - const isSection = linkPath !== siteRootPath && currentPath.startsWith(linkPath); - const isActive = isHome || isSection; - link.classList.toggle('active', isActive); - if (isActive) { - link.setAttribute('aria-current', 'page'); - } else { - link.removeAttribute('aria-current'); - } - } - - // Hide inherited type info sections (inheritance, implements, inheritedMembers, derivedClasses) - for (const dl of document.querySelectorAll('dl.typelist.inheritance, dl.typelist.implements, dl.typelist.inheritedMembers, dl.typelist.derivedClasses')) { - dl.style.display = 'none'; } - - // Hide protected members from API pages - for (const code of document.querySelectorAll('.codewrapper pre code')) { - const text = code.textContent.trim(); - if (!/^(?:private\s+)?protected\b/.test(text)) continue; - - const wrapper = code.closest('.codewrapper'); - if (!wrapper) continue; - - const toHide = []; - - // Walk backward from codewrapper to collect h3 header and anchor - let el = wrapper; - while (el) { - toHide.push(el); - if (el.tagName === 'H3') { - const prev = el.previousElementSibling; - if (prev && prev.tagName === 'A' && prev.dataset.uid) { - toHide.push(prev); - } - break; - } - el = el.previousElementSibling; - } - - // Walk forward from codewrapper to collect parameters, returns, etc. - let next = wrapper.nextElementSibling; - while (next && next.tagName !== 'H3' && next.tagName !== 'H2' && - !(next.tagName === 'A' && next.dataset.uid)) { - toHide.push(next); - next = next.nextElementSibling; - } - - toHide.forEach(e => e.style.display = 'none'); - } - - // Hide empty section headers (e.g. "Constructors" when all constructors are hidden) - for (const h2 of document.querySelectorAll('article h2.section')) { - let next = h2.nextElementSibling; - let hasVisibleMember = false; - while (next && next.tagName !== 'H2') { - if (next.tagName === 'H3' && next.style.display !== 'none') { - hasVisibleMember = true; - break; - } - next = next.nextElementSibling; - } - if (!hasVisibleMember) { - h2.style.display = 'none'; - } - } - - observeUntil( - document.querySelector('main > .affix'), - { childList: true, subtree: true }, - initializeAffix - ); - - initializeRevealMotion(); - - // Search results: navigate in same tab with back button support - document.addEventListener('click', event => { - const link = event.target instanceof Element - ? event.target.closest('#search-results .sr-item a') - : null; - if (!link) return; - if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || - event.shiftKey || event.altKey || link.hasAttribute('download') || - (link.target && link.target !== '_self')) return; - - event.preventDefault(); - const query = document.getElementById('search-query')?.value || ''; - history.replaceState({ search: true, query, scrollY: window.scrollY }, ''); - window.location.href = link.href; - }); - - const restoreSearchState = (state) => { - if (!state?.search) return; - - const input = document.getElementById('search-query'); - if (!input) return; - - input.value = state.query || ''; - input.dispatchEvent(new Event('input', { bubbles: true })); - - if (!Number.isFinite(state.scrollY)) return; - - const restoreScroll = () => { - if (!document.body.hasAttribute('data-search')) return false; - - const maxScroll = Math.max(0, document.documentElement.scrollHeight - window.innerHeight); - if (maxScroll < state.scrollY) return false; - - window.scrollTo(0, state.scrollY); - return true; - }; - - if (restoreScroll()) return; - - const observer = new MutationObserver(() => { - if (restoreScroll()) observer.disconnect(); - }); - observer.observe(document.body, { attributes: true, childList: true, subtree: true }); - window.setTimeout(() => { - restoreScroll(); - observer.disconnect(); - }, 2000); - }; - - window.addEventListener('popstate', (e) => restoreSearchState(e.state)); - - const restoreInitialSearchState = () => { - if (!history.state?.search) return; - - const input = document.getElementById('search-query'); - if (!input) return; - - observeUntil(input, { attributes: true, attributeFilter: ['disabled'] }, () => { - if (input.disabled) return; - restoreSearchState(history.state); - return true; - }); - }; - - restoreInitialSearchState(); } -} +}; diff --git a/documents/templates/public/member-finder.js b/documents/templates/public/member-finder.js new file mode 100644 index 00000000..b7c1c330 --- /dev/null +++ b/documents/templates/public/member-finder.js @@ -0,0 +1,156 @@ +// A page-local symbol finder. Every result points to an existing DocFX member ID. +export function initializeMemberFinder() { + const dialog = document.getElementById('api-member-dialog'); + if (!dialog) return; + + const input = document.getElementById('api-member-query'); + const results = document.getElementById('api-member-results'); + const empty = document.getElementById('api-member-empty'); + const clear = document.getElementById('api-member-clear'); + const launchers = [...document.querySelectorAll('[data-member-find]')]; + const groups = [...document.querySelectorAll('.api-reference > .api-group')].map(section => ({ + name: section.querySelector('.api-group-heading h2')?.textContent.trim(), + members: [...section.querySelectorAll('.api-member-heading h3[id], .api-enum-value h3[id]')].map(heading => ({ + heading, + name: heading.textContent.trim(), + signature: heading.closest('.api-member')?.querySelector(':scope > pre > code')?.textContent || heading.textContent + })) + })).filter(group => group.members.length); + if (!groups.length) empty.textContent = 'This type has no declared members.'; + + let opener; + let restoreFocus = true; + const shortcut = /Mac|iPhone|iPad/.test(navigator.platform) ? '⌥ M' : 'Alt M'; + for (const launcher of launchers) { + launcher.hidden = false; + launcher.title = `Find a member (${shortcut})`; + const key = launcher.querySelector('[data-member-shortcut]'); + if (key) key.textContent = shortcut; + launcher.addEventListener('click', () => open(launcher)); + } + + function render() { + const terms = input.value.toLowerCase().trim().split(/\s+/).filter(Boolean); + const fragment = document.createDocumentFragment(); + for (const group of groups) { + const matches = group.members.filter(member => { + const text = `${group.name} ${member.name} ${member.signature}`.toLowerCase(); + return terms.every(term => text.includes(term)); + }); + if (!matches.length) continue; + const section = document.createElement('section'); + const label = document.createElement('h3'); + const list = document.createElement('ul'); + label.textContent = group.name; + for (const member of matches) { + const item = document.createElement('li'); + const link = document.createElement('a'); + link.href = '#' + encodeURIComponent(member.heading.id); + link.dataset.memberTarget = member.heading.id; + link.textContent = member.name; + item.append(link); + list.append(item); + } + section.append(label, list); + fragment.append(section); + } + results.replaceChildren(fragment); + empty.hidden = results.childElementCount > 0; + clear.hidden = !input.value; + dialog.querySelector('.search-scroll').scrollTop = 0; + } + + function isVisible(button) { + if (!button || !button.getClientRects().length || getComputedStyle(button).visibility !== 'visible') return false; + const drawer = button.closest('#tocOffcanvas'); + if (drawer && window.matchMedia('(max-width: 767.98px)').matches && (!drawer.classList.contains('show') || drawer.classList.contains('hiding'))) return false; + const bounds = button.getBoundingClientRect(); + return bounds.right > 0 && bounds.left < innerWidth && bounds.bottom > 0 && bounds.top < innerHeight; + } + + function visibleLauncher() { + return launchers.find(isVisible); + } + + function open(button) { + if (document.querySelector('dialog[open]')) return; + opener = button || visibleLauncher(); + restoreFocus = true; + document.querySelector('#tocOffcanvas.show .contents-close')?.click(); + document.getElementById('menu-toggle').setAttribute('aria-expanded', 'false'); + document.querySelector('.site-header').classList.remove('menu-open'); + render(); + dialog.showModal(); + input.focus(); + input.select(); + } + + document.getElementById('api-member-close').addEventListener('click', () => dialog.close()); + dialog.addEventListener('cancel', event => { + event.preventDefault(); + dialog.close(); + }); + dialog.addEventListener('close', () => { + if (restoreFocus && !document.querySelector('dialog[open]')) { + const menu = document.getElementById('menu-toggle'); + const target = isVisible(opener) ? opener : visibleLauncher() || (isVisible(menu) ? menu : null); + target?.focus({ preventScroll: true }); + } + }); + dialog.addEventListener('click', event => { + if (event.target === dialog) { + const bounds = dialog.getBoundingClientRect(); + if (event.clientX < bounds.left || event.clientX > bounds.right || event.clientY < bounds.top || event.clientY > bounds.bottom) dialog.close(); + return; + } + const link = event.target.closest('[data-member-target]'); + if (!link || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; + const target = document.getElementById(link.dataset.memberTarget); + restoreFocus = false; + dialog.close(); + target.tabIndex = -1; + // Keep native anchor navigation/history; move keyboard focus after scrolling. + requestAnimationFrame(() => { + target.focus({ preventScroll: true }); + target.scrollIntoView({ block: 'start', behavior: 'auto' }); + }); + }); + input.addEventListener('input', render); + clear.addEventListener('click', () => { + input.value = ''; + render(); + input.focus(); + }); + document.getElementById('api-member-form').addEventListener('submit', event => { + event.preventDefault(); + results.querySelector('a')?.click(); + }); + dialog.addEventListener('keydown', event => { + if (event.key === 'Escape') { + event.preventDefault(); + event.stopPropagation(); + dialog.close(); + return; + } + if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') return; + const links = [...results.querySelectorAll('a')]; + if (!links.length) return; + event.preventDefault(); + const current = links.indexOf(document.activeElement); + const next = event.key === 'ArrowDown' ? (current + 1) % links.length : (current <= 0 ? links.length - 1 : current - 1); + links[next].focus(); + }, { capture: true }); + document.addEventListener('keydown', event => { + if (!event.altKey || event.ctrlKey || event.metaKey || event.shiftKey || event.repeat || event.code !== 'KeyM' && event.key.toLowerCase() !== 'm') return; + if (event.target.closest('input, textarea, select, [contenteditable]')) return; + event.preventDefault(); + if (dialog.open) dialog.close(); + else open(); + }); + const dismissForNavigation = () => { + restoreFocus = false; + dialog.close(); + }; + window.addEventListener('pagehide', dismissForNavigation); + window.addEventListener('popstate', dismissForNavigation); +} diff --git a/documents/templates/public/motion.js b/documents/templates/public/motion.js new file mode 100644 index 00000000..d193135f --- /dev/null +++ b/documents/templates/public/motion.js @@ -0,0 +1,42 @@ +// Reveal content once as it enters the viewport; navigation itself stays immediate. +export function initializeMotion() { + const preference = window.matchMedia('(prefers-reduced-motion: reduce)'); + if (preference.matches) return; + + const selector = document.querySelector('.home-page') + ? '.render-copy > *, .geometry-stage, .paths-intro, .path-card' + : document.querySelector('.learn-hub') + ? '.learn-hub > h1, .page-intro, .learning-entry, .hub-section-title, .section-description, .concept-list > a' + : document.querySelector('.api-reference') + ? '.api-heading, .api-declaration, .api-start-grid, .api-group-heading' + : 'article > h1, article > p, article > section'; + const observer = new IntersectionObserver(entries => { + let order = 0; + for (const { target, isIntersecting } of entries) { + if (!isIntersecting) continue; + observer.unobserve(target); + target.style.setProperty('--entrance-delay', `${Math.min(order++, 3) * 55}ms`); + target.classList.add('motion-enter'); + target.addEventListener('animationend', event => { + if (event.target === target && event.animationName === 'zenith-reveal') { + target.classList.remove('motion-enter'); + target.style.removeProperty('--entrance-delay'); + } + }); + } + }, { threshold: 0 }); + document.querySelectorAll(selector).forEach(element => observer.observe(element)); + + const finish = () => { + observer.disconnect(); + for (const element of document.querySelectorAll('.motion-enter')) { + element.classList.remove('motion-enter'); + element.style.removeProperty('--entrance-delay'); + } + }; + // Cached pages return in their completed state, without replaying an entrance. + window.addEventListener('pagehide', finish); + preference.addEventListener('change', event => { + if (event.matches) finish(); + }); +} diff --git a/documents/templates/public/search.js b/documents/templates/public/search.js new file mode 100644 index 00000000..62b69f0b --- /dev/null +++ b/documents/templates/public/search.js @@ -0,0 +1,201 @@ +// Custom search presentation using DocFX's generated index and search worker. +export function initializeSearch() { + const dialog = document.getElementById('search-dialog'); + if (!dialog) return; + + const trigger = document.getElementById('search-open'); + if (!trigger) return; + const input = document.getElementById('site-search-input'); + const status = document.getElementById('search-status'); + const shortcuts = document.getElementById('search-shortcuts'); + const results = document.getElementById('site-search-results'); + const more = document.getElementById('search-more'); + const root = new URL(document.querySelector('meta[name="docfx:rel"]').content || './', location.href); + const pendingQueries = []; + let worker; + let ready = false; + let hits = []; + let shown = 0; + let closeTimer; + + function rememberSearch(open = dialog.open) { + history.replaceState({ + ...history.state, + zenithSearch: { open, query: input.value } + }, ''); + } + + if (!/Mac|iPhone|iPad/.test(navigator.platform)) { + document.querySelector('[data-search-shortcut]').textContent = 'Ctrl K'; + } + + function runQuery() { + const query = input.value.trim(); + results.replaceChildren(); + more.hidden = true; + shortcuts.hidden = query !== ''; + if (!query) { + status.textContent = 'Search the docs, concepts, and API.'; + return; + } + status.textContent = ready ? 'Searching…' : 'Loading search…'; + if (!ready) return; + const terms = query.split(/\s+/).map(term => '+' + term.replace(/[+\-:^~*\\]/g, '\\$&')).join(' '); + pendingQueries.push(query); + worker.postMessage({ q: terms }); + } + + function appendResults() { + const fragment = document.createDocumentFragment(); + for (const hit of hits.slice(shown, shown + 30)) { + const item = document.createElement('li'); + const link = document.createElement('a'); + const heading = document.createElement('span'); + const title = document.createElement('strong'); + const category = document.createElement('small'); + const apiResult = hit.href.startsWith('api/'); + link.href = new URL(hit.href, root).href; + link.setAttribute('data-search-item', ''); + heading.className = 'search-result-heading'; + title.textContent = hit.title.replace(/\s*\|\s*Zenith\.NET\s*$/, ''); + category.textContent = apiResult ? 'API' : hit.href === 'index.html' ? 'Home' : 'Learn'; + heading.append(title, category); + link.append(heading); + if (apiResult || hit.summary) { + const excerpt = document.createElement('p'); + // API results identify the fully qualified type, without indexing UI labels into the preview. + let text = apiResult + ? hit.href === 'api/index.html' ? 'Browse namespaces and types.' : decodeURIComponent(new URL(hit.href, root).pathname.split('/').pop()).replace(/\.html$/, '') + : hit.summary.replace(/\s+/g, ' ').trim(); + if (text.startsWith(title.textContent)) text = text.slice(title.textContent.length).trim(); + if (text) { + excerpt.textContent = text.length > 160 ? text.slice(0, 160) + '…' : text; + link.append(excerpt); + } + } + item.append(link); + fragment.append(item); + } + shown = Math.min(shown + 30, hits.length); + results.append(fragment); + more.hidden = shown === hits.length; + } + + function openSearch() { + document.getElementById('api-member-dialog')?.close(); + clearTimeout(closeTimer); + closeTimer = undefined; + dialog.classList.remove('is-closing'); + document.getElementById('menu-toggle').setAttribute('aria-expanded', 'false'); + document.querySelector('.site-header').classList.remove('menu-open'); + if (!dialog.open) dialog.showModal(); + input.focus(); + input.select(); + rememberSearch(); + if (worker) return; + worker = new Worker(new URL('public/search-worker.min.js', root), { type: 'module' }); + worker.addEventListener('message', event => { + if (event.data.e === 'index-ready') { + ready = true; + runQuery(); + } else if (event.data.e === 'query-ready') { + const query = pendingQueries.shift(); + if (query !== input.value.trim()) return; + hits = event.data.d; + shown = 0; + results.replaceChildren(); + status.textContent = hits.length ? `${hits.length} result${hits.length === 1 ? '' : 's'}` : `No results for “${query}”.`; + appendResults(); + } + }); + worker.addEventListener('error', () => { + status.textContent = 'Search is unavailable. You can still open the pages below.'; + shortcuts.hidden = false; + }); + worker.postMessage({ init: {} }); + } + + function closeSearch() { + if (!dialog.open || closeTimer) return; + rememberSearch(false); + if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) { + dialog.close(); + return; + } + dialog.classList.add('is-closing'); + closeTimer = setTimeout(() => dialog.close(), 160); + } + + trigger.addEventListener('click', openSearch); + input.addEventListener('input', runQuery); + document.getElementById('search-close').addEventListener('click', closeSearch); + dialog.addEventListener('close', () => { + if (dialog.open) return; + clearTimeout(closeTimer); + closeTimer = undefined; + dialog.classList.remove('is-closing'); + rememberSearch(); + trigger.focus({ preventScroll: true }); + }); + dialog.addEventListener('cancel', event => { + event.preventDefault(); + closeSearch(); + }); + dialog.addEventListener('click', event => { + if (event.target.closest('[data-search-item]')) rememberSearch(); + if (event.target === dialog) closeSearch(); + }); + document.getElementById('site-search-form').addEventListener('submit', event => { + event.preventDefault(); + results.querySelector('a')?.click(); + }); + more.addEventListener('click', () => { + const next = shown; + appendResults(); + results.children[next]?.querySelector('a').focus(); + }); + document.addEventListener('keydown', event => { + const command = (event.metaKey || event.ctrlKey) && event.key.toLowerCase() === 'k'; + const slash = event.key === '/' && !event.metaKey && !event.ctrlKey && !event.altKey; + const editing = event.target.closest('input, textarea, select, [contenteditable]'); + if (command || slash && !editing) { + event.preventDefault(); + if (dialog.open && command && !closeTimer) closeSearch(); + else openSearch(); + } + }); + dialog.addEventListener('keydown', event => { + if (event.key === 'Escape') { + event.preventDefault(); + event.stopPropagation(); + closeSearch(); + return; + } + if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') return; + const links = [...dialog.querySelectorAll('[data-search-item]')].filter(link => link.getClientRects().length); + if (!links.length) return; + event.preventDefault(); + const current = links.indexOf(document.activeElement); + const next = event.key === 'ArrowDown' ? (current + 1) % links.length : (current <= 0 ? links.length - 1 : current - 1); + links[next].focus(); + }, { capture: true }); + + // Restore the search when returning from a result, including a full reload. + function restoreSearch() { + const saved = history.state?.zenithSearch; + if (!saved?.open) return; + const queryChanged = input.value !== saved.query; + input.value = saved.query; + if (!dialog.open) { + openSearch(); + runQuery(); + } else { + input.focus(); + input.select(); + if (queryChanged) runQuery(); + } + } + // Run after history traversal restores form controls, including Safari's search input. + window.addEventListener('pageshow', () => setTimeout(restoreSearch, 0)); + restoreSearch(); +} diff --git a/documents/toc.yml b/documents/toc.yml index b1d527b5..39295b03 100644 --- a/documents/toc.yml +++ b/documents/toc.yml @@ -1,10 +1,6 @@ -- name: Docs - href: docs/ - homepage: docs/index.md - -- name: Tutorials - href: tutorials/ - homepage: tutorials/index.md +- name: Learn + href: learn/ + homepage: learn/index.md - name: API href: api/ diff --git a/documents/tutorials/getting-started/application-host.md b/documents/tutorials/getting-started/application-host.md deleted file mode 100644 index a0e3a224..00000000 --- a/documents/tutorials/getting-started/application-host.md +++ /dev/null @@ -1,291 +0,0 @@ -# Application Host - -Every workload guide runs inside the same application host. The host owns the window and graphics context, creates the swap chain, records the outer frame transitions, and presents textures produced by compute workloads. - -This page explains that contract before the guides begin creating workload resources. Platform integration is host infrastructure and remains in the complete reference source rather than the walkthrough. - -## Responsibilities - -The shared host is responsible for: - -- selecting a supported graphics API for the current operating system; -- creating a window surface and swap chain; -- providing the active `GraphicsContext` and framebuffer dimensions; -- obtaining one graphics command buffer per frame; -- transitioning the swap-chain drawable into and out of attachment layout; -- forwarding update, render, and resize events to the active workload; -- submitting work, waiting for completion, and presenting the drawable; -- loading shared assets and presenting offscreen textures. - -The workload renderer remains responsible for its own buffers, textures, pipelines, commands, transitions, and disposal. - -## Renderer contract - -Create `IRenderer.cs`: - -```csharp -namespace ZenithTutorials; - -internal interface IRenderer : IDisposable -{ - void Update(double deltaTime); - - void Render(CommandBuffer commandBuffer, Texture drawable); - - void Resize(uint width, uint height); -} -``` - -The host calls `Update` before rendering, passes the current swap-chain texture to `Render`, and reports framebuffer size changes through `Resize`. Extending `IDisposable` makes each guide state its GPU ownership explicitly. - -## Create the graphics context - -`App` exposes one shared graphics context. Its static constructor selects DirectX 12 on Windows, Metal 4 on macOS, or Vulkan 1.4 on Linux. - -The complete `App.cs` contains the required imports and declares `App` as an `unsafe` static class because its upload helpers use pointers. - -```csharp -static App() -{ - if (!OperatingSystem.IsWindows() && !OperatingSystem.IsMacOS() && !OperatingSystem.IsLinux()) - { - throw new PlatformNotSupportedException("The tutorials support Windows, macOS, and Linux."); - } - - if (OperatingSystem.IsWindows()) - { - Context = GraphicsContext.CreateDirectX12(useValidationLayer: true); - } - else if (OperatingSystem.IsMacOS()) - { - Context = GraphicsContext.CreateMetal(useValidationLayer: true); - } - else - { - Context = GraphicsContext.CreateVulkan(useValidationLayer: true); - } - - Context.ValidationMessage += static (_, args) => Console.WriteLine($"[{args.Severity}] {args.Message}"); -} -``` - -Validation remains enabled throughout the guides. Validation messages are written to the terminal and should remain free of errors when a workload is running correctly. - -The host also publishes the shared color format and current framebuffer dimensions: - -```csharp -public static GraphicsContext Context { get; } - -public static PixelFormat ColorFormat => PixelFormat.B8G8R8A8UNorm; - -public static uint Width => (uint)(window?.FramebufferSize.X ?? 0); - -public static uint Height => (uint)(window?.FramebufferSize.Y ?? 0); -``` - -Framebuffer dimensions, rather than logical window dimensions, are used for textures, viewports, and projection aspect ratios. This matters on high-density displays. - -## Create the window and swap chain - -Silk.NET creates a window without an OpenGL context because Zenith.NET owns the native graphics API: - -```csharp -window = Window.Create(WindowOptions.Default with -{ - API = GraphicsAPI.None, - Title = "Zenith.NET Tutorials" -}); - -window.Initialize(); -window.Center(); -``` - -The host creates a Zenith.NET `Surface` from the window. That platform integration is contained in `App.cs` and `CocoaHelper.cs`; workload renderers depend only on the resulting swap chain. The surface and shared color format define that swap chain: - -```csharp -swapChain = Context.CreateSwapChain(new() -{ - Surface = surface, - Format = ColorFormat -}); -``` - -## Follow one frame - -The outer frame has the same shape for every workload: - -```mermaid -flowchart LR - A[Update workload] --> B[Acquire command buffer] - B --> C[Drawable to ColorAttachment] - C --> D[Record workload] - D --> E[Drawable to Present] - E --> F[Submit and wait] - F --> G[Present swap chain] -``` - -The render callback records those operations in order: - -```csharp -window.Render += _ => -{ - if (Width is 0 || Height is 0) - { - return; - } - - CommandBuffer commandBuffer = Context.GraphicsQueue.CommandBuffer(); - - commandBuffer.Transition(swapChain.Drawable, default, TextureLayout.Undefined, TextureLayout.ColorAttachment); - - renderer.Render(commandBuffer, swapChain.Drawable); - - commandBuffer.Transition(swapChain.Drawable, default, TextureLayout.ColorAttachment, TextureLayout.Present); - - commandBuffer.Submit().Wait(); - - swapChain.Present(); -}; -``` - -The workload starts with a drawable already in `ColorAttachment` layout and must leave it in that layout. The host performs the final transition to `Present`. - -`Submit().Wait()` deliberately permits only one frame of work at a time. That makes resource lifetime and CPU uploads easier to follow, but it is not a production frame scheduler. Applications that keep multiple frames in flight need per-frame resources and explicit reuse synchronization. - -## Update and resize - -The update callback forwards elapsed seconds: - -```csharp -window.Update += delta => -{ - if (Width is 0 || Height is 0) - { - return; - } - - renderer.Update(delta); -}; -``` - -The resize callback lets the workload release size-dependent resources before resizing the swap chain: - -```csharp -window.Resize += _ => -{ - if (Width is 0 || Height is 0) - { - return; - } - - renderer.Resize(Width, Height); - swapChain.Resize(Width, Height); -}; -``` - -Zero-size checks cover minimized windows. A workload normally sets a depth or output texture to `null` during `Resize`; its next `Render` call creates a replacement at the new framebuffer size. - -## Upload shared data - -The guides use one helper for small static and CPU-updated buffers: - -```csharp -public static Buffer LoadBuffer(T[] data, BufferUsages usages) where T : unmanaged -{ - Buffer buffer = Context.CreateBuffer(new() - { - SizeInBytes = (uint)(sizeof(T) * data.Length), - StrideInBytes = (uint)sizeof(T), - Usages = usages, - Residency = MemoryResidency.CpuWriteOnly - }); - - fixed (T* pointer = data) - { - buffer.Upload(0, new() - { - Pointer = (nint)pointer, - SizeInBytes = (uint)(sizeof(T) * data.Length) - }); - } - - return buffer; -} -``` - -`SizeInBytes` controls allocation size, while `StrideInBytes` describes one array element. `BufferUsages` states how later commands or shaders consume the buffer. The helper uses `CpuWriteOnly` residency because these compact guides favor direct uploads over a staging system. - -## Present offscreen textures - -Compute Shader and Ray Tracing do not render directly into the swap-chain drawable. They write an offscreen texture, transition it to `Sampled`, and pass it to `App.PresentTexture`. - -`TexturePresenter` owns a sampler, a two-handle constant buffer, and a fullscreen-triangle graphics pipeline: - -The complete presenter is also declared `unsafe` because it uploads a pointer to its local `Constants` value. - -| Resource | Role | -| --- | --- | -| Sampler | Samples the input texture with linear filtering and clamp addressing | -| Constant buffer | Carries sampled-texture and sampler handles to Slang | -| Graphics pipeline | Draws a fullscreen triangle into the current drawable | - -The presenter calculates a destination rectangle, uploads the two handles, and records a small render pass: - -```csharp -Constants constants = new() -{ - Image = texture.SampledHandle, - Sampler = sampler.Handle -}; - -constantBuffer.Upload(0, new() -{ - Pointer = (nint)(&constants), - SizeInBytes = (uint)sizeof(Constants) -}); -``` - -```csharp -commandBuffer.BeginRenderPass([ColorAttachment.Clear(drawable, new(0.04f, 0.055f, 0.075f, 1.0f))], null); - -commandBuffer.SetPipeline(pipeline); -commandBuffer.SetViewports([new() { X = x, Y = y, Width = width, Height = height, MaxDepth = 1.0f }]); -commandBuffer.SetScissors([new() { X = x, Y = y, Width = width, Height = height }]); -commandBuffer.SetConstantBuffer(constantBuffer, 0); - -commandBuffer.Draw(3, 1, 0, 0); - -commandBuffer.EndRenderPass(); -``` - -Its vertex shader derives a fullscreen triangle from `SV_VertexID`, so no vertex buffer is required. Workload guides treat this presenter as host infrastructure and focus on producing the sampled texture correctly. - -## Resource lifetime - -The `using TRenderer renderer = new();` declaration scopes the active renderer to the `try` body, so it is disposed when that body exits. The `finally` block then releases the host-owned presenter, swap chain, window, and graphics context: - -```csharp -finally -{ - texturePresenter?.Dispose(); - swapChain?.Dispose(); - window?.Dispose(); - - Context.Dispose(); -} -``` - -The sample disposes temporary shader objects after pipeline creation. Buffers and textures remain alive until every submitted GPU command that references them has completed. A top-level acceleration structure is a stronger ownership example: keep every BLAS it instances alive until the TLAS is no longer used. - -## Complete source - -Use the complete host implementation as the shared starting point for the workload guides: - -- [App.cs](https://github.com/qian-o/ZenithTutorials/blob/master/ZenithTutorials/App.cs) -- [IRenderer.cs](https://github.com/qian-o/ZenithTutorials/blob/master/ZenithTutorials/IRenderer.cs) -- [CocoaHelper.cs](https://github.com/qian-o/ZenithTutorials/blob/master/ZenithTutorials/CocoaHelper.cs) -- [TexturePresenter.cs](https://github.com/qian-o/ZenithTutorials/blob/master/ZenithTutorials/TexturePresenter.cs) -- [PresentTexture.slang](https://github.com/qian-o/ZenithTutorials/blob/master/ZenithTutorials/Assets/Shaders/PresentTexture.slang) -- [Program.cs](https://github.com/qian-o/ZenithTutorials/blob/master/ZenithTutorials/Program.cs) - -The reference `Program.cs` presents a menu for all six completed renderers. Continue with [Hello Triangle](../guides/hello-triangle.md) to create the first workload renderer and understand the first menu entry. diff --git a/documents/tutorials/getting-started/project-setup.md b/documents/tutorials/getting-started/project-setup.md deleted file mode 100644 index 065e9e12..00000000 --- a/documents/tutorials/getting-started/project-setup.md +++ /dev/null @@ -1,134 +0,0 @@ -# Project Setup - -This page creates the .NET project used throughout the guides. It installs the current Zenith.NET packages, enables the low-level C# features used for GPU uploads, and configures shader and texture assets for the build output. - -The runnable reference implementation is maintained separately in [ZenithTutorials](https://github.com/qian-o/ZenithTutorials). You do not need to clone that repository to follow the guides. - -## Requirements - -Install the [.NET 10 SDK](https://dotnet.microsoft.com/download/dotnet/10.0) and a current graphics driver. Verify the SDK from a terminal: - -```console -dotnet --list-sdks -``` - -Zenith.NET selects a supported graphics API for the current operating system: - -| Operating system | Graphics API | -| --- | --- | -| Windows | DirectX 12 | -| macOS | Metal 4 | -| Linux | Vulkan 1.4 | - -Ray tracing and mesh shading are optional device capabilities. The corresponding guides check support at runtime before creating those resources. - -## Create the project - -Create a .NET 10 console application and enter its directory: - -```console -dotnet new console --framework net10.0 --name ZenithTutorials -cd ZenithTutorials -``` - -Add the windowing package, the Zenith.NET graphics packages, and the ImageSharp extension. No version is specified, so the CLI selects the latest compatible package available from the configured NuGet sources. - -```console -dotnet package add Silk.NET.Windowing -dotnet package add Zenith.NET -dotnet package add Zenith.NET.DirectX12 -dotnet package add Zenith.NET.Metal -dotnet package add Zenith.NET.Vulkan -dotnet package add Zenith.NET.Extensions.ImageSharp -``` - -All three graphics packages can remain in one project. The application host creates only the graphics context selected for the current operating system. - -## Configure the project - -Open `ZenithTutorials.csproj`. Keep the package references generated by the CLI and make sure the main property group contains these settings: - -```xml - - Exe - net10.0 - enable - enable - true - -``` - -Several guides upload unmanaged structures by pointer, so `AllowUnsafeBlocks` is required. Nullable analysis remains enabled for resources that are created lazily or recreated after a resize. - -`AllowUnsafeBlocks` permits unsafe code to compile; the type or method containing each pointer expression must still be declared `unsafe`. The reference host and the renderers that upload structures by pointer include that declaration in their complete source files. - -Shaders and textures are opened at runtime from the application directory. Add this item group after the package references: - -```xml - - - PreserveNewest - - -``` - -`PreserveNewest` copies changed assets without rewriting every file on every build. - -## Create the source layout - -Create the following folders and files as the guides introduce them: - -```text -ZenithTutorials/ -├── Assets/ -│ ├── Shaders/ -│ └── Textures/ -├── Renderers/ -├── App.cs -├── CocoaHelper.cs -├── IRenderer.cs -├── Program.cs -├── TexturePresenter.cs -├── Usings.cs -└── ZenithTutorials.csproj -``` - -The application host is shared by every guide. Each workload adds one renderer under `Renderers` and one Slang source file under `Assets/Shaders`. - -These guides are walkthroughs of the current reference implementation rather than file-by-file listings. Each code fence is a contiguous excerpt from that implementation. Use the **Complete source** links at the end of a page when assembling the runnable file; the surrounding text explains why the excerpt exists and how it participates in the workload. - -## Add shared namespaces - -Create `Usings.cs`: - -```csharp -global using System.Numerics; -global using System.Runtime.CompilerServices; -global using System.Runtime.InteropServices; -global using Zenith.NET; -global using Zenith.NET.Extensions.ImageSharp; -global using Buffer = Zenith.NET.Buffer; -``` - -The alias on the final line resolves the name shared by `System.Buffer` and `Zenith.NET.Buffer`. `System.Numerics` supplies the vectors and matrices used by both the CPU data structures and the camera calculations. - -## Build the empty project - -Build once before adding the host: - -```console -dotnet build -``` - -A successful build confirms that the SDK and packages restore correctly. No graphics device or window is created during `dotnet build`; those operations begin when the application runs. - -Continue with [Application Host](application-host.md) to add the shared window, graphics context, swap chain, and frame loop. - -## Reference project - -The finished project configuration and shared usings are available in the tutorial repository: - -- [ZenithTutorials.csproj](https://github.com/qian-o/ZenithTutorials/blob/master/ZenithTutorials/ZenithTutorials.csproj) -- [Usings.cs](https://github.com/qian-o/ZenithTutorials/blob/master/ZenithTutorials/Usings.cs) - -The reference repository uses local project references so it can track Zenith.NET development. For a standalone reader project, keep the NuGet package references created above. diff --git a/documents/tutorials/guides/compute-shader.md b/documents/tutorials/guides/compute-shader.md deleted file mode 100644 index 66b1f54d..00000000 --- a/documents/tutorials/guides/compute-shader.md +++ /dev/null @@ -1,253 +0,0 @@ -# Compute Shader - -Compute Shader produces an image without a render pass. A compute pipeline reads a sampled texture, converts one pixel per thread to grayscale, and writes a storage texture. The host then presents that output with its shared fullscreen-triangle pipeline. - -The grayscale conversion makes the result easy to inspect, but the guide focuses on Zenith.NET resource handles, compute dispatch, and texture layout transitions rather than color-science derivations. - -## Result - -![An image converted to grayscale by a Zenith.NET compute shader](https://raw.githubusercontent.com/qian-o/ZenithTutorials/master/ZenithTutorials/Assets/Screenshots/compute-shader.png) - -The source image is processed once at its original dimensions. It is displayed at those dimensions while the framebuffer is at least as large as the image. Threads outside the image bounds are discarded when the dimensions are not exact multiples of the thread-group size. - -## Frame overview - -```mermaid -flowchart LR - A{Already processed?} -- No --> B[Output to Storage] - B --> C[Bind compute pipeline and constants] - C --> D[Dispatch thread groups] - D --> E[Output to Sampled] - E --> F[Present texture] - A -- Yes --> F -``` - -The output is static, so the compute pass runs only during the first frame. Later frames reuse the sampled result. - -## Resource map - -| Resource | Usage | Access | -| --- | --- | --- | -| Input texture | `Sampled` | Compute shader reads pixels | -| Output texture | `Storage` and `Sampled` | Compute shader writes; presenter reads | -| Constant buffer | `Constant` | Width, height, and two resource handles | -| Compute shader | `CSMain` | One thread per output pixel | -| Compute pipeline | Compute dispatch | Binds the shader executable | - -The output texture needs both usages at creation time because it changes roles after the dispatch. - -## Load the input texture - -Place an image at `Assets/Textures/shoko.png`. The project configuration from Project Setup copies it next to the executable. The ImageSharp extension loads it into a sampled Zenith.NET texture: - -```csharp -inputTexture = App.LoadTexture("shoko.png", false); -``` - -The final argument disables mipmap generation because this workload reads exact source pixels with `Texture2D.Load`. - -`App.LoadTexture` completes the upload before returning and leaves the loaded mip in `Sampled` layout. The compute pass therefore needs no input-texture transition; only the output texture changes layout during `Render`. - -## Create the output texture - -Create a floating-point texture with the same dimensions as the source: - -```csharp -outputTexture = App.Context.CreateTexture(new() -{ - Type = TextureType.Texture2D, - Format = PixelFormat.R32G32B32A32Float, - Width = inputTexture.Desc.Width, - Height = inputTexture.Desc.Height, - Depth = 1, - MipLevels = 1, - ArrayLayers = 1, - SampleCount = SampleCount.Count1, - Usages = TextureUsages.Sampled | TextureUsages.Storage -}); -``` - -`R32G32B32A32Float` matches the shader's writable `float4` element type. `Storage` permits writes during compute; `Sampled` permits reads by `TexturePresenter` afterward. - -## Data contract - -The constant buffer passes image dimensions and descriptor handles: - -```slang -struct Constants -{ - uint Width; - - uint Height; - - DescriptorHandle Input; - - DescriptorHandle> Output; -}; - -ConstantBuffer constants; -``` - -The declaration after the structure binds that contract as the constant-buffer view read by `CSMain`. - -The C# layout matches the two four-byte integers followed by two eight-byte handles: - -```csharp -[StructLayout(LayoutKind.Explicit, Size = 256)] -file struct Constants -{ - [FieldOffset(0)] - public uint Width; - - [FieldOffset(4)] - public uint Height; - - [FieldOffset(8)] - public ResourceHandle Input; - - [FieldOffset(16)] - public ResourceHandle Output; -} -``` - -| Offset | C# value | Slang view | -| ---: | --- | --- | -| 0 | `inputTexture.Desc.Width` | `uint Width` | -| 4 | `inputTexture.Desc.Height` | `uint Height` | -| 8 | `inputTexture.SampledHandle` | `DescriptorHandle` | -| 16 | `outputTexture.StorageHandle` | `DescriptorHandle>` | - -The structure reserves a 256-byte constant-buffer allocation while its semantic fields occupy the leading bytes. The offsets, rather than the C# field names, define the shared binary contract. - -Initialize and upload one value: - -```csharp -Constants constants = new() -{ - Width = inputTexture.Desc.Width, - Height = inputTexture.Desc.Height, - Input = inputTexture.SampledHandle, - Output = outputTexture.StorageHandle -}; - -constantBuffer = App.LoadBuffer([constants], BufferUsages.Constant); -``` - -## Shader interface - -The shader declares a $16 \times 16$ thread group: - -```slang -[shader("compute")] -[numthreads(16, 16, 1)] -void CSMain(uint3 dispatchThreadID: SV_DispatchThreadID) -{ - uint2 pixel = dispatchThreadID.xy; - - if (pixel.x >= constants.Width || pixel.y >= constants.Height) - { - return; - } - - float4 color = constants.Input.Load(int3(pixel, 0)); - float3 linear = pow(color.rgb, 2.2); - float grayscale = dot(linear, float3(0.2126, 0.7152, 0.0722)); - grayscale = pow(grayscale, 1.0 / 2.2); - - constants.Output[pixel] = float4(grayscale, grayscale, grayscale, color.a); -} -``` - -`SV_DispatchThreadID` is the global thread coordinate across all dispatched groups. The bounds check is essential because group counts round up to cover partial groups at the image edges. - -The middle lines approximate conversion to linear light, calculate luminance, and convert back for display. That effect can be replaced without changing the pipeline or resource flow; the important interface is one sampled read and one storage write at the same pixel coordinate. - -## Create the compute pipeline - -Compile the compute entry point and create its pipeline: - -```csharp -using Shader computeShader = App.LoadShader("ComputeShader.slang", "CSMain"); - -computePipeline = App.Context.CreateComputePipeline(new() { ComputeShader = computeShader }); -``` - -A compute pipeline has no attachment formats or rasterizer state. It executes outside a render pass. - -## Dispatch the workload - -Before the first dispatch, transition the output from its undefined initial contents into writable storage layout: - -```csharp -commandBuffer.Transition(outputTexture, default, TextureLayout.Undefined, TextureLayout.Storage); - -commandBuffer.SetPipeline(computePipeline); -commandBuffer.SetConstantBuffer(constantBuffer, 0); -commandBuffer.Dispatch((inputTexture.Desc.Width + ThreadGroupSize - 1) / ThreadGroupSize, (inputTexture.Desc.Height + ThreadGroupSize - 1) / ThreadGroupSize, 1); -``` - -For a dimension $D$ and group size $G$, integer ceiling division is: - -$$ -\left\lceil \frac{D}{G} \right\rceil = \frac{D + G - 1}{G} -$$ - -After all storage writes, transition the texture for sampled reads: - -```csharp -commandBuffer.Transition(outputTexture, default, TextureLayout.Storage, TextureLayout.Sampled); - -processed = true; -``` - -The command buffer preserves this order: transition, dispatch, then transition. The presenter consumes the texture only after it reaches `Sampled` layout. - -## Present the output - -Every frame, including the first, hands the sampled result to the shared presenter: - -```csharp -App.PresentTexture(commandBuffer, drawable, outputTexture, false); -``` - -Passing `false` preserves the texture's original size and centers it when the framebuffer is at least as large in both dimensions. In a smaller framebuffer, the presenter clamps each viewport dimension to the available size. The presenter records the graphics render pass that writes the swap-chain drawable. - -## Lifetime - -This image does not depend on the framebuffer size, so `Resize` is empty. Dispose each renderer-owned resource after the final submitted frame has completed: - -```csharp -public void Dispose() -{ - computePipeline.Dispose(); - constantBuffer.Dispose(); - outputTexture.Dispose(); - inputTexture.Dispose(); -} -``` - -## Inspect the result - -Run the host and select **Compute Shader**. Confirm that: - -- the complete source image appears in grayscale; -- no unprocessed strip appears along the right or bottom edge; -- resizing to a framebuffer at least as large as the image preserves its original display size; -- validation reports no storage/sampled usage or layout errors. - -An unprocessed edge usually indicates floor division or a missing bounds check. A blank result often indicates an incorrect descriptor handle or a missing `Storage` to `Sampled` transition. - -## Explore further - -1. Replace the grayscale calculation with `constants.Output[pixel] = color` to verify a direct copy. -2. Invert `color.rgb` while preserving alpha. -3. Change the declared thread-group size and update the C# `ThreadGroupSize` constant to match. -4. Set `fitToWindow` to `true` when presenting and compare the viewport behavior. - -## Complete source - -- [ComputeShaderRenderer.cs](https://github.com/qian-o/ZenithTutorials/blob/master/ZenithTutorials/Renderers/ComputeShaderRenderer.cs) -- [ComputeShader.slang](https://github.com/qian-o/ZenithTutorials/blob/master/ZenithTutorials/Assets/Shaders/ComputeShader.slang) -- [Input texture](https://github.com/qian-o/ZenithTutorials/blob/master/ZenithTutorials/Assets/Textures/shoko.png) - -Continue with [Ray Tracing](ray-tracing.md) to reuse the compute-output flow for an image regenerated from inline ray queries every frame. diff --git a/documents/tutorials/guides/hello-triangle.md b/documents/tutorials/guides/hello-triangle.md deleted file mode 100644 index 002017d3..00000000 --- a/documents/tutorials/guides/hello-triangle.md +++ /dev/null @@ -1,216 +0,0 @@ -# Hello Triangle - -Hello Triangle is the smallest complete graphics workload in the series. It uploads three colored vertices, compiles one vertex and one fragment entry point, creates a graphics pipeline, and records a single draw into the swap-chain texture. - -This guide focuses on how vertex data moves from C# through a Zenith.NET pipeline into Slang. The shared window, command submission, and presentation loop come from [Application Host](../getting-started/application-host.md). - -## Result - -![A vertex-colored triangle rendered with Zenith.NET](https://raw.githubusercontent.com/qian-o/ZenithTutorials/master/ZenithTutorials/Assets/Screenshots/hello-triangle.png) - -The final image is one triangle on a dark clear color. Red, green, and blue values are supplied per vertex and interpolated by the rasterizer across the covered fragments. - -## Frame overview - -The renderer creates its long-lived resources once. Each frame then records one render pass: - -```mermaid -flowchart LR - A[Drawable in ColorAttachment] --> B[Begin render pass and clear] - B --> C[Bind graphics pipeline] - C --> D[Bind vertex buffer] - D --> E[Draw 3 vertices] - E --> F[End render pass] -``` - -The host transitions the drawable into `ColorAttachment` before calling the renderer and transitions it to `Present` afterward. - -## Resource map - -| Resource | Created from | Consumed by | -| --- | --- | --- | -| Vertex buffer | Three `Vertex` values | Vertex input stage | -| Vertex shader | `VSMain` in `HelloTriangle.slang` | Graphics pipeline | -| Fragment shader | `FSMain` in `HelloTriangle.slang` | Graphics pipeline | -| Graphics pipeline | Shaders, input layout, attachment format, render state | Draw command | -| Swap-chain drawable | Application host | Color attachment | - -There is no index buffer, constant buffer, depth attachment, or descriptor handle in this first workload. - -## Data contract - -The CPU vertex stores a three-component position followed by a four-component color: - -```csharp -[StructLayout(LayoutKind.Sequential)] -file struct Vertex(Vector3 position, Vector4 color) -{ - public Vector3 Position = position; - - public Vector4 Color = color; -} -``` - -The corresponding Slang input uses matching attribute types and semantic names: - -```slang -struct VSInput -{ - float3 Position : POSITION0; - - float4 Color : COLOR0; -}; -``` - -An `InputLayout` connects the buffer fields to those semantics: - -```csharp -InputLayout inputLayout = new(); -inputLayout.Add(new() { Format = ElementFormat.Float3, Semantic = ElementSemantic.Position }); -inputLayout.Add(new() { Format = ElementFormat.Float4, Semantic = ElementSemantic.Color }); -``` - -The layout order matches the C# field order. `App.LoadBuffer` supplies `sizeof(Vertex)` as the buffer stride, so the GPU advances by one complete position-and-color record for each vertex. - -## Create the vertex buffer - -The renderer defines three positions directly in clip space. Their colors become the three corners visible in the result: - -```csharp -Vertex[] vertices = -[ - new(new(0.0f, 0.6f, 0.0f), new(1.0f, 0.2f, 0.15f, 1.0f)), - new(new(0.6f, -0.5f, 0.0f), new(0.15f, 0.85f, 0.35f, 1.0f)), - new(new(-0.6f, -0.5f, 0.0f), new(0.2f, 0.45f, 1.0f, 1.0f)) -]; - -vertexBuffer = App.LoadBuffer(vertices, BufferUsages.Vertex); -``` - -`BufferUsages.Vertex` declares that later commands will bind this allocation as vertex input. Because the coordinates already lie in clip space, the workload does not need model, view, or projection matrices. - -## Shader interface - -The vertex shader converts each `float3` position into homogeneous clip-space coordinates and forwards the color: - -```slang -struct FSInput -{ - float4 Position : SV_POSITION; - - float4 Color : COLOR0; -}; - -[shader("vertex")] -FSInput VSMain(VSInput input) -{ - FSInput output; - output.Position = float4(input.Position, 1.0); - output.Color = input.Color; - - return output; -} -``` - -`SV_POSITION` is consumed by rasterization. `COLOR0` is a user varying: the rasterizer interpolates it, then supplies the interpolated value to the fragment shader. - -```slang -[shader("fragment")] -float4 FSMain(FSInput input) : SV_TARGET -{ - return input.Color; -} -``` - -`SV_TARGET` marks the returned value as the color written to the active color attachment. - -## Create the pipeline - -Compile both named entry points and create the graphics pipeline: - -```csharp -using Shader vertexShader = App.LoadShader("HelloTriangle.slang", "VSMain"); -using Shader fragmentShader = App.LoadShader("HelloTriangle.slang", "FSMain"); - -pipeline = App.Context.CreateGraphicsPipeline(new() -{ - VertexShader = vertexShader, - FragmentShader = fragmentShader, - InputLayouts = [inputLayout], - PrimitiveTopology = PrimitiveTopology.TriangleList, - AttachmentFormats = new() - { - ColorFormats = [App.ColorFormat], - SampleCount = SampleCount.Count1 - }, - RenderState = new() - { - Rasterizer = RasterizerState.CullNone(), - DepthStencil = DepthStencilState.DepthNone(), - Blend = BlendState.Opaque() - } -}); -``` - -The attachment format must match the swap chain. A triangle list consumes every group of three vertices as one triangle. Culling and depth testing are unnecessary because this workload has one two-dimensional primitive and no depth attachment. - -The `using` declarations limit the temporary `Shader` objects to pipeline creation. - -## Record the frame - -The render method clears the drawable, binds the two resources required by the draw, and emits one triangle: - -```csharp -public void Render(CommandBuffer commandBuffer, Texture drawable) -{ - commandBuffer.BeginRenderPass([ColorAttachment.Clear(drawable, new(0.04f, 0.055f, 0.075f, 1.0f))], null); - - commandBuffer.SetPipeline(pipeline); - commandBuffer.SetVertexBuffer(vertexBuffer, 0, 0); - - commandBuffer.Draw(3, 1, 0, 0); - - commandBuffer.EndRenderPass(); -} -``` - -The arguments to `Draw` request three vertices, one instance, first vertex zero, and first instance zero. No explicit viewport or scissor is needed here; the render pass uses the drawable dimensions. - -## Resource lifetime - -This renderer has no animated or size-dependent resources, so `Update` and `Resize` remain empty. Dispose both renderer-owned resources after the final submitted frame has completed: - -```csharp -public void Dispose() -{ - pipeline.Dispose(); - vertexBuffer.Dispose(); -} -``` - -## Inspect the result - -Run the tutorial host and select **Hello Triangle**. Confirm that: - -- the triangle appears centered on the dark background; -- all three corner colors are visible and interpolate smoothly; -- resizing the window preserves the workload without recreating resources; -- the validation layer reports no errors. - -If the pipeline is rejected, first compare `App.ColorFormat` with `AttachmentFormats.ColorFormats`. If geometry is missing or corrupted, compare the C# field order, `InputLayout`, and Slang semantics. - -## Explore further - -Try these changes independently: - -1. Change the x and y components while keeping them in $[-1,1]$; leave z at 0 so the vertices remain in the visible depth range. -2. Replace all three colors with one constant color and observe that interpolation no longer produces a gradient. -3. Reverse two vertices and enable back-face culling to inspect how winding affects visibility. -4. Add a fourth vertex and change the topology to explore how a triangle list groups input vertices. - -## Complete source - -- [HelloTriangleRenderer.cs](https://github.com/qian-o/ZenithTutorials/blob/master/ZenithTutorials/Renderers/HelloTriangleRenderer.cs) -- [HelloTriangle.slang](https://github.com/qian-o/ZenithTutorials/blob/master/ZenithTutorials/Assets/Shaders/HelloTriangle.slang) - -Continue with [Spinning Cube](spinning-cube.md) to add indexed geometry, transformation constants, back-face culling, and a depth attachment. diff --git a/documents/tutorials/guides/indirect-drawing.md b/documents/tutorials/guides/indirect-drawing.md deleted file mode 100644 index af6ab622..00000000 --- a/documents/tutorials/guides/indirect-drawing.md +++ /dev/null @@ -1,289 +0,0 @@ -# Indirect Drawing - -Indirect Drawing reuses the depth-tested cube pipeline to render a $5 \times 5$ grid of animated instances. One structured buffer stores the model matrix and tint for each cube, while one indirect argument record supplies the indexed draw counts to the GPU. - -Two mechanisms are involved: - -- **instancing** draws the shared geometry multiple times and assigns each invocation an `SV_InstanceID`; -- **indirect drawing** reads draw parameters from a buffer instead of C# method arguments. - -The CPU still updates instance data in this workload. The indirect buffer demonstrates the command format; it is not generated by a GPU culling pass. - -## Result - -![A grid of instanced cubes rendered with one indirect draw](https://raw.githubusercontent.com/qian-o/ZenithTutorials/master/ZenithTutorials/Assets/Screenshots/indirect-drawing.png) - -Twenty-five cubes share one vertex buffer, one index buffer, one graphics pipeline, and one indirect draw record. Their positions, rotations, and colors vary through structured instance data. - -## Frame overview - -```mermaid -flowchart LR - A[Update 25 Instance records] --> B[Upload structured buffer] - B --> C[Begin color and depth pass] - C --> D[Bind geometry, constants, and pipeline] - D --> E[DrawIndexedIndirect one record] - E --> F[End render pass] -``` - -The indirect record is static in this example; only the instance buffer changes each frame. - -## Resource map - -| Resource | Usage | Contents | -| --- | --- | --- | -| Vertex buffer | `Vertex` | Shared cube corners | -| Index buffer | `Index` | 36 cube indices | -| Instance buffer | `StorageReadOnly` | 25 model matrices and colors | -| Indirect buffer | `Indirect` | One `IndirectDrawIndexedArgs` record | -| Constant buffer | `Constant` | View, projection, and instance-buffer handle | -| Graphics pipeline | Indexed instanced rendering | Depth and back-face culling enabled | -| Depth texture | Depth-stencil attachment | Recreated after resize | - -The shader reaches the structured buffer through a descriptor handle stored in the constant buffer. It does not bind the instance buffer as vertex input. - -## Define the indirect command - -The indirect structure contains the same values supplied to a direct indexed draw: - -```csharp -IndirectDrawIndexedArgs arguments = new() -{ - IndexCount = (uint)indices.Length, - InstanceCount = GridSize * GridSize -}; -``` - -Unassigned fields remain zero, so this record means: - -| Field | Value | Meaning | -| --- | ---: | --- | -| `IndexCount` | 36 | Indices consumed per instance | -| `InstanceCount` | 25 | Number of cube instances | -| `FirstIndex` | 0 | Start of the index buffer | -| `VertexOffset` | 0 | Added to each selected index | -| `FirstInstance` | 0 | Starting system instance ID | - -Upload one record with `BufferUsages.Indirect`: - -```csharp -indirectBuffer = App.LoadBuffer([arguments], BufferUsages.Indirect); -``` - -The final draw call requests one record from this buffer. It does not pass the instance count separately. - -## Instance data contract - -Each instance occupies 80 bytes in both C# and Slang: - -```csharp -[StructLayout(LayoutKind.Explicit, Size = 80)] -file struct Instance -{ - [FieldOffset(0)] - public Matrix4x4 Model; - - [FieldOffset(64)] - public Vector4 Color; -} -``` - -```slang -struct Instance -{ - float4x4 Model; - - float4 Color; -}; -``` - -The renderer allocates enough structured-buffer elements for the complete grid: - -```csharp -instanceBuffer = App.LoadBuffer(new Instance[GridSize * GridSize], BufferUsages.StorageReadOnly); -``` - -`App.LoadBuffer` records `sizeof(Instance)` as the stride. The shader therefore indexes a sequence of 80-byte records through `StructuredBuffer`. - -## Constant-buffer contract - -The vertex shader also needs the camera matrices and a handle to the instance buffer: - -```slang -struct Constants -{ - float4x4 View; - - float4x4 Projection; - - DescriptorHandle> Instances; -}; -``` - -The corresponding C# offsets place the handle after two 64-byte matrices: - -```csharp -[StructLayout(LayoutKind.Explicit, Size = 256)] -file struct Constants -{ - [FieldOffset(0)] - public Matrix4x4 View; - - [FieldOffset(64)] - public Matrix4x4 Projection; - - [FieldOffset(128)] - public ResourceHandle Instances; -} -``` - -On initialization and resize, upload `instanceBuffer.StorageReadOnlyHandle` with the current view and projection: - -```csharp -Constants constants = new() -{ - View = Matrix4x4.CreateLookAt(new(0.0f, 0.0f, 8.0f), Vector3.Zero, Vector3.UnitY), - Projection = Matrix4x4.CreatePerspectiveFieldOfView(float.DegreesToRadians(45.0f), (float)width / height, 0.1f, 100.0f), - Instances = instanceBuffer.StorageReadOnlyHandle -}; -``` - -## Select an instance in Slang - -`SV_InstanceID` is generated by the draw command. It is a system value, not an attribute in the C# `InputLayout`: - -```slang -struct VSInput -{ - float3 Position : POSITION0; - - float4 Color : COLOR0; - - uint InstanceID : SV_InstanceID; -}; -``` - -The vertex shader uses that ID to select one structured-buffer element: - -```slang -[shader("vertex")] -VSOutput VSMain(VSInput input) -{ - Instance instance = constants.Instances[input.InstanceID]; - float4 worldPosition = mul(float4(input.Position, 1.0), instance.Model); - float4 viewPosition = mul(worldPosition, constants.View); - - VSOutput output; - output.Position = mul(viewPosition, constants.Projection); - output.Color = input.Color * instance.Color; - - return output; -} -``` - -Every invocation reads the same cube geometry. The instance record supplies only its world transform and tint. - -## Update instance records - -The CPU calculates one record for every grid coordinate: - -```csharp -for (uint index = 0; index < GridSize * GridSize; index++) -{ - uint x = index % GridSize; - uint y = index / GridSize; - float offsetX = (x - ((GridSize - 1) * 0.5f)) * 1.5f; - float offsetY = (y - ((GridSize - 1) * 0.5f)) * 1.5f; - float rotation = rotationAngle * (1.0f + (index * 0.1f)); - - pointer[index] = new() - { - Model = Matrix4x4.CreateScale(0.4f) * Matrix4x4.CreateRotationY(rotation) * Matrix4x4.CreateRotationX(rotation * 0.5f) * Matrix4x4.CreateTranslation(offsetX, offsetY, 0.0f), - Color = new((float)x / GridSize, (float)y / GridSize, 1.0f - ((float)x / GridSize), 1.0f) - }; -} -``` - -After filling the array, upload all records in one contiguous copy: - -```csharp -instanceBuffer.Upload(0, new() -{ - Pointer = (nint)pointer, - SizeInBytes = (uint)(sizeof(Instance) * instances.Length) -}); -``` - -This direct CPU update is intentionally simple. A larger renderer would normally avoid allocating a new managed array every frame and would coordinate dynamic-buffer reuse across frames in flight. - -The shared host waits for each submitted frame before the next update, so this single instance buffer is not overwritten while an earlier frame is reading it. - -## Record the indirect draw - -Create the depth attachment on first use and transition it from `Undefined` to `DepthStencilAttachment`. The texture remains in that layout until resize replaces it. Then begin a color/depth render pass, bind the shared geometry and constants, and execute one indirect record: - -```csharp -if (depthTexture is null) -{ - depthTexture = App.Context.CreateTexture(TextureDesc.DepthStencilAttachment(PixelFormat.D32FloatS8UInt, App.Width, App.Height, SampleCount.Count1)); - - commandBuffer.Transition(depthTexture, default, TextureLayout.Undefined, TextureLayout.DepthStencilAttachment); -} - -commandBuffer.BeginRenderPass([ColorAttachment.Clear(drawable, new(0.04f, 0.055f, 0.075f, 1.0f))], DepthStencilAttachment.Clear(depthTexture, 1.0f, 0)); - -commandBuffer.SetPipeline(pipeline); -commandBuffer.SetVertexBuffer(vertexBuffer, 0, 0); -commandBuffer.SetIndexBuffer(indexBuffer, 0, IndexFormat.UInt32); -commandBuffer.SetConstantBuffer(constantBuffer, 0); - -commandBuffer.DrawIndexedIndirect(indirectBuffer, 0, 1); - -commandBuffer.EndRenderPass(); -``` - -The arguments mean indirect-buffer byte offset zero and draw count one. That one record expands to an indexed draw with 25 instances. - -The GPU does not read the indirect buffer through a shader descriptor. The command processor interprets it because the allocation was created with `BufferUsages.Indirect` and passed to `DrawIndexedIndirect`. - -## Resize and lifetime - -Resize invalidates the depth texture and uploads a projection for the new aspect ratio. Geometry, indirect arguments, and instance-buffer capacity remain unchanged. - -Release resources in dependency order: - -```csharp -depthTexture?.Dispose(); - -pipeline.Dispose(); -constantBuffer.Dispose(); -instanceBuffer.Dispose(); -indirectBuffer.Dispose(); -indexBuffer.Dispose(); -vertexBuffer.Dispose(); -``` - -## Inspect the result - -Run the host and select **Indirect Drawing**. Confirm that: - -- 25 cubes appear in a centered grid; -- each cube rotates and receives a distinct tint; -- resize preserves the grid proportions and depth behavior; -- validation reports no buffer-usage, structured-stride, or indirect-command errors. - -If every cube uses the same transform, inspect `SV_InstanceID` and the structured-buffer handle. If only one cube appears, inspect `InstanceCount` in the indirect record. If the draw is rejected, confirm `BufferUsages.Indirect` and the record layout. - -## Explore further - -1. Replace `DrawIndexedIndirect` temporarily with `DrawIndexed(36, GridSize * GridSize, 0, 0, 0)` and verify that the picture remains equivalent. -2. Change `GridSize`, then update buffer capacity and camera distance together. -3. Set `FirstInstance` to a nonzero value and account for it in the instance buffer. -4. Create multiple indirect records and increase the final `drawCount` argument. - -## Complete source - -- [IndirectDrawingRenderer.cs](https://github.com/qian-o/ZenithTutorials/blob/master/ZenithTutorials/Renderers/IndirectDrawingRenderer.cs) -- [IndirectDrawing.slang](https://github.com/qian-o/ZenithTutorials/blob/master/ZenithTutorials/Assets/Shaders/IndirectDrawing.slang) - -Continue with [Ray Tracing](ray-tracing.md) to see a different kind of GPU-readable scene structure, or [Mesh Shading](mesh-shading.md) to move geometry emission into programmable shader stages. diff --git a/documents/tutorials/guides/mesh-shading.md b/documents/tutorials/guides/mesh-shading.md deleted file mode 100644 index a8ae80a2..00000000 --- a/documents/tutorials/guides/mesh-shading.md +++ /dev/null @@ -1,454 +0,0 @@ -# Mesh Shading - -Mesh Shading replaces fixed vertex and index fetch with programmable task and mesh stages. This workload renders a $10 \times 10 \times 10$ sphere grid. Task threads test candidate instances against the camera frustum, compact visible IDs into a payload, and launch one mesh workgroup for each surviving sphere. - -This guide focuses on the Zenith.NET mesh-shading pipeline, structured geometry, C#/Slang layout, task payload, synchronization, and mesh dispatch. The UV-sphere construction and final diffuse-lighting calculation support the sample result but are not derived as general geometry or lighting algorithms. - -## Result - -![A culled grid of spheres emitted by task and mesh shaders](https://raw.githubusercontent.com/qian-o/ZenithTutorials/master/ZenithTutorials/Assets/Screenshots/mesh-shading.png) - -The camera moves around 1,000 possible sphere instances. Only instances intersecting the view frustum produce mesh workgroups and rasterized geometry. - -> [!IMPORTANT] -> Mesh shading is optional. Check `App.Context.Capabilities.MeshShadingSupported` before creating shaders, buffers, or a mesh-shading pipeline. - -## Frame overview - -```mermaid -flowchart LR - A[Update camera and frustum constants] --> B[Begin color and depth pass] - B --> C[Bind mesh-shading pipeline] - C --> D[Bind constants] - D --> E[Dispatch 32 task groups] - E --> F[Task groups compact visible IDs] - F --> G[Mesh groups emit sphere geometry] - G --> H[Rasterize and shade fragments] -``` - -No vertex or index buffer is bound through traditional command-buffer slots. The mesh shader reads source geometry through descriptor handles and writes pipeline outputs directly. - -## Pipeline stages - -```mermaid -flowchart TD - A[32 candidate IDs per task group] --> B[Frustum test] - B --> C[groupshared payload] - C --> D[DispatchMesh visible count] - D --> E[One mesh group per visible ID] - E --> F[Emit 62 vertices] - E --> G[Emit 120 triangles] - F --> H[Rasterization] - G --> H - H --> I[Fragment shader] -``` - -Zenith.NET calls the first stage `TaskShader`; Slang declares the corresponding entry point with `[shader("task")]`. Other APIs may call this an amplification or object stage. - -## Resource map - -| Resource | Usage | Role | -| --- | --- | --- | -| Vertex buffer | `StorageReadOnly` | Source sphere positions and normals | -| Triangle buffer | `StorageReadOnly` | Source sphere index triplets | -| Constant buffer | `Constant` | View-projection, frustum, light, and two handles | -| Task shader | `ASMain` | Culls and compacts candidate instance IDs | -| Mesh shader | `MSMain` | Emits transformed vertices and primitive indices | -| Fragment shader | `FSMain` | Applies simple directional lighting | -| Mesh-shading pipeline | Task, mesh, and fragment stages | Rasterized output | -| Depth texture | Depth-stencil attachment | Recreated after resize | - -The source geometry remains in structured buffers for the renderer lifetime. Each visible instance reuses the same 62 vertices and 120 triangles. - -## Check device support - -Reject unsupported devices before generating or uploading the source mesh: - -```csharp -if (!App.Context.Capabilities.MeshShadingSupported) -{ - throw new PlatformNotSupportedException("Mesh Shading is not supported by the selected device."); -} -``` - -The capability controls creation and execution of the task/mesh pipeline. It is independent of the traditional graphics pipeline used by earlier guides. - -## Create the source mesh - -The CPU generates one compact UV sphere with 62 vertices and 120 triangles. It creates a north pole, five latitude rings, a south pole, and indices for both caps and the ring quads. - -The complete generation loop is available in the renderer source. Its important output for this workload is two tightly defined arrays: - -```csharp -vertexBuffer = App.LoadBuffer([.. sphereVertices], BufferUsages.StorageReadOnly); -triangleBuffer = App.LoadBuffer([.. sphereTriangles], BufferUsages.StorageReadOnly); -constantBuffer = App.LoadBuffer([new Constants()], BufferUsages.Constant); -``` - -These are structured shader inputs, not traditional vertex and index bindings. Their element strides come from the explicit C# structures described next. - -## Geometry data contract - -Three-component vectors can receive different alignment across shader targets. The C# vertex therefore places position and normal at separate 16-byte boundaries: - -```csharp -[StructLayout(LayoutKind.Explicit, Size = 32)] -file struct Vertex -{ - [FieldOffset(0)] - public Vector3 Position; - - [FieldOffset(16)] - public Vector3 Normal; -} -``` - -The Slang side uses two `float4` backing values: - -```slang -struct Vertex -{ - private float4 PositionAndPadding; - - private float4 NormalAndPadding; - - property float3 Position - { - get { - return PositionAndPadding.xyz; - } - } - - property float3 Normal - { - get { - return NormalAndPadding.xyz; - } - } -}; -``` - -Triangle elements follow the same pattern. C# stores three indices in a 16-byte record: - -```csharp -[StructLayout(LayoutKind.Explicit, Size = 16)] -file struct Triangle -{ - [FieldOffset(0)] - public uint Index0; - - [FieldOffset(4)] - public uint Index1; - - [FieldOffset(8)] - public uint Index2; -} -``` - -Slang reads one `uint4` and exposes its first three lanes: - -```slang -struct Triangle -{ - private uint4 IndicesAndPadding; - - property uint3 Indices - { - get { - return IndicesAndPadding.xyz; - } - } -}; -``` - -| Structured element | C# size | Slang backing storage | -| --- | ---: | --- | -| `Vertex` | 32 bytes | Two `float4` values | -| `Triangle` | 16 bytes | One `uint4` value | - -Explicit backing storage keeps these strides consistent across the supported graphics APIs. - -## Frame constants - -The constant buffer supplies one view-projection matrix, six frustum planes, a light direction, and two structured-buffer handles: - -```csharp -[StructLayout(LayoutKind.Explicit, Size = 256)] -file struct Constants -{ - [FieldOffset(0)] - public Matrix4x4 ViewProjection; - - [FieldOffset(64)] - public FrustumPlanes FrustumPlanes; - - [FieldOffset(160)] - public Vector3 LightDirection; - - [FieldOffset(176)] - public ResourceHandle Vertices; - - [FieldOffset(184)] - public ResourceHandle Triangles; -} -``` - -`FrustumPlanes` is an inline array of six `Vector4` values, occupying 96 bytes from offset 64 through 159. Slang backs `LightDirection` with a `float4`, so the handles begin at byte 176 rather than immediately after the 12-byte C# `Vector3`. - -```slang -struct Constants -{ - float4x4 ViewProjection; - - float4 FrustumPlanes[6]; - - private float4 LightDirectionAndPadding; - - DescriptorHandle> Vertices; - - DescriptorHandle> Triangles; - - property float3 LightDirection - { - get { - return LightDirectionAndPadding.xyz; - } - } -}; -``` - -The renderer extracts and normalizes the six planes from the current view-projection matrix. That matrix extraction is supporting camera math; the mesh-shading interface only requires six consistently oriented `float4` plane equations. - -## Create the pipeline - -Compile all three stage entry points: - -```csharp -using Shader taskShader = App.LoadShader("MeshShading.slang", "ASMain"); -using Shader meshShader = App.LoadShader("MeshShading.slang", "MSMain"); -using Shader fragmentShader = App.LoadShader("MeshShading.slang", "FSMain"); -``` - -Create a mesh-shading pipeline with the same color, depth, culling, and blend configuration used by the spinning cube: - -```csharp -pipeline = App.Context.CreateMeshShadingPipeline(new() -{ - TaskShader = taskShader, - MeshShader = meshShader, - FragmentShader = fragmentShader, - PrimitiveTopology = PrimitiveTopology.TriangleList, - AttachmentFormats = new() - { - ColorFormats = [App.ColorFormat], - DepthStencilFormat = PixelFormat.D32FloatS8UInt, - SampleCount = SampleCount.Count1 - }, - RenderState = new() - { - Rasterizer = RasterizerState.CullBack(), - DepthStencil = DepthStencilState.DepthReadWrite(), - Blend = BlendState.Opaque() - } -}); -``` - -There is no `InputLayouts` field because fixed vertex fetch is not part of this pipeline. `TaskShader` is optional at the API level, but this workload uses it to generate mesh work dynamically. - -## Map instance IDs - -A linear ID maps into the $10 \times 10 \times 10$ grid: - -```slang -void DecomposeInstanceID(uint id, out uint x, out uint y, out uint z) -{ - x = id % GridSize; - y = (id / GridSize) % GridSize; - z = id / (GridSize * GridSize); -} -``` - -Helper functions convert those coordinates into world positions and colors. This arithmetic controls sample placement; it does not alter the task or mesh pipeline contract. - -## Cull and compact in the task shader - -The task stage declares 32 threads and two groupshared values: - -```slang -groupshared Payload s_payload; -groupshared uint s_visibleCount; - -[shader("task")] -[numthreads(ASGroupSize, 1, 1)] -void ASMain(uint groupID: SV_GroupID, uint groupThreadID: SV_GroupThreadID) -``` - -Each thread derives one candidate instance and tests its bounding sphere against all six frustum planes: - -```slang -uint instanceIndex = groupID * ASGroupSize + groupThreadID; - -bool visible = false; -if (instanceIndex < GridSize * GridSize * GridSize) -{ - float3 worldPos = InstancePosition(instanceIndex); - visible = !IsFrustumCulled(worldPos, BoundingSphereRadius); -} -``` - -Thread zero resets the shared counter, then all threads synchronize: - -```slang -if (groupThreadID == 0) -{ - s_visibleCount = 0; -} - -GroupMemoryBarrierWithGroupSync(); -``` - -Visible threads reserve unique payload slots with an atomic increment: - -```slang -if (visible) -{ - uint offset; - InterlockedAdd(s_visibleCount, 1, offset); - s_payload.InstanceIndices[offset] = instanceIndex; -} - -GroupMemoryBarrierWithGroupSync(); - -DispatchMesh(s_visibleCount, 1, 1, s_payload); -``` - -The second barrier ensures all payload writes are visible before the task group launches mesh work. A task group dispatches between zero and 32 mesh groups, one for each compacted instance ID. - -## Emit geometry in the mesh shader - -The mesh shader receives the payload, selects one instance, and declares its output capacity: - -```slang -[shader("mesh")] -[numthreads(120, 1, 1)] -[outputtopology("triangle")] -void MSMain(uint groupID: SV_GroupID, uint groupThreadID: SV_GroupThreadID, in payload Payload meshPayload, OutputVertices outVertices, OutputIndices outIndices) -{ - uint instanceIndex = meshPayload.InstanceIndices[groupID]; - float3 instancePos = InstancePosition(instanceIndex); - float3 color = InstanceColor(instanceIndex); - - SetMeshOutputCounts(SphereVertexCount, SphereTriangleCount); -``` - -The group has 120 threads because the source sphere contains 120 triangles. Threads zero through 61 also transform and emit the 62 vertices: - -```slang -if (groupThreadID < SphereVertexCount) -{ - Vertex v = constants.Vertices[groupThreadID]; - float3 worldPos = v.Position + instancePos; - - VertexOutput output; - output.Position = mul(float4(worldPos, 1.0), constants.ViewProjection); - output.WorldNormal = v.Normal; - output.Color = color; - - outVertices[groupThreadID] = output; -} - -if (groupThreadID < SphereTriangleCount) -{ - outIndices[groupThreadID] = constants.Triangles[groupThreadID].Indices; -} -``` - -`SetMeshOutputCounts` establishes the valid output ranges before writes occur. The fragment shader receives the emitted normal and color, then applies a compact ambient-plus-diffuse lighting calculation. - -## Update frame data - -Each update moves the camera, creates the view-projection matrix, extracts frustum planes, and supplies the two storage handles: - -```csharp -Constants constants = new() -{ - ViewProjection = viewProjection, - FrustumPlanes = new(viewProjection), - LightDirection = -Vector3.Normalize(cameraPosition), - Vertices = vertexBuffer.StorageReadOnlyHandle, - Triangles = triangleBuffer.StorageReadOnlyHandle -}; -``` - -The same matrix controls both emitted vertex positions and the planes used for culling, so visibility and rasterization share one camera definition. - -## Record the mesh dispatch - -Create the depth attachment on first use and transition it from `Undefined` to `DepthStencilAttachment`. Begin a color/depth render pass, bind the pipeline and constants, dispatch the task groups, and end the pass: - -```csharp -if (depthTexture is null) -{ - depthTexture = App.Context.CreateTexture(TextureDesc.DepthStencilAttachment(PixelFormat.D32FloatS8UInt, App.Width, App.Height, SampleCount.Count1)); - - commandBuffer.Transition(depthTexture, default, TextureLayout.Undefined, TextureLayout.DepthStencilAttachment); -} - -commandBuffer.BeginRenderPass([ColorAttachment.Clear(drawable, new(0.05f, 0.05f, 0.08f, 1.0f))], DepthStencilAttachment.Clear(depthTexture, 1.0f, 0)); - -commandBuffer.SetPipeline(pipeline); -commandBuffer.SetConstantBuffer(constantBuffer, 0); - -commandBuffer.DispatchMesh(32, 1, 1); - -commandBuffer.EndRenderPass(); -``` - -There are 1,000 candidate instances and 32 task threads per group: - -$$ -\left\lceil \frac{1000}{32} \right\rceil = 32 -$$ - -The bounds check discards candidate IDs at or above 1,000 in the final task group. Frustum testing then determines how many mesh groups each task group launches. - -## Resize and lifetime - -Only the depth attachment depends on framebuffer dimensions. Dispose it during `Resize` and let the next frame create a replacement. The source mesh, pipeline, and constant-buffer allocation remain valid. - -Release the optional depth texture, then the pipeline and its buffers: - -```csharp -depthTexture?.Dispose(); - -pipeline.Dispose(); -constantBuffer.Dispose(); -triangleBuffer.Dispose(); -vertexBuffer.Dispose(); -``` - -## Inspect the result - -Run the host and select **Mesh Shading** on a supported device. Confirm that: - -- the camera moves around a colored sphere grid; -- visible spheres remain complete as they approach the viewport edges; -- resize preserves depth behavior and camera proportions; -- validation reports no structured-stride, payload, output-count, or attachment errors. - -Missing spheres inside the view often indicate incorrect frustum-plane orientation or a missing groupshared barrier. Corrupted geometry points to a C#/Slang stride mismatch or output counts that disagree with the source mesh. A rejected pipeline usually indicates missing mesh-shading capability or mismatched shader stages. - -## Explore further - -1. Replace `IsFrustumCulled` with `false` and compare the number of generated mesh groups. -2. Visualize visibility by assigning a constant color per task group. -3. Change `InstanceSpacing` without modifying the source sphere buffers. -4. Add a mesh entry point with no payload parameter that selects instance zero, create a pipeline with `TaskShader = null`, and dispatch one mesh group to isolate geometry emission. -5. Replace the UV sphere with another mesh while keeping the vertex and triangle contracts unchanged. - -## Complete source - -- [MeshShadingRenderer.cs](https://github.com/qian-o/ZenithTutorials/blob/master/ZenithTutorials/Renderers/MeshShadingRenderer.cs) -- [MeshShading.slang](https://github.com/qian-o/ZenithTutorials/blob/master/ZenithTutorials/Assets/Shaders/MeshShading.slang) - -This completes the guide set. Use the [Zenith.NET documentation](../../docs/index.md) and [API reference](../../api/index.md) to inspect the underlying resource and command types in more detail. diff --git a/documents/tutorials/guides/ray-tracing.md b/documents/tutorials/guides/ray-tracing.md deleted file mode 100644 index 73d43a2a..00000000 --- a/documents/tutorials/guides/ray-tracing.md +++ /dev/null @@ -1,441 +0,0 @@ -# Ray Tracing - -Ray Tracing reuses the compute-output flow from Compute Shader, but each thread now traces a camera ray through an acceleration structure. The scene contains a triangle floor and three procedural spheres represented by axis-aligned bounding boxes. - -This guide explains the Zenith.NET acceleration structures, resource handles, inline ray-query interface, output texture, and synchronization. The complete shader also implements soft shadows, rough reflections, checkerboard filtering, and tone mapping; those supporting effects are summarized rather than derived line by line. - -## Result - -![A ray-traced floor and procedural spheres rendered with Zenith.NET](https://raw.githubusercontent.com/qian-o/ZenithTutorials/master/ZenithTutorials/Assets/Screenshots/ray-tracing.png) - -The camera orbits a checkerboard floor and three colored spheres. Primary rays determine the visible surface, while additional queries produce shadows and reflections. - -> [!IMPORTANT] -> Inline ray tracing is optional. Check `App.Context.Capabilities.RayTracingSupported` before creating any acceleration-structure resources. - -## Frame overview - -Acceleration structures are built once during renderer construction. Every frame updates the camera, regenerates the output texture, and presents it: - -```mermaid -flowchart LR - A[Update camera constants] --> B[Output to Storage] - B --> C[Bind ray-query compute pipeline] - C --> D[Dispatch one thread per pixel] - D --> E[Output to Sampled] - E --> F[Present texture] -``` - -The output is recreated after a framebuffer resize, but the scene geometry and acceleration structures remain valid. - -## Scene structure - -The acceleration structures form a two-level hierarchy: - -```mermaid -flowchart TD - A[TLAS] --> B[Floor instance] - A --> C[Sphere instance] - B --> D[Triangle BLAS] - C --> E[AABB BLAS] - D --> F[Floor vertex and index buffers] - E --> G[AABB buffer] - H[Sphere structured buffer] --> I[Inline sphere-intersection logic in CSMain] -``` - -- A bottom-level acceleration structure, or **BLAS**, describes geometry. -- A top-level acceleration structure, or **TLAS**, instances one or more BLAS objects into the traced scene. -- Triangle geometry can be intersected directly by traversal hardware. -- An AABB narrows traversal to a candidate region; the shader must test and commit the exact procedural intersection. - -The sphere structured buffer is not part of the AABB geometry description. The shader reads it separately to recover each candidate's center, radius, and color. - -## Resource map - -| Resource | Usage | Role | -| --- | --- | --- | -| Floor vertex buffer | `StorageReadOnly` | Triangle BLAS positions | -| Floor index buffer | `StorageReadOnly` | Triangle BLAS indices | -| AABB buffer | `StorageReadOnly` | Procedural BLAS bounds | -| Sphere buffer | `StorageReadOnly` | Exact intersection and material data | -| Floor BLAS | Acceleration structure | Triangle geometry | -| Sphere BLAS | Acceleration structure | Procedural AABB geometry | -| TLAS | Acceleration structure | Scene instances supplied to ray queries | -| Constant buffer | `Constant` | Camera and three resource handles | -| Output texture | `Storage` and `Sampled` | Compute output and presenter input | -| Compute pipeline | `CSMain` | Primary and secondary inline queries | - -Build-input buffers must remain alive until the BLAS build or update submission completes. The BLAS objects themselves must remain alive for as long as a TLAS that instances them is in use. The sphere buffer has an additional lifetime requirement because the shader reads it during every frame. - -## Check device support - -Fail before allocating workload resources when the selected device does not expose ray tracing: - -```csharp -if (!App.Context.Capabilities.RayTracingSupported) -{ - throw new PlatformNotSupportedException("Ray Tracing is not supported by the selected device."); -} -``` - -Check the capability before creating the shaders and acceleration structures required by this workload. - -## Create scene geometry - -The floor uses four positions and six indices. Three `Sphere` values provide procedural geometry and shading data. Convert each sphere into an AABB: - -```csharp -Aabb[] aabbs = new Aabb[spheres.Length]; -for (int index = 0; index < spheres.Length; index++) -{ - aabbs[index] = new(spheres[index].Center - new Vector3(spheres[index].Radius), spheres[index].Center + new Vector3(spheres[index].Radius)); -} -``` - -Upload all four arrays: - -```csharp -floorVertexBuffer = App.LoadBuffer(floorVertices, BufferUsages.StorageReadOnly); -floorIndexBuffer = App.LoadBuffer(floorIndices, BufferUsages.StorageReadOnly); -aabbBuffer = App.LoadBuffer(aabbs, BufferUsages.StorageReadOnly); -sphereBuffer = App.LoadBuffer(spheres, BufferUsages.StorageReadOnly); -constantBuffer = App.LoadBuffer([new Constants()], BufferUsages.Constant); -``` - -These buffers are read during acceleration-structure construction or shader execution. They are not vertex and index bindings in a graphics render pass. - -## Create the compute pipeline - -Load the `CSMain` entry point and create the compute pipeline used for every inline ray-query dispatch: - -```csharp -using Shader computeShader = App.LoadShader("RayTracing.slang", "CSMain"); - -rayTracingPipeline = App.Context.CreateComputePipeline(new() { ComputeShader = computeShader }); -``` - -The acceleration structures and descriptor handles become inputs to this pipeline; no separate ray-tracing pipeline or intersection-shader stage is created. - -## Build the bottom-level structures - -Record acceleration-structure construction on a compute command buffer: - -```csharp -CommandBuffer commandBuffer = App.Context.ComputeQueue.CommandBuffer(); -``` - -The sample submits this one-time build and waits for it to complete before rendering begins. - -Describe the indexed triangle geometry for the floor: - -```csharp -floorBlas = commandBuffer.BuildAccelerationStructure(new BottomLevelAccelerationStructureDesc() -{ - Geometries = - [ - RayTracingGeometry.Triangles(new() - { - VertexBuffer = floorVertexBuffer, - VertexFormat = PixelFormat.R32G32B32Float, - VertexCount = (uint)floorVertices.Length, - VertexStrideInBytes = (uint)sizeof(Vector3), - IndexBuffer = floorIndexBuffer, - IndexFormat = IndexFormat.UInt32, - IndexCount = (uint)floorIndices.Length, - Transform = Matrix4x4.Identity - }, true) - ], - BuildFlags = AccelerationStructureBuildFlags.PreferFastTrace -}); -``` - -The vertex format and stride tell the builder how to read each `Vector3`. The final `true` marks the geometry opaque, allowing traversal to accept triangle hits without an any-hit stage. - -The procedural BLAS instead reads an array of AABBs: - -```csharp -sphereBlas = commandBuffer.BuildAccelerationStructure(new BottomLevelAccelerationStructureDesc() -{ - Geometries = - [ - RayTracingGeometry.Aabbs(new() - { - Buffer = aabbBuffer, - Count = (uint)spheres.Length, - StrideInBytes = aabbBuffer.Desc.StrideInBytes - }, true) - ], - BuildFlags = AccelerationStructureBuildFlags.PreferFastTrace -}); -``` - -The AABBs accelerate traversal, but they do not turn boxes into visible surfaces. `CSMain` later performs the exact sphere intersection for each procedural candidate. - -## Build the top-level scene - -Create one identity-transform instance for each BLAS: - -```csharp -tlas = commandBuffer.BuildAccelerationStructure(new TopLevelAccelerationStructureDesc() -{ - Instances = - [ - new() - { - AccelerationStructure = floorBlas, - InstanceId = 0, - VisibilityMask = 0xFF, - Transform = Matrix4x4.Identity - }, - new() - { - AccelerationStructure = sphereBlas, - InstanceId = 1, - VisibilityMask = 0xFF, - Transform = Matrix4x4.Identity - } - ], - BuildFlags = AccelerationStructureBuildFlags.PreferFastTrace -}); - -commandBuffer.Submit().Wait(); -``` - -The CPU wait ensures both BLAS objects and the TLAS are complete before construction returns. The instance IDs distinguish scene entries; procedural primitive indices still identify individual AABBs inside the sphere BLAS. - -## Data contract - -Shared C#/Slang layout requires care around three-component vectors. The CPU sphere packs center and radius into the first 16 bytes, followed by color at byte 16: - -```csharp -[StructLayout(LayoutKind.Explicit, Size = 32)] -file struct Sphere -{ - [FieldOffset(0)] - public Vector3 Center; - - [FieldOffset(12)] - public float Radius; - - [FieldOffset(16)] - public Vector3 Color; -} -``` - -Slang uses two `float4` backing fields and exposes semantic properties: - -```slang -struct Sphere -{ - private float4 CenterAndRadius; - - private float4 ColorAndPadding; - - property float3 Center - { - get { - return CenterAndRadius.xyz; - } - } - - property float Radius - { - get { - return CenterAndRadius.w; - } - } - - property float3 Color - { - get { - return ColorAndPadding.xyz; - } - } -}; -``` - -This explicit storage keeps the structured-buffer stride at 32 bytes across the supported graphics APIs. - -The frame constants use the same technique for camera position, followed by three handles: - -| Offset | C# | Slang | -| ---: | --- | --- | -| 0 | `Vector3 Position` | `PositionAndPadding.xyz` | -| 16 | `tlas.Handle` | `RaytracingAccelerationStructure Scene` | -| 24 | `sphereBuffer.StorageReadOnlyHandle` | `StructuredBuffer Spheres` | -| 32 | `outputTexture.StorageHandle` | `RWTexture2D OutputTexture` | - -## Inline ray-query interface - -Each compute thread reconstructs one camera ray and begins traversal through the TLAS: - -```slang -RayDesc ray; -ray.Origin = cameraPos; -ray.Direction = rayDir; -ray.TMin = RayEpsilon; -ray.TMax = 1000.0; - -float3 sphereHitNormal = float3(0.0); -float3 sphereHitColor = float3(0.0); - -RayQuery query; -query.TraceRayInline(constants.Scene, RAY_FLAG_NONE, 0xFF, ray); -``` - -The two temporary values preserve the normal and material color produced by a procedural sphere candidate after that candidate is committed. - -Triangle intersections can become committed hits automatically. Procedural AABBs are reported as candidates and require an exact test: - -```slang -while (query.Proceed()) -{ - if (query.CandidateType() == CANDIDATE_PROCEDURAL_PRIMITIVE) - { - uint sphereIndex = query.CandidatePrimitiveIndex(); - Sphere sphere = constants.Spheres[sphereIndex]; - - float3 ro = query.CandidateObjectRayOrigin(); - float3 rd = query.CandidateObjectRayDirection(); - - float t = IntersectSphere(ro, rd, sphere); - - if (t >= query.RayTMin() && t <= query.CommittedRayT()) - { - float3 hitPoint = ro + rd * t; - - sphereHitNormal = normalize(hitPoint - sphere.Center); - sphereHitColor = sphere.Color; - - query.CommitProceduralPrimitiveHit(t); - } - } -} -``` - -`CandidatePrimitiveIndex` maps the AABB candidate back to its sphere record. The shader computes a positive intersection distance and commits it only when it lies inside the query's valid interval. - -After traversal, committed status selects the visible surface: - -```slang -if (query.CommittedStatus() == COMMITTED_TRIANGLE_HIT) -{ - float3 hitPoint = ray.Origin + ray.Direction * query.CommittedRayT(); - color = ShadeFloor(hitPoint, rayDir, cameraPos); -} -else if (query.CommittedStatus() == COMMITTED_PROCEDURAL_PRIMITIVE_HIT) -{ - float3 hitPoint = ray.Origin + ray.Direction * query.CommittedRayT(); - color = ShadePrimarySphere(hitPoint, rayDir, cameraPos, sphereHitNormal, sphereHitColor); -} -else -{ - color = SampleSky(rayDir); -} -``` - -## Supporting shading flow - -The remaining shader functions improve the sample image but do not change the Zenith.NET resource interface: - -```mermaid -flowchart TD - A[CSMain primary query] --> B[Shade floor] - A --> C[Shade sphere] - A --> D[Sample sky] - B --> E[Shadow queries] - B --> F[Reflection query] - C --> E - C --> G[Rough reflection queries] - B --> H[ACES tone mapping] - C --> H - D --> H -``` - -Shadow rays reuse the TLAS with `RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH`. Reflection rays use the same procedural-candidate loop as the primary query. Multiple jittered directions soften shadows and reflections. Finally, `ACESFilm` maps the accumulated HDR color into the output range. - -You can replace these helpers with simpler colors while preserving the acceleration structures, descriptors, pipeline, dispatch, and texture transitions described by this guide. - -## Create and update the output - -Create an `R32G32B32A32Float` texture with `Sampled | Storage` usage when the renderer first sees a valid framebuffer size. A new texture is initially established as sampled because every subsequent frame follows the same repeating cycle: - -```text -Sampled -> Storage -> compute writes -> Sampled -> presenter reads -``` - -Update the camera and resource handles before dispatch: - -```csharp -Constants constants = new() -{ - Position = new(12.0f * MathF.Sin(totalTime * 0.3f), 4.0f + MathF.Sin(totalTime * 0.2f), -12.0f * MathF.Cos(totalTime * 0.3f)), - Scene = tlas.Handle, - Spheres = sphereBuffer.StorageReadOnlyHandle, - OutputTexture = outputTexture.StorageHandle -}; -``` - -Then record the state changes and dispatch: - -```csharp -commandBuffer.Transition(outputTexture, default, TextureLayout.Sampled, TextureLayout.Storage); - -commandBuffer.SetPipeline(rayTracingPipeline); -commandBuffer.SetConstantBuffer(constantBuffer, 0); -commandBuffer.Dispatch((App.Width + ThreadGroupSize - 1) / ThreadGroupSize, (App.Height + ThreadGroupSize - 1) / ThreadGroupSize, 1); - -commandBuffer.Transition(outputTexture, default, TextureLayout.Storage, TextureLayout.Sampled); - -App.PresentTexture(commandBuffer, drawable, outputTexture, true); -``` - -Unlike the static grayscale image, this workload dispatches every frame because the camera moves. Passing `true` to the presenter fits the output to the framebuffer. - -## Resize and lifetime - -Resize disposes only the framebuffer-sized output texture. The next frame recreates it and uploads its new storage handle. - -Dispose resources from users to dependencies: - -```csharp -outputTexture?.Dispose(); - -rayTracingPipeline.Dispose(); -constantBuffer.Dispose(); -tlas.Dispose(); -sphereBlas.Dispose(); -floorBlas.Dispose(); -sphereBuffer.Dispose(); -aabbBuffer.Dispose(); -floorIndexBuffer.Dispose(); -floorVertexBuffer.Dispose(); -``` - -The TLAS is released before the BLAS objects it instances. The sphere buffer remains live because ray-query shading reads it every frame. - -## Inspect the result - -Run the host and select **Ray Tracing** on a supported device. Confirm that: - -- the floor, three spheres, sky, shadows, and reflections are visible; -- the camera orbits continuously; -- resize recreates an output that fills the new framebuffer; -- validation reports no acceleration-structure lifetime, descriptor, or texture-layout errors. - -A sky-only image often indicates a missing TLAS handle or visibility-mask mismatch. Box-shaped procedural hits indicate that AABBs are being treated as bounds without committing the exact sphere intersection. A stale or blank image usually points to the output handle or `Sampled`/`Storage` transition sequence. - -## Explore further - -1. Return a constant color for each committed status to inspect traversal without the supporting shading functions. -2. Set `ShadowSamples` and `ReflectionSamples` to `1` and compare cost and image quality. -3. Disable reflections while leaving primary and shadow queries unchanged. -4. Move one TLAS instance with its transform instead of changing the source geometry. -5. Change a sphere radius and update both its structured-buffer record and AABB. - -## Complete source - -- [RayTracingRenderer.cs](https://github.com/qian-o/ZenithTutorials/blob/master/ZenithTutorials/Renderers/RayTracingRenderer.cs) -- [RayTracing.slang](https://github.com/qian-o/ZenithTutorials/blob/master/ZenithTutorials/Assets/Shaders/RayTracing.slang) - -Continue with [Mesh Shading](mesh-shading.md) to explore another optional workload that replaces fixed vertex and index fetch with programmable geometry emission. diff --git a/documents/tutorials/guides/spinning-cube.md b/documents/tutorials/guides/spinning-cube.md deleted file mode 100644 index a9c41c9e..00000000 --- a/documents/tutorials/guides/spinning-cube.md +++ /dev/null @@ -1,265 +0,0 @@ -# Spinning Cube - -Spinning Cube extends the first graphics workload into three dimensions. It reuses vertex input and a graphics pipeline, then adds indexed geometry, model-view-projection constants, back-face culling, a depth attachment, animation, and size-dependent resource handling. - -The guide focuses on the Zenith.NET objects and their lifetime. Matrix construction uses `System.Numerics`; a full derivation of perspective projection is outside the workload boundary. - -## Result - -![A rotating depth-tested cube rendered with Zenith.NET](https://raw.githubusercontent.com/qian-o/ZenithTutorials/master/ZenithTutorials/Assets/Screenshots/spinning-cube.png) - -The cube rotates around two axes. Back faces are culled, and the depth attachment ensures that nearer fragments hide farther surfaces. - -## Frame overview - -Initialization uploads eight shared vertices and 36 indices, creates a constant buffer, and builds a depth-enabled pipeline. Per frame: - -```mermaid -flowchart LR - A[Update MVP constants] --> B{Depth texture exists?} - B -- No --> C[Create and transition depth texture] - B -- Yes --> D[Begin color and depth render pass] - C --> D - D --> E[Bind pipeline and buffers] - E --> F[DrawIndexed 36] - F --> G[End render pass] -``` - -On resize, the renderer disposes only the depth texture. The next frame recreates it with the new framebuffer dimensions. - -## Resource map - -| Resource | Usage | Lifetime | -| --- | --- | --- | -| Vertex buffer | Eight cube positions and colors | Renderer | -| Index buffer | Twelve triangles sharing those vertices | Renderer | -| Constant buffer | Model, view, and projection matrices | Renderer; updated each frame | -| Graphics pipeline | Depth-tested indexed drawing | Renderer | -| Depth texture | `D32FloatS8UInt` attachment | Recreated after resize | -| Swap-chain drawable | Color attachment | Host-owned | - -The depth format appears in both the pipeline attachment declaration and the texture description. Those values must agree. - -## Geometry and indexed drawing - -Eight vertices describe the unique corners of the cube. The index buffer selects them to build six faces, two triangles per face: - -```csharp -uint[] indices = -[ - 0, 1, 2, 0, 2, 3, - 5, 4, 7, 5, 7, 6, - 4, 0, 3, 4, 3, 7, - 1, 5, 6, 1, 6, 2, - 3, 2, 6, 3, 6, 7, - 4, 5, 1, 4, 1, 0 -]; - -vertexBuffer = App.LoadBuffer(vertices, BufferUsages.Vertex); -indexBuffer = App.LoadBuffer(indices, BufferUsages.Index); -``` - -Using indices avoids duplicating a complete position-and-color record for every triangle corner. The element type is `uint`, so the render method binds it as `IndexFormat.UInt32`. - -## Data contract - -The Slang constant buffer contains three consecutive matrices: - -```slang -struct Constants -{ - float4x4 Model; - - float4x4 View; - - float4x4 Projection; -}; - -ConstantBuffer constants; -``` - -The C# structure fixes each 64-byte matrix at the corresponding offset: - -```csharp -[StructLayout(LayoutKind.Explicit, Size = 192)] -file struct Constants -{ - [FieldOffset(0)] - public Matrix4x4 Model; - - [FieldOffset(64)] - public Matrix4x4 View; - - [FieldOffset(128)] - public Matrix4x4 Projection; -} -``` - -| Offset | C# | Slang | Size | -| ---: | --- | --- | ---: | -| 0 | `Matrix4x4 Model` | `float4x4 Model` | 64 bytes | -| 64 | `Matrix4x4 View` | `float4x4 View` | 64 bytes | -| 128 | `Matrix4x4 Projection` | `float4x4 Projection` | 64 bytes | - -Explicit offsets keep the shared binary contract visible. The total structure size is 192 bytes. - -## Transform vertices - -The vertex shader composes the three matrices and transforms each position: - -```slang -[shader("vertex")] -FSInput VSMain(VSInput input) -{ - float4x4 modelView = mul(constants.Model, constants.View); - float4x4 mvp = mul(modelView, constants.Projection); - - FSInput output; - output.Position = mul(float4(input.Position, 1.0), mvp); - output.Color = input.Color; - - return output; -} -``` - -`System.Numerics.Matrix4x4` and this shader use the same row-vector order: model, then view, then projection. The fragment shader simply returns the interpolated vertex color. - -## Enable depth and culling - -The graphics pipeline adds a depth format and enables both back-face culling and depth read/write: - -```csharp -pipeline = App.Context.CreateGraphicsPipeline(new() -{ - VertexShader = vertexShader, - FragmentShader = fragmentShader, - InputLayouts = [inputLayout], - PrimitiveTopology = PrimitiveTopology.TriangleList, - AttachmentFormats = new() - { - ColorFormats = [App.ColorFormat], - DepthStencilFormat = PixelFormat.D32FloatS8UInt, - SampleCount = SampleCount.Count1 - }, - RenderState = new() - { - Rasterizer = RasterizerState.CullBack(), - DepthStencil = DepthStencilState.DepthReadWrite(), - Blend = BlendState.Opaque() - } -}); -``` - -Back-face culling removes triangles whose winding faces away from the camera. Depth testing compares overlapping fragments, while depth writes preserve the nearest accepted value for later triangles. - -## Update transformation constants - -`Update` advances a frame-rate-independent angle and constructs the three matrices: - -```csharp -rotationAngle += (float)deltaTime; - -Constants constants = new() -{ - Model = Matrix4x4.CreateRotationY(rotationAngle) * Matrix4x4.CreateRotationX(rotationAngle * 0.5f), - View = Matrix4x4.CreateLookAt(new(0.0f, 0.0f, 3.0f), Vector3.Zero, Vector3.UnitY), - Projection = Matrix4x4.CreatePerspectiveFieldOfView(float.DegreesToRadians(45.0f), (float)App.Width / App.Height, 0.1f, 100.0f) -}; -``` - -The framebuffer aspect ratio keeps the projection proportional after a resize. Upload exactly one `Constants` value: - -```csharp -constantBuffer.Upload(0, new() -{ - Pointer = (nint)(&constants), - SizeInBytes = (uint)sizeof(Constants) -}); -``` - -The teaching host waits for each submitted frame, so overwriting this single constant buffer does not race a previous frame. A multi-frame application needs separate per-frame storage or equivalent synchronization. - -## Create the depth attachment - -The depth texture is created lazily after the window has a valid framebuffer size: - -```csharp -if (depthTexture is null) -{ - depthTexture = App.Context.CreateTexture(TextureDesc.DepthStencilAttachment(PixelFormat.D32FloatS8UInt, App.Width, App.Height, SampleCount.Count1)); - - commandBuffer.Transition(depthTexture, default, TextureLayout.Undefined, TextureLayout.DepthStencilAttachment); -} -``` - -The first transition establishes `DepthStencilAttachment` layout. The texture remains in that layout while reused by later frames. - -## Record the frame - -Begin a render pass with both color and depth attachments, bind all inputs, and issue an indexed draw: - -```csharp -commandBuffer.BeginRenderPass([ColorAttachment.Clear(drawable, new(0.04f, 0.055f, 0.075f, 1.0f))], DepthStencilAttachment.Clear(depthTexture, 1.0f, 0)); - -commandBuffer.SetPipeline(pipeline); -commandBuffer.SetVertexBuffer(vertexBuffer, 0, 0); -commandBuffer.SetIndexBuffer(indexBuffer, 0, IndexFormat.UInt32); -commandBuffer.SetConstantBuffer(constantBuffer, 0); - -commandBuffer.DrawIndexed(36, 1, 0, 0, 0); - -commandBuffer.EndRenderPass(); -``` - -Depth is cleared to `1.0` for each frame. `DrawIndexed` consumes all 36 indices for one instance, starting at index and vertex offsets zero. - -## Resize and lifetime - -The depth attachment dimensions must match the drawable. Dispose it on resize and recreate it during the next render: - -```csharp -public void Resize(uint width, uint height) -{ - depthTexture?.Dispose(); - depthTexture = null; -} -``` - -Release the optional depth texture first, then the pipeline and its input resources: - -```csharp -public void Dispose() -{ - depthTexture?.Dispose(); - - pipeline.Dispose(); - constantBuffer.Dispose(); - indexBuffer.Dispose(); - vertexBuffer.Dispose(); -} -``` - -## Inspect the result - -Run the host and select **Spinning Cube**. Confirm that: - -- the cube rotates smoothly and hidden surfaces do not bleed through; -- resizing changes the projection without stretching the cube; -- the depth texture is recreated after resize; -- the validation layer reports no attachment-format or layout errors. - -If faces disappear unexpectedly, inspect index winding and culling. If distant faces draw over near faces, confirm that the pipeline enables depth read/write and that a depth attachment is supplied to the render pass. - -## Explore further - -1. Replace `CullBack` with `CullNone` and compare the result. -2. Disable depth testing while leaving the depth attachment present. -3. Change the near and far projection planes and observe depth precision at different distances. -4. Give each face its own vertices and colors to see the tradeoff between shared indices and per-face attributes. - -## Complete source - -- [SpinningCubeRenderer.cs](https://github.com/qian-o/ZenithTutorials/blob/master/ZenithTutorials/Renderers/SpinningCubeRenderer.cs) -- [SpinningCube.slang](https://github.com/qian-o/ZenithTutorials/blob/master/ZenithTutorials/Assets/Shaders/SpinningCube.slang) - -Continue with [Indirect Drawing](indirect-drawing.md) to reuse this depth-tested cube for 25 instances driven by one indirect argument record, or branch to [Compute Shader](compute-shader.md) to produce an image without rasterized geometry. diff --git a/documents/tutorials/index.md b/documents/tutorials/index.md deleted file mode 100644 index 9d3b2af6..00000000 --- a/documents/tutorials/index.md +++ /dev/null @@ -1,36 +0,0 @@ -# Tutorials - -The Zenith.NET tutorials examine complete rendering workloads built with C# and the Slang shader language. Each guide focuses on the resources, pipelines, commands, data contracts, and lifetime rules that connect a workload to Zenith.NET. - -Begin with Project Setup and Application Host. The six guides then move from a first graphics pipeline to compute, indirect drawing, inline ray queries, and programmable geometry. - -> [!NOTE] -> The guides explain the Zenith.NET integration points in detail. Supporting graphics techniques such as sampling patterns, tone mapping, and procedural mesh generation are summarized when they are not essential to the API workflow. Their complete implementations remain available in the tutorial source. - -## Getting started - -- [Project Setup](getting-started/project-setup.md) creates the .NET 10 project and configures runtime assets. -- [Application Host](getting-started/application-host.md) follows the cross-platform window, swap chain, frame loop, and offscreen texture presenter. - -## Guides - -| Guide | Result | Focus | -| --- | --- | --- | -| [Hello Triangle](guides/hello-triangle.md) | A vertex-colored triangle | Vertex input, graphics pipeline, render pass, and draw command | -| [Spinning Cube](guides/spinning-cube.md) | A rotating depth-tested cube | Indexed geometry, constant buffers, transforms, depth, and resize | -| [Compute Shader](guides/compute-shader.md) | A grayscale image | Storage textures, descriptor handles, dispatch, and layout transitions | -| [Indirect Drawing](guides/indirect-drawing.md) | A grid of animated cubes | Structured instance data and indirect draw arguments | -| [Ray Tracing](guides/ray-tracing.md) | Procedural spheres above a floor | Acceleration structures, inline ray queries, and compute output | -| [Mesh Shading](guides/mesh-shading.md) | A culled sphere grid | Task and mesh shaders, payload compaction, and mesh dispatch | - -The complete, runnable implementations are maintained in the [ZenithTutorials repository](https://github.com/qian-o/ZenithTutorials). Code shown in these pages is static so it remains readable and searchable with the rest of the documentation; each guide links its complete renderer and shader at the end. - -## Suggested paths - -Complete [Hello Triangle](guides/hello-triangle.md) first. From there: - -- continue with [Spinning Cube](guides/spinning-cube.md) and [Indirect Drawing](guides/indirect-drawing.md) for the graphics path; -- continue with [Compute Shader](guides/compute-shader.md) and [Ray Tracing](guides/ray-tracing.md) for compute-produced images; -- read [Mesh Shading](guides/mesh-shading.md) after Spinning Cube when you are comfortable with graphics pipelines, depth attachments, and GPU thread groups. - -Ray tracing and mesh shading are optional device capabilities. Their guides show how to test support before creating workload-specific resources. diff --git a/documents/tutorials/toc.yml b/documents/tutorials/toc.yml deleted file mode 100644 index 0616191a..00000000 --- a/documents/tutorials/toc.yml +++ /dev/null @@ -1,24 +0,0 @@ -- name: Tutorials - href: index.md - -- name: Getting Started - items: - - name: Project Setup - href: getting-started/project-setup.md - - name: Application Host - href: getting-started/application-host.md - -- name: Guides - items: - - name: Hello Triangle - href: guides/hello-triangle.md - - name: Spinning Cube - href: guides/spinning-cube.md - - name: Compute Shader - href: guides/compute-shader.md - - name: Indirect Drawing - href: guides/indirect-drawing.md - - name: Ray Tracing - href: guides/ray-tracing.md - - name: Mesh Shading - href: guides/mesh-shading.md From d4eff60f991e5119f8fce60a7f8ab3b0687df52b Mon Sep 17 00:00:00 2001 From: qian-o <1324771795@qq.com> Date: Fri, 18 Sep 2026 00:16:34 +0800 Subject: [PATCH 09/35] Revise docs: update front matter, add placeholders, update TOC Updated index.md front matter for new titles and descriptions. Added placeholder comments to several topic Markdown files. Updated toc.yml to include "Learn" section and "First Triangle" page. --- documents/api/index.md | 2 +- documents/index.md | 2 +- documents/learn/concepts/execution-model.md | 2 +- documents/learn/concepts/platform-integration.md | 2 +- documents/learn/concepts/resource-management.md | 2 +- documents/learn/concepts/shader-data-and-binding.md | 2 +- documents/learn/concepts/synchronization.md | 2 +- documents/learn/first-triangle.md | 2 +- documents/learn/index.md | 2 +- documents/learn/samples.md | 2 +- documents/learn/toc.yml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/documents/api/index.md b/documents/api/index.md index d9e89e40..9cdfdaf8 100644 --- a/documents/api/index.md +++ b/documents/api/index.md @@ -1,4 +1,4 @@ ---- +--- title: API Reference description: Explore the types and members in Zenith.NET. --- diff --git a/documents/index.md b/documents/index.md index 89af3af4..d603e8b6 100644 --- a/documents/index.md +++ b/documents/index.md @@ -1,4 +1,4 @@ ---- +--- title: Modern RHI for .NET description: A consistent C# API for graphics and compute across DirectX, Metal, and Vulkan. _layout: landing diff --git a/documents/learn/concepts/execution-model.md b/documents/learn/concepts/execution-model.md index 41734934..db30cf23 100644 --- a/documents/learn/concepts/execution-model.md +++ b/documents/learn/concepts/execution-model.md @@ -1,3 +1,3 @@ -# Execution Model +# Execution Model diff --git a/documents/learn/concepts/platform-integration.md b/documents/learn/concepts/platform-integration.md index 36918a16..6c856635 100644 --- a/documents/learn/concepts/platform-integration.md +++ b/documents/learn/concepts/platform-integration.md @@ -1,3 +1,3 @@ -# Platform Integration +# Platform Integration diff --git a/documents/learn/concepts/resource-management.md b/documents/learn/concepts/resource-management.md index 5f2be7dd..a23091b6 100644 --- a/documents/learn/concepts/resource-management.md +++ b/documents/learn/concepts/resource-management.md @@ -1,3 +1,3 @@ -# Resource Management +# Resource Management diff --git a/documents/learn/concepts/shader-data-and-binding.md b/documents/learn/concepts/shader-data-and-binding.md index a9786f65..9baceea0 100644 --- a/documents/learn/concepts/shader-data-and-binding.md +++ b/documents/learn/concepts/shader-data-and-binding.md @@ -1,3 +1,3 @@ -# Shader Data and Binding +# Shader Data and Binding diff --git a/documents/learn/concepts/synchronization.md b/documents/learn/concepts/synchronization.md index ebdc42f1..15d0c693 100644 --- a/documents/learn/concepts/synchronization.md +++ b/documents/learn/concepts/synchronization.md @@ -1,3 +1,3 @@ -# Synchronization +# Synchronization diff --git a/documents/learn/first-triangle.md b/documents/learn/first-triangle.md index 14c768dc..eebf4733 100644 --- a/documents/learn/first-triangle.md +++ b/documents/learn/first-triangle.md @@ -1,3 +1,3 @@ -# First Triangle +# First Triangle diff --git a/documents/learn/index.md b/documents/learn/index.md index 7f05a91b..c4c8bc09 100644 --- a/documents/learn/index.md +++ b/documents/learn/index.md @@ -1,4 +1,4 @@ ---- +--- title: Learn description: Get started with Zenith.NET and explore its programming model. _pageKind: hub diff --git a/documents/learn/samples.md b/documents/learn/samples.md index 289397ea..ed622a09 100644 --- a/documents/learn/samples.md +++ b/documents/learn/samples.md @@ -1,3 +1,3 @@ -# Samples +# Samples diff --git a/documents/learn/toc.yml b/documents/learn/toc.yml index 90f9b0fe..1be99e25 100644 --- a/documents/learn/toc.yml +++ b/documents/learn/toc.yml @@ -1,4 +1,4 @@ -- name: Learn +- name: Learn href: index.md - name: First Triangle From f0766129cf4568f6f3cfac6c5510d4d95f6a9080 Mon Sep 17 00:00:00 2001 From: qian-o <1324771795@qq.com> Date: Sat, 19 Sep 2026 18:35:53 +0800 Subject: [PATCH 10/35] chore: update SVG logos for improved styling and consistency --- documents/images/Zenith.NET-Logo.png | Bin 6576 -> 7398 bytes documents/images/Zenith.NET-Logo.svg | 34 ++++++++++++++++++++++++--- documents/images/Zenith.NET.png | Bin 3037 -> 4008 bytes documents/images/Zenith.NET.svg | 34 ++++++++++++++++++++++++--- 4 files changed, 62 insertions(+), 6 deletions(-) diff --git a/documents/images/Zenith.NET-Logo.png b/documents/images/Zenith.NET-Logo.png index 9cff01b8b13bb97d21c8c1eb676f00adb3bc0a06..090eb8a70e4bbcdd97dfc5a4dd3a21664b41e1f8 100644 GIT binary patch literal 7398 zcmYj$2UJr{v~`r;L3;0qR8bI+CLKgNiWEVSBE3Us2?nJ}5u^x6=)H<`0vJ(1ksw_R zkWfOE5I_u_ckx^Q|6bNgR@U5^Gv~~ivuEEu31%kxbktnbAP|Vo&_Krm1iEwp{Ewz2 z2Yy#&BHVxm4R>vAGxw)YK_HIIsMozlm;E{VHKy-pJ)~2XXW(7UbRaxY zzIS3?7&1rH${i}IdKRzeNmV@4&vQfqD-@(IuA3~3O@GxuZ)-NP3ju>2=Cdg>RuSfm zb6hNmt*rEiEnuOl4hOTHu@Ql%or2$S2G^+t{-j^`k{n^^#*_?(DR$ShkE=9H*L)=_ z>r^pMA=7vubKr;%(&PBZj=gzrh+LPX->CIk7!`qQGn^|!>AK4oW<#^Tr3Icl3CmWm zWJT>p{XiL9g}B>FlgO7Rtq4icUZQj2d&(aaNkWv&pU(Bm+j6KFACo&f_C_$ybj(a; zxiN*qc~-rz*vI`)3V1hSIpF^8`4MGH-QP1;vX#w3zUJ-;Is2`?L2dNj{l}HGliZeV zf6B`)KboPdEajwpvZ!CBT{g{Y0A;*Lp4LE>)P+NH_F2X`0*Ye>4BWs-nl5$v-5^v*!XC<&bM? zq#cz}GF9?bN>yr58j+|T7+F=Vti3^a7vDz$rcSK`)kvV{BaAdgVG z#Z6tUyRq>`_t@X>xU*DIHl(e5l|wFp516Otx0$uKRsZ{SV`E2VLKT>MZ2qTy zcB)-gp7q2h-@FrYYQZ5o)KiovYHt+xwBRGR8eqB5!Y1m=1XIb~P0J%%f%QLPha$p3 zw5UMTF%y~SfMj*Qv0gGM2*k*EcxWjjb*;u$RUm?6pOyIBi;iA~MCMgfwZAO;y|)DB z2{T|ubxV8uD0g%BFDvuwB)UQNzD%rnN!K;~Z2WRqlIu?@i=7r_%`JgdepX)V>Lg;k zbR_jY6lyT}0(rVOt7z)-$34v3o76)JFhv*mYv9y_<*S;YGRX~vFp<(fOYXrD`dOKe zVsmLgphBa7Ku?H#^|SA;hz`4}2gW^x?UBr>*>~uG68&-QOG!;u#UD;ef7{v)_)u+Q z^P=IzW56n=sM+iHa?&O3>xHOdlI>Dg@Dl@E_-G;wt^z-9nV@W-v@sJ1X>TBAxc$%3w7$vEY zr8k59I4x`-_bn_qV{(CEAXb=9Na_zHtmq|Wd8M^~Fa6(m=zd+3$VWxf_` z3e>N^V|)={TIQQJ;oCA_J)uk>!*-0;pU2$u6>$IN_`Oi_3ra0cz6r)>KTFN59S(`}h=U*q1np;{D zcB}o#snu<0zw<#z6?j1)FFn@>c+QF;4y5Jy`-4p*NgYqmJW7}LDs`FBxBm3@tvNQ@ zsKRm}b93`p3OdigF&XEy(S%OjT9y0X^LowRsi8%Ff6`{qsQ2V6V34tsdHT3Tr|gx|ODD^w%$m#Jdu7Osd&(9=AcDpGgpsK(*s|{nxb46sEE&QAf>no?c|rP8Z!?M4_{Z^IVcwGq=FA+4RKt= z|6APKUYpq=!BcoRwH@q?+u!IrD&#(=i zZSI0JWu;|O=mBA&QCL4k^=Ve&pYQ#Oa~hSoXPcuX`o5)+vv)`Dg&iuNMs8t|F(gTM z$LG5vp!F6jdv#eO83Qd`8@mcf_3h^*6vdOMh_xR@K9@3H@?o|U|GF1LBWCXr`9+hN zlbKaVazey7u1sT;gay9t1+<}CqqMqu>zGYt?C>_1iSy_1%>=aTFx$;@$;P*#=P_`) zr_O}KDoZD9;S-C!?4bv~$njx~ml7@4jecZrdRP7mZS|Qu^34dX=^Pw?(7BU(Q|Qq^ z3U8NH8A7AQ*1jnr7TUv6S>os9CgE>C5>ANDrewS4)rDj9skXk(jd`&6eC(=Mo<^8npfE5iui*_ z{!^>{nhZ$-^*K|lUiKEoUcqlMpW>nEITMMU-2+DmibeDM!g*uo2-q5 zF@6Xht~Y)10_c$^<}$xbq`A}nr8Qat;)XbFF%CBRl|1O zel)q0k|T%0Vpe}HHh={V7}+BOJj&g^d>~YU(YjMuRsTOf<*o&+uAE`)!|E2M2VI6- zc(jVa4~OK15|y5@!rBtBhq-Qd2te{1bR_nTpsigdzY06iZWx!uO%6)Oh-be%e0Zf?Wgm*o;97s0F-@Z3o03J|g@Hygr=_LPcer zK{5>Iv5rczR&>+NlmPa4iykNw=VXoX`YC+-QVpK{o2^aQ4x9T%<4U?Y!US9}1*tfy ze$iao_^&OgsZ${NwdCZJ>&)L^6`QZ<%Mp|mUoBLP{Vzwg_~)sms|v52m)!0BAh`T2p2}ubG9!l0_BFm_~!d$ z4M|2n**>?RG!`#~llLMULLwum7VC=fB1`=VeN4jjxu>z_(fGk|icfUONW&x^r=*XltE~__ka^LY0-4v* z@C4taNvx83$e+8@Mrub0!fT#jf5^!vJ?^dh&|4xuK`sFst^XBzCoWNE;d3wD}xNb(+4%tXMgG)2dLurN_){*oNGjNO~;x#C4`rV^ay*nSaqMP zR6*K`Y~*yx)@M*%^`XhF#)Pv|P|r^)AXz#eviA^ctNw59*FOya!8FVr9icf>&3^2$vB(%2Ei1zQiE`Xu8s9qU< zSiy|2$@{3Gxm{ay?rPUYL+r)bxMLWlrAMegn0H$0Hy&F?4Wau*OKl`fdmM7xQYq6k zgFRyua&6X^_CxCbfPAJTyLm#(dSS$=&)c}${Fci2nj&%VZOrzmc-t3=fyl33FyFRY zpOmF(Z~&AdM1>{9M)yLbUqu}=#H(}KWDT)@pn>PrD$rM>`+RLQ5k+T{Lmhv~z`qmb zR|-Qz-uw^(caD}H`j1!d2NNEMQ^M^mPQ=@&dXk(KUtty02mNhQUtqn(4%$Df!$+sO z4agtRnVf$Z=@mD|t3H%`g%o=L*%$R}|}qwGNW8}l+~bQ?*)_4DS(H=GXrml$KXzqr6nw+iQ0r@NQ!s-eY?-16Qm=Sn3LMn z9f|2KWG&2k%&~0YILIyTC@uD-j{tbQKR>o!~ky5HmIaYO%VyZ5>_TX>zvk!nlK1%h*Q>?ep!F9S1mmVDM zHqsygs04V_$m3cECK)5$;4PhE{tGv?XW z@0hXW9=8#PwDc^_8v%-MuwnG|{k)@WgC;{~r^m9^hJ8=Tml=Q%D2xf;NcL4*Sn=YE z7krBlZ+e#<-M0N&j2IhBo~8f>8+@IUf)V}A=7_<$&~0z__tO{sHelBMUB4~A)`&7j zQqrhrWrgBKr__XU+qnD2o50(|KA7^=~{-!nJlXU#A> ze_cylwAq2E6+d7z+YT;gB0OGVwI34XW-(q)$T*cbCtUU9*z!E^Y9(geEg^z~I1m6E zOAo3eG_?zk*;#z@2S~nKbX>!c`ORTgzXWwAqFT2v*d`~;I^{G{AVv$o4u{-#aL9_X z;2YpofZnEqTN*4KvylNg)ao8DZ+$1#aG(EUFlNg;79=fsq)mCI;yIwNNeCbvxl+Ca zrAMO83I2|$9NV0Ho}CW~AGIxT>b_?&tLNPX-nMnDM|TIj!|R;ao2wfulYA z(W5yAtL4}F1?aN$l>A3@^EAQ8J^Cn*ymbPE$Pxpt3pzUYOF=C==^^*>y6)!MuDQX? zVH&+T^!clj-DC}Y#AAAZl*1Y-JGJB$6^-5;r$F(4ey93Sba0DaP&R>8LzeTh27EM&G8e7!k$x#oJHGx>I)u8Iqw->vGF=3!b{y)M(r~h)IeJ; za{3u^4`kYsB?fFJhHzRQc`F_b2Y|0QLJrGTFMTozh{Lu}IdmXVS#M(pZs&2iT}4Vx zw~JYknF3s|h_A<`8JpR>;`izbP!5|{zE+)n#&@a#J8x`EsCpo!Eq_)JyanJ_RGmgt z#(XaBn$PM!=y%VL%gJta@=qsu(H;7z&%e0r;p^ae>5(uRrSTok!i)9kuiecJePr#Qy;0*J1t zc1C=uku3Wbwcdnl&FXp%<9BKrr1J9^rFE&9-crqV=tu~ZZxqPHJks{nl{=S)ET7)_FUuJLPs{Fs*>cQOBcMGfx;|~M~`!=Cr=1Bj!L&J?P z+mN!%MLLJc*P*f#O(8G%!sfnOjLmpp_%=wKBOcb9Ke z1vqxQ=DS^0n3vi_u;52fFtM&`TW=7&uU!Vv~= zB|q%r>~$B_9YR0A82FDOyLgx@GG2B`^y~MpRCC8f>cEkpdG0M<*sqbK%yG zcA}r$6%{YKN8@!yhaDM4ld395MRcLc5q|*ylxFDUIi}-~@)$5>3&iJLosWPDX$;(%o{ku(LA$!HGosDRG?=c9d6dk2Gi?-;NE2e6vwfOY7|D0gshqN<=ScAh413T~X!TyOvwo+j1 z$n^-7EVa`lHxLgg0|;~{3yc2q`ku=^YhySCn>0j={cGSqNh|u46jK@J{OK8b>?oG} zVK;9aJwKaa_s!B3m27Y4=40Cb^s)H0gYfR$M0Qyl>Ke)4=r+s;_2}QK=iz*jCvyKJ zHZ(WlCWQSJb{B3wRss$p`)*R}*sCcbR5>Y`G=wR5SPbi^NBi$Po9^AvrV4uSg>TwnxJ zrG$CqLXL|bj!!bKT~MA0r@GpoDH8Q4{N{U?&0BI|8~5Qoe%&|}(#0r>kXgA70zJOD zxO5Y0B0OuipMerim8P~S+9Ov$w?Y>?^n~Yss$858|4D(bDcxqp)biG!&Rr9d?Nusu zI*8XwgQwwavZkL^wfVvsUL~UAxd0I@gf;TsC)$$S*G#*gZc@zWfSEm%04b5B4ShP) z82@%0L{T}v8<4MoA-BX-Z$rXDA$yxl36#&VO-TWr*~J$+^f1*cL%+X? z@!lOt%h8PxKbzb6c#a7#KwXsoiRw-|_7ODjjB7%EzcTR*XybEo8k3=a6*Q^6J4H7# z(LVT-{7*NaPWnYgtlJW;9C*l@nqB>7bU%MK)iNdrfv^YoW@X}sxriORNYYPQNEf!} z&w~Lwor_~e5sn=AAa7jN1I7vk*pP(Kx0b`*A=z_5kLy5r$SkPa=W?HOiulrXjK3q^ z&X(M=uIvCtS|#{(2pR51fF1T-=7br=Xl1x%N(KkpDJLERPjeUAw76_~S<@9OW+Qa_ zeHJn)|J^wp&=NPtV&#n@ew=v3Px2sLn3#Bp9&JAL{3WrM0ryF7y+kRrxV_yYH61uo zFeER6Mt0wQ6r`<_wv^@5Ku&0;gJzfK*!tMap{sMGu;rU+XJ&@-1VXP%nloOzn+t z2)LcUM1>88%?PW8TRwadq37&up*V4Itq?oCrqq#T_;GE8 zlCdCTKKZJ#8g5bs^?@Kh9g{YS_dpr_yLAGF{-4ivwR4J1DUo}D5*pSQ&4#)rI`vwQ GVgCb-3S@Tx literal 6576 zcmY*-2{_bW)c;fzvXvzvLXo|Qu?&h3vTxaj$dbvvjlG8KOZM!MUC3^%O<{^`iLs8c z4h?238M3`!{ht5-dEf8z%zS6=y=T4WoO|vkT2Duvj)t8E1Om}%Jbq*V0-f6je!rr+ z2z=wk0v&-Dwfkc;FA#|J_Sxs0hQTco2z1?6#RQs9okXUm&laG%g^P^9W;@>kboxt>#-5o-tHR|+f9Qm zZ$+Lg?L|8HUznH5vuWwOM$5fR*-y!99?sx--NVcy)BpT@l4V3s4~t`g+Bp#DZd`J5 z@=k0}v0u`!4EXti-gf1#)d{3t!_bc_Ra5rStW}adEL9TS_NFB~g%lZd8Ty1hvm}Yd zx-mLcS)IPwzIDHV-Bx#aG{Twd`leiBl3qJR5_Ll1bU$9 z5!nAX;KK6QB(jIG?O`Flu5|0Kf@)V6VCSXrYp_mwv!Anqxtv6^>-qU)!+Stw4H)NkVB>(=bVKAE(1%gZO})v zs5#QUc#-oU4z_qX9E11oxK`ME9t6_s*`Pl~^dwCRa`Q_0dw&yqpB@CatHvB^{jxkG zPR@gRUi9n#uJ)58v)(8e6Z6_k_!X zK<=_Z>$!d+Duh{wDtK$j#5*9KEp_r_xm!8<7uJz4t0%ZynWQ*DAWoXb-EM1IvhbC)+&V^4j6Q>`?SWp2;^-9#71m114`h~%K zC3S~Kr|+}fyv5De3^D<0oJ5W}*&#c56mbT*Q)t!Z zt1YE9yhYmsR=8J|b@GzDIeVd;Q&{kKxky)WKGAiqQvp+EH`VUHBP)bC5;qZc6k1ed z|Gk}Celp`S-DFk0hm`kSZ@C!_D?pPEvzQX2Pd08#&W5JiwWB-`csBTHn1)8)=xnul zhe^8<@xsWd_+`2->(cqwUqp&&ByHcO5{1~@JWb#i>D8sahRizv+wWjA(ymi}HG zGgt6?zx?CJBd}1L>_F-ZzS;d6$%U4Rii(hO&yKEIbF0q0@J`LxuHQD5BKpv3m5q1ZD{OI4rXJ_6SRU4fEH0HXcMVi}H$^?AndC zC@EN1I0zn%VbW09GP3(*{hlf9_4Uskcy zbyQ){9JJYfIK6PYzsP4`Cy(r#`;StnZJFKmr1>GKl?GZ=SILEl#QDTtiiEHxS>Io2 zSF&z~Y>JvYMj>}tA9DnTI(Of(5NLgk+c=jttwXnb*pg1JsIFE_LBp~y|202iMqn)S z8GcS2)bPNmum%V`99K}F=u~nz&QJ_4R`1FPp>UH$aj-xLP*zCjdzS!5_4P}-v$b7?G{@oewR&GOx}rnU zl`++i97l#=C6^4~e6Ax#)IyIut>Wi@a4W?iL7ZG6;#EcaWSRqi=GgL znwD{)K~iDB^fmF@AiH*wMBGib{Dbp466($Vl1L<_y$T8E@OB`fR_a|iA+plA`M zeHD`8r?CbmeqOTd#wN~)(m5sdt;{~y3gCwJ50s(y+4KuU?oc7^&3cESq%7{aXaqi6 zDH!Q|-`lt|yMm*ku76xcRPvARs;teHpY9UdDlw#B`(#Hq=(snYLwC{D?C-1z9lH1W z+Q|d(;^~w3Gj=Pge#bJhgZ+X~CCl88xaOCWo^r>B7j}u$_fyB{#Z2YMr*|`P0zZdD zit~B`^nTN!R7eTTN6Vt4Jr-_5$^3qUR&y0r>1%`2eF!{9Rh@D9RJ^}JDMWj3=P5!H zR?b5$X#CRy|Ltmf@?$6M^XSHC*Cwl+TX4BK+C2Bn&v@53GP~wx;c4Y|tAt z%Hig$F>lu$n<=m63LMhHSPLVg`bPL*w-u=oQ;%dTE$)ZL;xt}n6tA+u4xaT6B1(5) zNkub>=x0KazWh$8A-VZRGHhRm`2ny!d=#O?_mNq%#bRdkH{?Y6`U2nmJ*v6`Zxy6y zcv7)=|E(bWty2o`_50aa2};Ci)IvWqSIY0H7nL;7%#2S$Z;*qg+Y}0679?U@$U9|t zt~nP~Ug{}4{Zhbk<{-u*=2TF9GK{p^+@9RA!hh)oL z%4I7c+GqIB>>juSPUH->O!EP)^->eO~;1K6zva+MY?-Gaxb{)4J8A*@#=K-#I|d zFAd)fJ4QK$s-uSm%uvD@_s%+bY$Liq#<9eZb9kRCpJN7bDx*0YtiIer@E^L!LF6aX zQxNq~m$Zbto98w&q&Elc{+bA0uB3uy8iB1ATb!nueFnh2e>u5?q83rl)BCgo;4u_k z;pj!H0r4&QM5v@{f8dtqXCoRcEdi$+qgsp2UV-Ke!RDp*zF6A6$0@~cgRgA`(KKEP zd+PPzEbcr@SOkTVlukvMqBwE0bJm@W;TX}7@8=Jg8I7553kx}%MlndFR zFW>T$yMlLXokrxC5MU>R8yyahVtNnEuKu~F=%|JuPD7U=uA0gusj;!KuAc!Sknnstn$9e1{Lju9gvEBG@o(&%3zS{mV?iZ7jY8;-8swJq+0pl;LA#$-SkW5LKL^`n zrIxVV*RzgDv@@7JG8%9&>4n<`o1kyGjuU&}bL6WmK_A6V*zmH@cf+JWha8hIt*g+}THK=X9%hy7JBvzN22+CVpLQTOtP2z;|{T&CQWskzPot`aQV z>*%7f-QgD1cu`?WTR9fDrk0)gS-VoVJ*9d5CVW#v1J`QBJ@mx4o(j4c#%WEsd3M-I zP;TsAmn{CCD?l(q=KK)am+4i6$tu8N+{&iyg0N3aJvF?38a*EuyMi(#A7xTE;N)-1 z${q2+~PYUu;!O*$lTXe^y!nI zDJZ&bj~vkHFhTH--)`M~?u!y8N~*iK97SvK$=crojLw$WM3P@eh1=gdioVkHF5gBP z1IGsn#QJ@5xxq%}pG$~>X|wx8q?~aKzh*r;cSC-Nlfo$I(s)V*n3DV}vQT zCQOsvA)(EwbkTt`>k=nUItRHBnA&<6F1%* zf`G^OJi(eIbAhoD*hOSq_E^`W<%w2)5{{Jp6l{q7z-hIsZ$XmvWo$Pf&XrE6)`oF2 zug%B-3NO#Nh5-&7rD*62zWO=U|i{+;Z-gW{fh5~+wU!y+*AhYGZa<|tesc|+hgfl&NCc(&E; zks2C;{x%ET?1ZUK!Uv>(OSS8=bPQeI-BIhz+;NcYgA#PhH@HeUzuwbHB6x0!{8eXa z4;f>tO){hpLKmIg|M@4Pj`#5+h8QY~c-CviZI6P-eD z&5s#bLCh5taD_NG;QSG#=DJL0feDG}D7MvYY-et`#K08;c_5>`$=KeCOXFDAi$>p7 zocbvvKn;~e`vWJzv1?^Sz<$yQ!Ze{VDlqjdH#2a%pR%Q0()q~|5fR@uy>wFLDQdJy zeI5*tpT|j zW_)W3fw(qyp_R9XVMg4HBi5nmMw#ZvKDQ($(I{@s}|;e?Z?~Zsz9P`bezj`3k;;qqEAH0 zzD0$d?th_B_R^P&hhaleO%Yk-d!~YwgVo)wRiSz72SQp$YQi1Nmt`w?h|sdze&Jm9 zH*TkSzn&rsj9=AngcYa{|LMH-=I~+nk%;J57e+`A%&bc6Ue_-my<`@|nOTK1O)j`xOpA zmSogPDqPpaj5o8JU$W$S#`q+y0QZk91$ykcA(7D}u7!FGq8wYj^S{hzzu$+@UKPgkU10QjflvUlIo zx?yNSz7?5TV^p_;;`K+*fj&QjUs#U(vnsX{E*?l8|NL9vQ;M%Za;{HeO_eyCV)#Ft z>njtj=~|l0#u%pL%WoQsW>+Rx>r62Q6RgdF*gwq2^0H!kiO->k6~!EImfw}HeR+WA z6)t_8A%TYxsKft5n!diD*{Gj#Tv_Gi;Bv!$dX{3>gPoYT(+fE)tUg#9m0R)*Icfe+ zCq07ebM)YwR%*x9PXadt{d8Uj8k4cD0?2t7VJ}_r|D$gK#?S(5@VvX*>-F|s2ivjV zjY(F!ao=pvN!HAau6}pp{)6dSS{6ipe{uN*)0Rf}Gg&u!fP+$=*6$I%$+C~wD)~PS zuMxGj`)9~a015PHi{qT_PQlj3Qkh!9Dye)3S6+w`q@L+(k);0YtK=6%0I->g;C31| zErlo*|BkUddgeTLd{-p#0UfY$kp>0^o}B`Wa<)r(%TY!(p+k(=2W4Uc0&x0&5F?x4 z&HMT_jgwRdD9q0dagM})&}QkKry=*^G1Bi@+!Dv-t+n#Sy{Vn00l?{6u}-jHTP#O% z1Dqt~eW?%nC>}sK8F|>&{ps-~;L#`UkAg<{t5R^Vs9HZ@z0&({hEt{AM#nyNi$pE? zCJ67P)0ne(h&oFElco*Seov(x2kbrW?o;mR97dYQ)=(kf3FfNhdS&Vm9ogn z$nax#z6)fV!xmg<@DF8c)!JJt(CaM7KD)m37av9I9?G&al-}t3PJs9>$?R?0yS$)&qURSTr1f+J$QrtkKnBZQ94$f*7F7l4d)zxk<7oJmy zt6P#-u3NU6hcB{W#X(X)Uc7P@{c9V#s^j+lNU~Y!*E=9?ZpdGYX`n|U46#j4xzXSK zg;JJV;#xko{AgKkp+$<6_ncfO;u9L`0c~hq#|{TYwo`q)0QeSuem)b(2s zG_RxBFSW##wVQZk>Q5?c_+I*InO>$35dGiBCg6m6fVI + Zenith.NET - A white Z on a solid graphite tile with a fine inner edge, paired with a soft silver-white Zenith.NET wordmark for dark backgrounds. + A graphite Z icon with a fine top-lit edge reflection, paired with a silver-white Zenith.NET wordmark for dark backgrounds. diff --git a/documents/images/Zenith.NET.png b/documents/images/Zenith.NET.png index 8b8e72ebb9e7961c2177251051b08ae12395e779..daf4219b2de8a5c1e1dd5d90b1ebe7da9de65977 100644 GIT binary patch delta 3991 zcmV;I4`}e+7pNbQBYy!uX+uL$X=7sm02q~hkiSa;aTvxw*HxBS4LLLv93@Q!QA<;S zhE5UqBh;qz{86BG-SD(qS?kA`U8TXAqt|c)u4uwi?0q^P|xyycz9mk zmj{&RyipL{8Wf7Q6%P5ecp|B}UQqGU&md#EAt%%tH}kWx;s&h1wU3U_+RdHMi{^s;4@6i21NtLOSUO_3Gf>0dK#2CFlEIPNl^Br zpKI}nV+18e45lecW9OrEkT!+v&a-7do$7!5_`UthH_WouC=Ifvyw7t|ZTrS822tHG7!1a7 zaH9sBZqqSUNMMQtLXs!V8Nn$ z!|5D)Pxe`T)H!80As(zUq-?gP0FS4~d-fGatU0VF%$$$myR>`; za#&I_;%-@p?)7@__mowPcNDs}+j9$>WqXAJ2?IN1v3OPgW zkVAWJQ4?}nQdU{zEHCdNIpN)96=tWaY)Mv5QDbyme=@O#_a+8Q6w#R?7`g$-C31?~ zW@Q&N7P$s4DlIKHN#Yk@>>5;^VRtm4ThYNxFuFjFk!$3<*fsDS(cTE2(!s;~=N8pQ z#3VqYBB62N3<3ffW(CCn>tW4d_Yx+SC=7RXP@Hj@c#9@o*gUiO_*-qyp-6DQQhWGcmjsd&a zFJC^uH$h&3YbVavx<2j~mn@5jNo2&zY&by8fAWjmi@GF!k#k^WTtYgV@X2&y*e5ZA zI9=YMzj54m_DIjlufxaWO-$|AjEMv$Xy*_KiI<-)T_U%~-(H+7 ziT0tUiK+Ic%uMG!yawp+aC*a|6PTc#e}pA0mVEuq7ILTf`RAX>lcUB;qMfL1exb|7 zpZB*rrdz^d;NegPAAmFLp~D_0M~@vR?L|XF1F`26ir!w-HX|#4Dz5=x_P-WOj+nUo z2#e}Nyn`yptT}IzBS(%BUjv`Tx;`=6Zn8y_l#J}vyaq^0vmel#BP2sMPO6@Ie|ju8 zj!vF3RWMASIfu-Ba~^r)t@&ihvX$hM^`DY$+jo%DXU>qW#Day3Mdee^EeGxUcntuh zMd$VAa8VnX2BIVRr%rc`Y$--dOAB$83=+`*;UqC7>nyJU;*&D!vCd44#=)zJeDL9F z(%jra{5fzaz&buLI7V&blhW(?f8PMf{aSRei=@$q3I-$8yic1khg`dModinEePf=W z9Nz+JiyF7{2FN5r8X(i|Aba-iBY_sp&CSG7=n=&Ls4=eruz&#fk=5`pZQ%0h>eZ_x zP-Fjr@44iR5M18^YKt0+Zh+CxPVoD&-j{gp`In?+04)E){-H`H%5u~xPkvRZj-u#7v8346Kjrk4GH&qY= zAcj;v#!LXw)YL@M`{fE}0MJ+x20)A$`4mS$pvQ(!Ka++5V*92DY5>IJPmJc4MS&jf z(!qil05#?}K%Zp64Zuv$e;OM<`&<|UfX0$D00K9C0(ohObpvtnsS+>%t{HVUQSkIL zRb4Uxrjz&X-4DBW8_A;TWn7AR@~cxhOq}#QnegYXVcPWB+=dQ~z-pqzgS?j$e#{S`Pn#{tEUq14(H78ytO?LR<8e|%gGdA#M+xz%ua zm?VA!ME6b<-2jMjRg*e2!FRiMll%ggAnh?hk<6AY+o-+zpByztkba=Hs4=erqTr7> zR;b`%u`zz)a~wH$inZ%Da9J%O+MzXul69YKpf>iuH2EKbaf;eT$;AMOapV8;t2aSi z-36`)Q>Zpz6%Vbbe_pa&P(Ed607T!U3<9NUzaTm;NwEKW+Kk!M#9zN*BlmWZlmYOd zA*mTaEKGn^1FgXMiv_BJgzgh+iyAWnbbw(ao}iYKIDY(upl`8G82}F+40Ho{yhF(K z>vYP~E?l_C6}^hpH`Eq2W(ME^e!Ow%(q$^*W0I=KJ+EbdXK_&!#V_iT}~+kGb@#Yzz; zW&ps`W2$&}8M_+zrBilZv1I!m@CK+DK9XAPAyzk+l@F72{{z|paLo;=hof3(6?I@G zlhirr&;YjZSZ=nc)R_GWnf82g@u#1tjr&txnBRqaEzG07{CPg>h0LElbZOLJ~qRtTXN#0HT50i z{|3PFaQt=BiW5JcBr#CbAvaz+Gyoo6gtNsEcv!B$_OE#NeR|*Y!(->5Vc8GC@mXGZrr#*P5ig!Esz~2cS7sxD9XPK05@Wh`ucjh zr*}XKl^H;SfP;@oZEYPj@ppdv9h_tu;TPijf1LqhggWn3& z7B%KI0NyewWdo>m7C0MVJ)wDsbH(t-{Zjl}20)EvX#i~3(&a0u9@K>A2>Gk{z8S#W ze>&q0Rv9ISnX~3n6(7$6kYc~P6R0g}%x?g=Q9_Cam`L$keT)xRt(L6uyWIewv8)U* z5)P51nd1HWo6X$zvA>HiO9Qw|22(vy`oQ-;aQowdAij?V2!n_4VT0)C*FT?JzI>UQ z_-D?Zg@comCDB)*fZC$Qk~ctNawa){f4-KQ_*br6;S3f?;>*SW;qXn}k)y{5&GY$7 z2bKq%_&ymx4}Zkn@vUruyK=xAf;X~yf$?PRq?T?LvISD-jCFb{&&3p2yY%&Y0ZLi z$_LaIHI|G4swPaLD*mzK$GKGn?S7=B+uJQp!5vH~m_Skn820E$s`mudUARD!QZlLb zA-Z=0nK^r|PbZ76`FI^s!ET(Se+{68KMK*10d6m~<5*iy<;0>6SGSYbCm|IMfvDs@ z2mfaC)=pn}x9X!cFc%Tm1X{5TkO1fB&`j}SoI6)TzWDO1E@AVQtz_5kJ=}glP0jgk zds}_*;YXsHpj`vtr_Q}X^i+`#W!!-t_$I)mFKw>x1k|`416bi99aY4|f2R-@gsfQk z9yhGe=KFS_#-bWP4Rw9&&fwNqvUG*uCJ@~Kh;7?;F!gW7(q$_JHGw1yFmu-HO!+oZ zy>vM@L6d?3T7+nX2QErx@&7S@!8?MO05xvU01ZMkLJ8ZFwRLq&^)_+(%o*->QkuM@ zwi>;qp4R|sy|q@TR}szofB57UCr9TV9#JJbrcl4neq@@ z;WM{TIJ!*;&bc8#XZ?Xc6R5YY7s>$m{~S7eBw&SaYHB9`gq_e3wLuWRZ*i_QSl00y zz!*A9C<7oSPWo#=ioXjkj?Bp`5{&1z2GHqkGx&!9W2hI`q(U_ae+v|8?+ZvNcJJ9s zD&gZ(9E*h(AA#D!9KgeWP^2~fZkVAr3)!eQ-=6Qcg5w6#-hKPIK8o>+za6M8YOH84 z)H?G{A%_7xg2kRw;8)0kZw_MPlDM?D*rK<6{lh6?I}{y-+F+{^>lMX74_ppF7y4|6 z2C!Hx4=B}!#-70%f5PBDfY<+Zoi6e|g)gDfTbK1h=LBgO`~aw>R%cnP@HLbMn+`rB zYI+3zF@yYpTIzHbgQ7D56PRioI~alT#?1|&g^JFG!4Q2f)UMSs6UZ0b(obWo^Lgz5 zb!yl$9Fqr(OnCyeQyZ)mimrs(U|G>C1m6N`1{nc0Q+Hudv+TGJe;L45r*SgAh*?uG9TbXNg{;f_FV xYJsbR$eBuOnhhUvlp>c37A#n>V8Nn$-YSjYrQh^0%c`U1dwNwyDAVfec z4}q8zFd(%>34tJLAP7i73WS7b9wd;2)AL^6Q6skY7F6o!obS61R2? zzJZS(dL&i#8Gn2SA5t>3h~Cgn_|~N;cN#A6F0XPQ4f;FOE~jOP24l)ornP6)AK@&O9(usS>RJs!?#GXlIs%ssegMF4~D*m7$6pIF}S*`$Mb!r z!OzO-_ao7#?8QFM4|B#kJR&Cad{8b);k%gxKi$*sUb@^I#{R>dZcIaLBwy%|Qxxy% z-2L7Y`XT<~9=$TSqYZ97duP&>AoQmT(%w-hq>tp%j9v5D9PSmE?q1rXzC1kn1& zkcxek#BOM5X;BkJIuU>vf&foFGm_NTHxRqxz*h%}9_KAX5a5LgQ!KyN$AW1yUVpP6 z0U$ED)YwQk2swZLf|^3M-3l=L=@I1e<;$D_6!`_q?Rf@33YC+9kmlxQBxmeL0NC$G zjZ+<9cWl|Z&7K5+jU4@=dM&a$hU5&lCjmGKzQxvUAKRAzu(9JO+4^b--9R6wU|#~j z#=kTfO$=-OQGLXdY~P3y5Tsr%qR$(;hZ`xJ9!(IyChVgs{Tvv){C5A}AJ{G=F8HzafoDvk}cbGnXYC!0_bJ9HLwEC zFM0_?IRRp@XGe@>mXkR4&2ddvF;0Lu4cD=zCN@Q?bLY-$TKM4vh||!^cd@pXN$`=R z8Z=~>?tddEKonJSb#)CR4S!&(TKP1>-^mFOVSqwBT|V(*`pnl2^S5#W++b*htEkw| zEcgp^^9}X)aspgu_jm0{{<-~AX2CBi-ekBDdz=8*b@r~`P{b_ws2v!o&yo}123uON zf?4nn9sXK#wJ#??9QLO_&tn$+)2FM|K@3Ly+igz(G^IqUGA0UiI)4ST2OIkDw>1Ht zd2Tc_?IG07PdxdY;eB9R0t_7dxH_tZm8fIFq?b+M2U`*VaL{$&PSFcz_8)Zk}FrPSZ0h1CqNw5e_#%2Xka&P zZtF*XCsuks$5I5K4l7@jl?c*C7O-^7@)*5#ap^_mmwQC zI02~Pc{Y{XSq@}=k&dFZ^B5e%5&-W9ZvUi| z>2(i7qwPKf%a8=X5QUAKN|**8ZvgWVcm^c^M!U0wR)3-nG@o8SULHfQv9fUjL@~_Z zXNk|hsL({z;q~`#_x&Th2ZTNaP5_O^v1&P$6Ml;(PC*6JC?qfp0Y;1(&-95HOyz`R zjI}Ch!J;KGO%~m>xx^5CgoYph%WN6Dnd$AFbLKkpMJz zUW6AkwCeO>`Amz^ftkf`&0nNxeE^Cp8siO-w*X&gPD-CF&3@3d8L!zg_((Ai7?h)V z5`PG>^@xF45ebkb1qNs-mBwnrx-MWOK<|hus9w*=;2i^xM-D|KfZH9ujV=)_TDD2C ze7QsaWxiFNV}QR=k1zhlEf=vxj2+P+dP6(49D#~q525f-OPSJtu==%Wb)b&L5L3ac z>~M4hmlPNSp#v9CTFcTiCA$BIMs-L4zklC;37x7 zkmVs=P#ZAPNtRpu6V(vInD_qgYz0E#F+8howD)hh#a8))0GHnChB^`f4ut$#Xn)RY zAKm-&9El<|HGB)b7MAl{fq4wN0vfYjPN(yGj?RD}gzu1i{VVYb7k6-y;a^Il+1!JY z6u#ThnQ)5YJ(4eUh_3|3{_+w0%uL@;94r7a$#t*<_7zE1 za&bGrHG>C0|EnHiK~MXul9TO;SLtzK? z8i&z<6~XOQo~Qi#8Dim=ihW% zSNl~#`hiOb_NOAm*;H&=NcHIZp-HEmDYa-%;?}O!!bgy9!)Fk1Lc<4NIyg8uI5;>u a7ykk7vtq7l*ZcDT0000 + Zenith.NET - A white Z on a solid graphite rounded square, with a thin, even inner edge for dark backgrounds. + A white Z on a vertically shaded graphite background, with a fine edge reflection that fades softly from top to bottom. + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + From aa689f32827435bad87b124350b09ee6a4bfd237 Mon Sep 17 00:00:00 2001 From: qian-o <1324771795@qq.com> Date: Sun, 20 Sep 2026 09:18:16 +0800 Subject: [PATCH 11/35] Add new styles and scripts for Zenith.NET theme - Introduced layout.css for navigation and site structure styling. - Added motion.css for shared illustration animations and transitions. - Created search.css for site search component styling. - Implemented signature-links.js for linking code references in signatures. - Developed site.js for site navigation and interaction functionalities. - Established theme.css for overall theme styling, including color schemes and typography. --- documents/api/index.md | 2 +- documents/authoring.md | 85 + documents/learn/index.md | 12 +- .../templates/ManagedReference.extension.js | 68 +- documents/templates/layout/_master.tmpl | 105 +- .../templates/partials/api.code.tmpl.partial | 4 + .../templates/partials/api.enum.tmpl.partial | 2 +- .../partials/api.header.tmpl.partial | 9 +- .../partials/api.member-launcher.tmpl.partial | 5 + .../partials/api.relationships.tmpl.partial | 49 +- .../partials/api.seealso.tmpl.partial | 9 +- .../api.signature-references.tmpl.partial | 1 + .../partials/api.signature.tmpl.partial | 42 +- .../partials/api.source.tmpl.partial | 5 + .../templates/partials/api.type.tmpl.partial | 15 +- .../partials/site.footer.tmpl.partial | 13 + .../partials/site.header.tmpl.partial | 22 + .../partials/site.member-finder.tmpl.partial | 23 + .../partials/site.search.tmpl.partial | 21 + .../partials/site.sidebar.tmpl.partial | 37 + documents/templates/public/api.css | 1323 +++++++++++++-- documents/templates/public/api.js | 12 +- documents/templates/public/code-links.js | 66 + documents/templates/public/content.css | 190 +++ documents/templates/public/dialog.js | 27 + documents/templates/public/home.css | 503 ++++++ documents/templates/public/home.js | 17 +- documents/templates/public/layout.css | 461 ++++++ documents/templates/public/main.css | 1429 +---------------- documents/templates/public/main.js | 91 +- documents/templates/public/member-finder.js | 35 +- documents/templates/public/motion.css | 336 ++++ documents/templates/public/motion.js | 4 +- documents/templates/public/search.css | 213 +++ documents/templates/public/search.js | 35 +- documents/templates/public/signature-links.js | 119 ++ documents/templates/public/site.js | 82 + documents/templates/public/theme.css | 242 +++ 38 files changed, 3841 insertions(+), 1873 deletions(-) create mode 100644 documents/authoring.md create mode 100644 documents/templates/partials/api.code.tmpl.partial create mode 100644 documents/templates/partials/api.member-launcher.tmpl.partial create mode 100644 documents/templates/partials/api.signature-references.tmpl.partial create mode 100644 documents/templates/partials/api.source.tmpl.partial create mode 100644 documents/templates/partials/site.footer.tmpl.partial create mode 100644 documents/templates/partials/site.header.tmpl.partial create mode 100644 documents/templates/partials/site.member-finder.tmpl.partial create mode 100644 documents/templates/partials/site.search.tmpl.partial create mode 100644 documents/templates/partials/site.sidebar.tmpl.partial create mode 100644 documents/templates/public/code-links.js create mode 100644 documents/templates/public/content.css create mode 100644 documents/templates/public/dialog.js create mode 100644 documents/templates/public/home.css create mode 100644 documents/templates/public/layout.css create mode 100644 documents/templates/public/motion.css create mode 100644 documents/templates/public/search.css create mode 100644 documents/templates/public/signature-links.js create mode 100644 documents/templates/public/site.js create mode 100644 documents/templates/public/theme.css diff --git a/documents/api/index.md b/documents/api/index.md index 9cdfdaf8..26142441 100644 --- a/documents/api/index.md +++ b/documents/api/index.md @@ -4,7 +4,7 @@ description: Explore the types and members in Zenith.NET. ---
    -
    Reference

    API Reference

    Types and members for graphics, compute, and platform integration.

    +

    API Reference

    Types and members for graphics, compute, and platform integration.

    Start hereGraphicsContext

    Create and manage your graphics resources.

    Record workCommandBuffer

    Build graphics and compute command sequences.

    diff --git a/documents/authoring.md b/documents/authoring.md new file mode 100644 index 00000000..5e55b44f --- /dev/null +++ b/documents/authoring.md @@ -0,0 +1,85 @@ +# Writing linked documentation + +This is a maintainer reference. It is not included in the site's navigation. + +## Inline references + +Use DocFX UIDs so links follow the generated API reference: + +```markdown +Create a [`GraphicsContext`](xref:Zenith.NET.GraphicsContext). +``` + +Plain backticks mark code without adding a link. Specify a UID when a reference is intended; identical names alone do not establish which symbol they refer to. + +## Linked code blocks + +Ordinary fenced code blocks retain their usual syntax highlighting and copy behavior. When a block needs clickable symbols, use a native HTML code block with DocFX `xref` elements: + +```html +
     context = CreateContext();
    + buffer = context.(description);
    +``` + +The `text` attribute is the exact code to display and copy. Escape HTML characters such as `<`, `>` and `&` in the code text and attribute values. A reference can cover a qualified name or a complete generic type expression. + +DocFX resolves the UID during the build. The shared code-link renderer preserves the reference through highlighting; copying returns only the displayed code. The same renderer handles generated API declarations. Comments, strings, parameter names and tuple element names do not acquire links by matching another symbol's spelling. + +## Automatic link scope + +Generated API declarations link **types with a reference page on this site** in these positions: + +- Field, property and event types, and method/operator return types. +- Method, constructor and indexer parameter types. +- Base classes and implemented interfaces in a type declaration. + +This includes local types inside generic, nullable, array, pointer and tuple expressions. The declared member's own name, parameter names, generic parameter names, tuple element names, attributes, generic constraints, modifiers and literal values remain text. Framework and third-party types without a local API page also remain text; automatic references do not lead to external documentation. + +Tutorial code and XML code examples do not acquire guessed links. Authored Markdown/HTML `xref` and XML prose `see` references are explicit and may point to local or external documentation. Only rendered links receive the code-reference color, pointer cursor and focus treatment. + +## XML comments + +Write a short `` describing behavior. Add ``, ``, `` and `` when they explain something beyond the declaration. These sections are displayed only when their descriptions contain content. Use `` for constraints, `` for failure conditions and `` for usage. + +Use `` for references in prose, `` and `` for names, and `` for literal inline code. The compiler resolves `cref` in the source's context. + +```csharp +/// Creates a buffer using . +/// The size, usage and memory requirements. +/// The newly created buffer. +/// The caller owns the returned resource. +/// +/// See . +/// +/// +``` + +Keep XML `` contents literal using `CDATA`. Put `` references in the surrounding prose: DocFX extracts the text of XML code examples and discards nested reference elements, which can remove the referenced identifier. The HTML `xref` form above applies to authored Markdown pages. + +## Validation + +After changing XML comments, run the full extraction and build from the repository root: + +```sh +docfx documents/docfx.json --warningsAsErrors +``` + +For Markdown or theme-only changes, run `docfx build documents/docfx.json --warningsAsErrors`. + +Check the resulting type page and a tutorial page in the browser. Verify links after highlighting, keyboard focus, copied code, long generic signatures and narrow layouts. A documented member should keep its summary, parameter descriptions, return/value explanation, remarks, examples and exceptions. An undocumented member should remain compact. + +## Template organization + +The template keeps DocFX's existing entry points and the `layout`, `partials` and `public` directories. + +- `layout/_master.tmpl` assembles the page shell from the `site.*` partials. +- `api.*` partials render generated reference data. `ManagedReference.extension.js` prepares names, descriptions and unique member anchors. +- `public/main.css` is the stylesheet entry. Theme, layout, search, content, home and motion styles have separate files; `api.css` is loaded only on reference pages. +- `public/main.js` is DocFX's extension entry. `site.js` owns navigation and content setup; `dialog.js` shares keyboard and backdrop behavior between the search dialogs. +- `code-links.js` preserves authored references through highlighting. `signature-links.js` supplies the bounded, metadata-driven references for API declarations. + +Keep the generated `_site` and API metadata out of source edits. Rebuild after template changes, and check existing page URLs, fragment links and copy behavior before publishing. diff --git a/documents/learn/index.md b/documents/learn/index.md index c4c8bc09..853b9b91 100644 --- a/documents/learn/index.md +++ b/documents/learn/index.md @@ -10,7 +10,6 @@ _disableAffix: true

    Start with a triangle, explore the samples, and find the concepts behind the API.

    Core concepts

    The rules and decisions behind a rendering application.

    diff --git a/documents/templates/ManagedReference.extension.js b/documents/templates/ManagedReference.extension.js index 8daed42e..c6f72ff5 100644 --- a/documents/templates/ManagedReference.extension.js +++ b/documents/templates/ManagedReference.extension.js @@ -1,20 +1,63 @@ -exports.postTransform = function (model) { - const labels = { - classes: 'Classes', structs: 'Structs', interfaces: 'Interfaces', enums: 'Enums', - delegates: 'Delegates', constructors: 'Constructors', fields: 'Fields', properties: 'Properties', - methods: 'Methods', events: 'Events', operators: 'Operators', eii: 'Explicit implementations' - }; - const kind = type => type ? type.charAt(0).toUpperCase() + type.slice(1) : 'Type'; - model.apiKind = kind(model.type); +const groupTitles = { + classes: 'Classes', structs: 'Structs', interfaces: 'Interfaces', enums: 'Enums', + delegates: 'Delegates', constructors: 'Constructors', fields: 'Fields', properties: 'Properties', + methods: 'Methods', events: 'Events', operators: 'Operators', eii: 'Explicit implementations' +}; +const relationshipKeys = ['inheritance', 'implements', 'derivedClasses', 'inheritedMembers', 'extensionMethods']; + +function prepareSignature(syntax) { + if (!syntax) return; + const value = syntax.fieldValue || syntax.propertyValue || syntax.eventType || syntax.return; + if (value) { + syntax.apiValueReference = value.type?.specName?.[0]?.value; + syntax.apiResult = { + label: syntax.return ? 'Returns' : 'Value', + type: syntax.apiValueReference, + description: value.description, + showType: !syntax.content?.[0]?.value + }; + } + syntax.apiParameterDescriptions = (syntax.parameters || []).filter(parameter => parameter.description?.trim()); + syntax.apiTypeParameterDescriptions = (syntax.typeParameters || []).filter(parameter => parameter.description?.trim()); +} + +function uidSuffix(uid) { + let hash = 2166136261; + for (let index = 0; index < uid.length; index++) hash = Math.imul(hash ^ uid.charCodeAt(index), 16777619); + return (hash >>> 0).toString(16); +} + +exports.postTransform = function (model) { model.apiName = model.name?.[0]?.value || model.uid; model.apiHasMemberFinder = !model.isNamespace; model.apiSeeAlsoId = 'seealso'; - model.apiHasRelationships = ['inheritance', 'implements', 'derivedClasses', 'inheritedMembers', 'extensionMethods'] - .some(key => Array.isArray(model[key]) && model[key].length > 0); + model.apiHasRelationships = relationshipKeys.some(key => model[key]?.length > 0); + model.apiHasTypeDetails = !model.isNamespace && (model.apiHasRelationships || !!model.namespace?.uid || !!model.assemblies?.length); + model.apiTypeDetailsLabel = model.apiHasRelationships ? 'Inheritance and metadata' : 'Type metadata'; + prepareSignature(model.syntax); + if (model.syntax) { + model.syntax.apiBaseReferences = [...(model.inheritance || []), ...(model.implements || [])] + .map(type => ({ type: type.specName?.[0]?.value })).filter(reference => reference.type); + } + + const anchors = new Set([model.id]); + const overloads = new Set(); for (const group of model.children || []) { - group.apiTitle = model.isEnum ? 'Values' : labels[group.id] || group.id.replace(/[-_]/g, ' '); + group.apiTitle = model.isEnum ? 'Values' : groupTitles[group.id] || group.id.replace(/[-_]/g, ' '); for (const item of group.children || []) { - item.apiSeeAlsoId = item.id + '_seealso'; + item.apiName = item.name?.[0]?.value || item.uid; + // DocFX normalizes pointer/by-ref UIDs to identical IDs in some overloads. + // Keep the first canonical anchor; later members get stable local anchors. + let anchor = item.id; + if (anchors.has(anchor)) anchor += '_' + uidSuffix(item.uid); + item.apiAnchor = anchor; + anchors.add(anchor); + item.apiSeeAlsoId = anchor + '_seealso'; + if (item.overload && !overloads.has(item.overload.id)) { + item.apiOverload = item.overload; + overloads.add(item.overload.id); + } + prepareSignature(item.syntax); } } if (model.namespace?.uid && model.namespace.specName) { @@ -22,6 +65,5 @@ name.value = `${model.namespace.uid}`; } } - return model; }; diff --git a/documents/templates/layout/_master.tmpl b/documents/templates/layout/_master.tmpl index dca7e3c2..2f260634 100644 --- a/documents/templates/layout/_master.tmpl +++ b/documents/templates/layout/_master.tmpl @@ -1,7 +1,5 @@ {{!Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license.}} {{!include(/^public/.*/)}} -{{!include(favicon.ico)}} -{{!include(logo.svg)}} @@ -16,7 +14,7 @@ {{#_description}}{{/_description}} {{#description}}{{/description}} - + {{#_apiReference}}{{/_apiReference}} @@ -37,7 +35,7 @@ - + + - + {{#_apiReference}}{{/_apiReference}} + {{#_noindex}}{{/_noindex}} - {{#_googleAnalyticsTagId}} - - - {{/_googleAnalyticsTagId}} - {{/redirect_url}} + + + + {{#_resourceTitle}}{{/_resourceTitle}} + {{#_resourceDescription}}{{/_resourceDescription}} + + + - {{^redirect_url}} - + {{>partials/site.header}}
    @@ -64,8 +41,8 @@
    {{^_disableToc}} {{#apiHasMemberFinder}}
    {{/apiHasMemberFinder}} - {{#apiHasMemberFinder}} {{>partials/api.member-launcher}} @@ -80,7 +57,7 @@ {{^_disableAffix}} {{/_disableAffix}}
    @@ -91,5 +68,4 @@ {{>partials/site.footer}} - {{/redirect_url}} diff --git a/documents/templates/partials/api.enum.tmpl.partial b/documents/templates/partials/api.enum.tmpl.partial index fa139577..be42dab5 100644 --- a/documents/templates/partials/api.enum.tmpl.partial +++ b/documents/templates/partials/api.enum.tmpl.partial @@ -1,7 +1,7 @@ {{!Based on the .NET Foundation DocFX templates, licensed under the MIT license.}} {{#children}}
    -

    {{apiTitle}}

    +

    {{apiTitle}}

    {{#children}}
    @@ -13,6 +13,6 @@
    {{/children}} -{{#remarks}}

    Remarks

    {{{remarks}}}
    {{/remarks}} -{{#example.0}}

    Examples

    {{#example}}{{{.}}}{{/example}}
    {{/example.0}} +{{#remarks}}

    {{r.ui.reference.remarks}}

    {{{remarks}}}
    {{/remarks}} +{{#example.0}}

    {{r.ui.reference.examples}}

    {{#example}}{{{.}}}{{/example}}
    {{/example.0}} {{>partials/api.seealso}} diff --git a/documents/templates/partials/api.header.tmpl.partial b/documents/templates/partials/api.header.tmpl.partial index 4fdb6b71..ec0eee97 100644 --- a/documents/templates/partials/api.header.tmpl.partial +++ b/documents/templates/partials/api.header.tmpl.partial @@ -5,7 +5,7 @@ {{#conceptual}}
    {{{conceptual}}}
    {{/conceptual}} {{#syntax.content.0.value}} -
    +
    {{>partials/api.source}} {{>partials/api.code}}
    diff --git a/documents/templates/partials/api.member-launcher.tmpl.partial b/documents/templates/partials/api.member-launcher.tmpl.partial index ee56ecbc..7d5de82d 100644 --- a/documents/templates/partials/api.member-launcher.tmpl.partial +++ b/documents/templates/partials/api.member-launcher.tmpl.partial @@ -1,5 +1,5 @@ diff --git a/documents/templates/partials/api.namespace.tmpl.partial b/documents/templates/partials/api.namespace.tmpl.partial index aed72875..2a1228ec 100644 --- a/documents/templates/partials/api.namespace.tmpl.partial +++ b/documents/templates/partials/api.namespace.tmpl.partial @@ -1,7 +1,7 @@ {{!Based on the .NET Foundation DocFX templates, licensed under the MIT license.}} {{#children}}
    -

    {{apiTitle}}

    +

    {{apiTitle}}

    {{#children}}
    {{name.0.value}}{{#summary}}
    {{{summary}}}
    {{/summary}}
    @@ -9,5 +9,5 @@
    {{/children}} -{{#remarks}}

    Remarks

    {{{remarks}}}
    {{/remarks}} -{{#example.0}}

    Examples

    {{#example}}{{{.}}}{{/example}}
    {{/example.0}} +{{#remarks}}

    {{r.ui.reference.remarks}}

    {{{remarks}}}
    {{/remarks}} +{{#example.0}}

    {{r.ui.reference.examples}}

    {{#example}}{{{.}}}{{/example}}
    {{/example.0}} diff --git a/documents/templates/partials/api.relationships.tmpl.partial b/documents/templates/partials/api.relationships.tmpl.partial index caaa45fd..a189fdd1 100644 --- a/documents/templates/partials/api.relationships.tmpl.partial +++ b/documents/templates/partials/api.relationships.tmpl.partial @@ -1,32 +1,32 @@ {{!Based on the .NET Foundation DocFX templates, licensed under the MIT license.}}
    - {{apiTypeDetailsLabel}} + {{apiTypeDetailsLabel}}
    {{#inheritance.0}}
    -

    Inheritance

    +

    {{r.ui.reference.inheritance}}

      {{#inheritance}}
    • {{{specName.0.value}}}
    • {{/inheritance}}
    • {{apiName}}
    {{/inheritance.0}} {{#implements.0}}
    -

    Interfaces

    +

    {{r.ui.reference.interfaces}}

      {{#implements}}
    • {{{specName.0.value}}}
    • {{/implements}}
    {{/implements.0}} {{#derivedClasses.0}}
    -

    Derived types

    +

    {{r.ui.reference.derived}}

      {{#derivedClasses}}
    • {{{specName.0.value}}}
    • {{/derivedClasses}}
    {{/derivedClasses.0}} {{#inheritedMembers.0}}
    -

    Inherited members

    +

    {{r.ui.reference.inheritedMembers}}

      {{#inheritedMembers}}
    • {{#definition}}{{/definition}}{{^definition}}{{/definition}}
    • @@ -36,7 +36,7 @@ {{/inheritedMembers.0}} {{#extensionMethods.0}}
      -

      Extension methods

      +

      {{r.ui.reference.extensionMethods}}

        {{#extensionMethods}}
      • {{#definition}}{{/definition}}{{^definition}}{{/definition}}
      • diff --git a/documents/templates/partials/api.seealso.tmpl.partial b/documents/templates/partials/api.seealso.tmpl.partial index c7c7f50e..204a7a27 100644 --- a/documents/templates/partials/api.seealso.tmpl.partial +++ b/documents/templates/partials/api.seealso.tmpl.partial @@ -1,7 +1,7 @@ {{!Based on the .NET Foundation DocFX templates, licensed under the MIT license.}} {{#seealso.0}}
    {{/children}} -{{#remarks}}

    Remarks

    {{{remarks}}}
    {{/remarks}} -{{#example.0}}

    Examples

    {{#example}}{{{.}}}{{/example}}
    {{/example.0}} +{{#remarks}}

    {{r.ui.reference.remarks}}

    {{{remarks}}}
    {{/remarks}} +{{#example.0}}

    {{r.ui.reference.examples}}

    {{#example}}{{{.}}}{{/example}}
    {{/example.0}} {{>partials/api.seealso}} diff --git a/documents/templates/partials/site.footer.tmpl.partial b/documents/templates/partials/site.footer.tmpl.partial index 8dd9e336..e6a44117 100644 --- a/documents/templates/partials/site.footer.tmpl.partial +++ b/documents/templates/partials/site.footer.tmpl.partial @@ -2,10 +2,10 @@
    -
    {{/children}} -{{#remarks}}

    {{r.ui.reference.remarks}}

    {{{remarks}}}
    {{/remarks}} -{{#example.0}}

    {{r.ui.reference.examples}}

    {{#example}}{{{.}}}{{/example}}
    {{/example.0}} -{{>partials/api.seealso}} diff --git a/documents/templates/public/api.css b/documents/templates/public/api.css index 38e4c5f5..57b8eec6 100644 --- a/documents/templates/public/api.css +++ b/documents/templates/public/api.css @@ -45,7 +45,6 @@ body.zenith-theme[data-section="api"] > main > .toc-offcanvas { .api-namespace-picker { border-radius: calc(var(--zenith-radius) - 1px) calc(var(--zenith-radius) - 1px) 0 0; position: relative; - flex-shrink: 0; min-height: 44px; padding: 11px 32px 11px 12px; color: var(--zenith-text); @@ -72,7 +71,6 @@ body.zenith-theme[data-section="api"] > main > .toc-offcanvas { } .api-namespace-picker, .api-type-search { - border-radius: 0 0 calc(var(--zenith-radius) - 1px) calc(var(--zenith-radius) - 1px); transition: box-shadow 180ms, background-color 180ms; } @@ -101,6 +99,7 @@ body.zenith-theme[data-section="api"] > main > .toc-offcanvas { min-height: 42px; padding: 8px 12px; border-top: 1px solid var(--zenith-border); + border-radius: 0 0 calc(var(--zenith-radius) - 1px) calc(var(--zenith-radius) - 1px); color: var(--zenith-muted); } @@ -244,10 +243,6 @@ body.zenith-theme[data-section="api"] > main > .toc-offcanvas { margin-top: 18px; } -.api-summary > :last-child { - margin-bottom: 0; -} - .api-reference :is(.api-summary, .api-value-description, .api-parameters dd, .api-member-notes) > :is(p, ul, ol, dl) { margin: 0 0 12px; } @@ -709,10 +704,6 @@ body.zenith-theme[data-section="api"] > main > .toc-offcanvas { font-size: 13px; } -.api-value-description > :last-child { - margin-bottom: 0; -} - .api-signature-section, .api-member-notes, .api-related { margin-top: 18px; } @@ -901,11 +892,7 @@ body.zenith-theme[data-section="api"] > main > .toc-offcanvas { font: 10px/1.5 var(--bs-font-monospace); } -.api-mobile-tools { - display: none; -} - -.api-menu-member { +.api-mobile-tools, .api-menu-member { display: none; } @@ -919,7 +906,7 @@ body.zenith-theme[data-section="api"] > main > .toc-offcanvas { column-gap: 28px; } - .api-type-grid, .api-namespace-grid { + .api-namespace-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } } @@ -979,7 +966,6 @@ body.zenith-theme[data-section="api"] > main > .toc-offcanvas { .api-mobile-tools > .api-member-launcher { width: auto; - min-height: 40px; } .menu-open .api-menu-member { diff --git a/documents/templates/public/search.css b/documents/templates/public/search.css index af340a3a..9c8c567a 100644 --- a/documents/templates/public/search.css +++ b/documents/templates/public/search.css @@ -67,22 +67,27 @@ body:has(.site-search[open]) { border-bottom-color: var(--zenith-focus); } -#site-search-input { +#site-search-input, #api-member-query { width: 100%; min-width: 0; - padding: 6px 0; + padding: 0; border: 0; outline: none; background: none; color: var(--zenith-text); + font: 16px/1.6 var(--bs-body-font-family); +} + +#site-search-input { + padding: 6px 0; font: 400 21px/1.5 var(--bs-body-font-family); } -#site-search-input::placeholder { +#site-search-input::placeholder, #api-member-query::placeholder { color: var(--zenith-muted); } -#site-search-input::-webkit-search-cancel-button { +#site-search-input::-webkit-search-cancel-button, #api-member-query::-webkit-search-cancel-button { display: none; } @@ -113,7 +118,7 @@ body:has(.site-search[open]) { font: 12px/1.5 var(--bs-body-font-family); } -#site-search-results { +#site-search-results, #api-member-results ul { margin: 0; padding: 0; list-style: none; @@ -233,25 +238,6 @@ body:has(.site-search[open]) { border-color: var(--zenith-focus); } -#api-member-query { - width: 100%; - min-width: 0; - padding: 0; - border: 0; - outline: 0; - background: none; - color: var(--zenith-text); - font: 16px/1.6 var(--bs-body-font-family); -} - -#api-member-query::placeholder { - color: var(--zenith-muted); -} - -#api-member-query::-webkit-search-cancel-button { - display: none; -} - #api-member-clear { flex-shrink: 0; width: 30px; @@ -280,12 +266,6 @@ body:has(.site-search[open]) { font: 500 11px/1.5 var(--bs-body-font-family); } -#api-member-results ul { - margin: 0; - padding: 0; - list-style: none; -} - #api-member-results a { display: block; padding: 11px 12px; @@ -298,7 +278,6 @@ body:has(.site-search[open]) { #api-member-results a:hover, #api-member-results a:focus-visible { background: var(--zenith-hover); - color: var(--zenith-text); } #api-member-results a:focus-visible { @@ -344,4 +323,3 @@ body:has(.site-search[open]) { padding: 12px 16px; } } - From b99f4190e8179d234b12dc32928daaaca4bb9f40 Mon Sep 17 00:00:00 2001 From: qian-o <1324771795@qq.com> Date: Mon, 21 Sep 2026 00:39:04 +0800 Subject: [PATCH 16/35] Update samples documentation and localization strings - Enhanced the samples documentation by adding xref links for pixel formats and capabilities in the `samples.md` file. - Improved clarity and conciseness in the localization strings within `strings.yml`, including descriptions for execution context, ownership, queues, platforms, synchronization, and tutorials. - Adjusted descriptions to better guide users through the rendering and compute processes, ensuring a more intuitive understanding of the Zenith.NET framework. --- documents/authoring.md | 22 ++- documents/learn/concepts/execution-model.md | 22 +-- .../learn/concepts/platform-integration.md | 38 ++-- .../learn/concepts/resource-management.md | 70 ++++---- .../learn/concepts/shader-data-and-binding.md | 30 ++-- documents/learn/concepts/synchronization.md | 36 ++-- documents/learn/first-triangle.md | 76 ++++---- documents/learn/samples.md | 6 +- documents/locales/en-US/strings.yml | 164 +++++++++--------- 9 files changed, 238 insertions(+), 226 deletions(-) diff --git a/documents/authoring.md b/documents/authoring.md index bebd37a8..816d60bb 100644 --- a/documents/authoring.md +++ b/documents/authoring.md @@ -58,6 +58,8 @@ Teach the triangle in cumulative steps: an empty window, a presented clear color Follow the established tutorial source's code style: explicit control flow, target-typed initialization, and its blank lines between logical operations and fields. Do not compress branches into nested conditional expressions, manually wrap method calls to fit the page, or introduce constants and helper functions solely to reorganize the article. Long code lines scroll within the existing code blocks. +Use ordinary file-level `using` directives in the standalone tutorial. A support file copied from the tutorial repository may rely on that repository's global imports; state the imports it needs in the reader's project instead of introducing a global import to make the file compile. + Introduce file settings when the file is created. For a shader, describe its Copy to Output Directory setting after writing the shader; do not front-load project XML for files the reader has not created. Prefer a directly linked support filename with a short purpose statement over raw-file download instructions. Keep snippets consistent with the complete application. The assembled source must not depend on omitted setup or unexplained helper methods. Keep platform-specific alternatives only where they are necessary to run it. @@ -68,13 +70,25 @@ Compile the complete tutorial using its documented setup and run it to verify th ## Inline references -Use DocFX UIDs so links follow the generated API reference: +In Learn prose and tables, link every explicitly named Zenith.NET API identifier that has a reference on this site. Use DocFX UIDs so the build checks the target and the link follows the generated API. Link a type to its type page, a member to its member entry, and a method family to its overload group when the discussion applies to all overloads. Repeated mentions follow the same rule; do not link only an arbitrary first occurrence. + +Keep the link and code styling in the shared page's slot. The English dictionary contains the complete sentence and its named placeholder, as described under [Resource keys and placeholders](#resource-keys-and-placeholders): -```markdown -Create a [`GraphicsContext`](xref:Zenith.NET.GraphicsContext). +```html +GraphicsContext ``` -Plain backticks mark code without adding a link. Specify a UID when a reference is intended; identical names alone do not establish which symbol they refer to. +For a code expression, link only the API symbols. Keep local variables, arguments, punctuation and operators as text within the same slot so translators can move the complete expression: + +```html +context.GraphicsApi +``` + +Plain code is intentional for variables, parameter names, keywords, literals, sample-defined types, package names, filenames and external symbols without a local reference. Resolve the meaning in context: the sample's `Vertex` struct differs from `BufferUsages.Vertex`, and the `Zenith.NET` package name differs from the namespace. A window's `Dispose()` must not link to the RHI's disposal method just because they share a name. + +If a documented API is absent from the generated reference, keep its identifier plain and provide a clearly labeled source link nearby. Do not substitute a containing type or unrelated member. Links belong to the shared markup, not translated strings; translators retain and may reorder the named placeholders without choosing API destinations. + +Ordinary tutorial code fences remain unlinked. Syntax coloring does not imply a reference. The explicit linked-block mechanism and the generated declaration scope below remain separate from this prose rule. ## Linked code blocks diff --git a/documents/learn/concepts/execution-model.md b/documents/learn/concepts/execution-model.md index 6918da91..45c04078 100644 --- a/documents/learn/concepts/execution-model.md +++ b/documents/learn/concepts/execution-model.md @@ -5,11 +5,11 @@ title: '@concepts.execution.title'

    -

    GraphicsContext

    -

    CapabilitiesRayTracingSupportedMeshShadingSupported

    +

    GraphicsContext

    +

    CapabilitiesRayTracingSupportedMeshShadingSupported

    -

    GraphicsQueue

    +

    GraphicsQueue

    @@ -19,15 +19,15 @@ title: '@concepts.execution.title' - + - + - + @@ -35,15 +35,15 @@ title: '@concepts.execution.title'

    -

    queue.CommandBuffer()CommandBufferSubmit()TimelineValue

    +

    queue.CommandBuffer()CommandBufferSubmit()TimelineValue

    commandBuffer

    ```csharp commandBuffer.Submit().Wait(); ``` -

    Submit()Wait()

    -

    queue.CommandBuffer()

    +

    Submit()Wait()

    +

    queue.CommandBuffer()

    @@ -67,7 +67,7 @@ commandBuffer.Submit().Wait(); - + @@ -76,6 +76,6 @@ commandBuffer.Submit().Wait();
    GraphicsQueueGraphicsQueue
    ComputeQueueComputeQueue
    TransferQueueTransferQueue
    SwapChain.DrawableSwapChain.Drawable
    -

    Dispose()

    +

    Dispose()

    diff --git a/documents/learn/concepts/platform-integration.md b/documents/learn/concepts/platform-integration.md index 243cd3a3..566e3478 100644 --- a/documents/learn/concepts/platform-integration.md +++ b/documents/learn/concepts/platform-integration.md @@ -6,7 +6,7 @@ title: '@concepts.platforms.title'

    -

    SurfaceSwapChain

    +

    SurfaceSwapChain

    @@ -18,45 +18,45 @@ title: '@concepts.platforms.title' - + - + - + - + - +
    Win32Win32 HWND
    WaylandWayland
    XlibXlib
    AndroidAndroid ANativeWindow
    AppleApple CAMetalLayer
    -

    App.csSurface.Wayland

    -

    context.Capabilities

    +

    App.csSurface.Wayland

    +

    context.Capabilities

    -

    SwapChain.Drawable

    -

    SwapChain.ResizeSwapChain.Refresh

    +

    SwapChain.Drawable

    +

    SwapChain.ResizeSwapChain.Refresh

    -

    Desc.WidthDesc.HeightDesc.FormatDesc.SampleCount

    +

    Desc.WidthDesc.HeightDesc.FormatDesc.SampleCount

    -

    IZenithViewGraphicsContextUpdateRequestedRenderRequestedRenderEventArgs

    -

    ColorAttachment

    -

    IZenithViewviewusing Zenith.NET;

    +

    IZenithViewGraphicsContextUpdateRequestedRenderRequestedRenderEventArgs

    +

    ColorAttachment

    +

    IZenithViewviewusing Zenith.NET;

    ```csharp view.RenderRequested += (_, args) => @@ -67,9 +67,9 @@ view.RenderRequested += (_, args) => }; ``` -

    ColorAttachment

    -

    Undefined

    -

    ZenithViewHelper.DrawableFormat

    +

    ColorAttachment

    +

    Undefined

    +

    ZenithViewHelper.DrawableFormat

    @@ -106,7 +106,7 @@ view.RenderRequested += (_, args) =>
    -

    RenderRequested

    +

    RenderRequested

    ```sh @@ -115,6 +115,6 @@ dotnet add package Zenith.NET.Views.Avalonia

    UseZenithViewExtensions.cs

    -

    GraphicsContext

    +

    GraphicsContext

    FrameScheduler.cs

    diff --git a/documents/learn/concepts/resource-management.md b/documents/learn/concepts/resource-management.md index 9349079b..2a573b11 100644 --- a/documents/learn/concepts/resource-management.md +++ b/documents/learn/concepts/resource-management.md @@ -5,7 +5,7 @@ title: '@concepts.resources.title'

    -

    BufferUsagesTextureUsagesBufferDesc.UsagesTextureDesc.Usages|

    +

    BufferUsagesTextureUsagesBufferDesc.UsagesTextureDesc.Usages|

    @@ -16,39 +16,39 @@ title: '@concepts.resources.title' - + - + - + - + - + - + - + - + - + @@ -63,40 +63,40 @@ title: '@concepts.resources.title' - + - + - + - + - + - + - +
    NoneNone
    VertexVertex
    IndexIndex
    IndirectIndirect
    ConstantConstant
    StorageReadOnlyStorageReadOnly
    StorageReadWriteStorageReadWrite
    TransferSrcTransferSrc
    TransferDstTransferDst
    NoneNone
    SampledSampled
    StorageStorage
    ColorAttachmentColorAttachment
    DepthStencilAttachmentDepthStencilAttachment
    TransferSrcTransferSrc
    TransferDstTransferDst
    -

    TransferSrcTransferDst

    +

    -

    BufferDescResidency

    +

    BufferDescResidency

    @@ -107,25 +107,25 @@ title: '@concepts.resources.title' - + - + - +
    GpuOnlyGpuOnly
    CpuReadOnlyCpuReadOnly
    CpuWriteOnlyCpuWriteOnly
    -

    CpuWriteOnly

    -

    TextureDescMap()

    -

    Map()Unmap()

    +

    CpuWriteOnly

    +

    TextureDesc

    +

    Map()Unmap()

    @@ -137,33 +137,33 @@ title: '@concepts.resources.title' - - + + - - + + - +
    Buffer.UploadCpuWriteOnlyBuffer.UploadCpuWriteOnly
    Buffer.DownloadCpuReadOnlyBuffer.DownloadCpuReadOnly
    Texture.UploadTexture.DownloadTexture.UploadTexture.Download

    -

    CommandBuffer.UploadCommandBuffer.Download

    +

    CommandBuffer.UploadCommandBuffer.Download

    -

    Heap

    -

    context.GetSizeAndAlignment

    +

    Heap

    +

    context.GetSizeAndAlignment

    -

    BufferViewTextureView

    +

    BufferViewTextureView

    diff --git a/documents/learn/concepts/shader-data-and-binding.md b/documents/learn/concepts/shader-data-and-binding.md index 9eba1c39..777b3169 100644 --- a/documents/learn/concepts/shader-data-and-binding.md +++ b/documents/learn/concepts/shader-data-and-binding.md @@ -5,7 +5,7 @@ title: '@concepts.shaders.title'

    -

    ZenithCompilerShaderDescGraphicsApi

    +

    ZenithCompilerShaderDescGraphicsApi

    context

    ```csharp @@ -17,10 +17,10 @@ Shader vertexShader = context.CreateShader(ZenithCompiler.CompileFromFile(contex

    VSMain

    -

    InputLayoutFloat3Float4InputLayout.Add

    -

    InputLayoutfloat3

    +

    InputLayoutFloat3Float4InputLayout.Add

    +

    InputLayoutfloat3

    -

    System.Runtime.InteropServicesZenith.NET

    +

    System.Runtime.InteropServicesZenith.NET

    ```csharp [StructLayout(LayoutKind.Explicit, Size = 256)] @@ -63,7 +63,7 @@ ConstantBuffer constants;

    -

    SetConstantBuffer

    +

    SetConstantBuffer

    ```csharp @@ -72,8 +72,8 @@ commandBuffer.SetConstantBuffer(constantBuffer, 0); commandBuffer.Dispatch(groupCountX, groupCountY, 1); ``` -

    commandBuffercomputePipelineconstantBufferBufferUsages.Constant

    -

    InputinputTexture.SampledHandleOutputoutputTexture.StorageHandleDescriptorHandle

    +

    commandBuffercomputePipelineconstantBufferBufferUsages.Constant

    +

    InputinputTexture.SampledHandleOutputoutputTexture.StorageHandleDescriptorHandle

    @@ -84,34 +84,34 @@ commandBuffer.Dispatch(groupCountX, groupCountY, 1); - + - + - + - + - +
    texture.SampledHandletexture.SampledHandle DescriptorHandle<Texture2D>
    texture.StorageHandletexture.StorageHandle DescriptorHandle<RWTexture2D<float4>>
    buffer.StorageReadOnlyHandlebuffer.StorageReadOnlyHandle DescriptorHandle<StructuredBuffer<T>> T
    buffer.StorageReadWriteHandlebuffer.StorageReadWriteHandle DescriptorHandle<RWStructuredBuffer<T>> T
    sampler.Handlesampler.Handle DescriptorHandle<SamplerState>
    -

    ResourceHandle

    +

    ResourceHandle

    -

    Dispatch[numthreads(16, 16, 1)]

    -

    ShaderDesc.ThreadGroupSizeDispatchComputeShaderRenderer.cs

    +

    Dispatch[numthreads(16, 16, 1)]

    +

    ShaderDesc.ThreadGroupSizeDispatchComputeShaderRenderer.cs

    diff --git a/documents/learn/concepts/synchronization.md b/documents/learn/concepts/synchronization.md index 244ce691..1d845064 100644 --- a/documents/learn/concepts/synchronization.md +++ b/documents/learn/concepts/synchronization.md @@ -17,19 +17,19 @@ title: '@concepts.synchronization.title' -CommandBuffer.Barrier +CommandBuffer.Barrier -CommandBuffer.Transition +CommandBuffer.Transition -TimelineValueSubmit +TimelineValueSubmit -Wait() +Wait() @@ -44,24 +44,24 @@ commandBuffer.Barrier(BarrierStages.ComputeShading, BarrierStages.ComputeShading

    -

    BarrierStages.All

    +

    BarrierStages.All

    -

    TextureLayoutStorage

    +

    TextureLayoutStorage

    ```csharp commandBuffer.Transition(outputTexture, default, TextureLayout.Storage, TextureLayout.Sampled); ``` -

    outputTextureSampled | StorageStoragedefault

    -

    Transition

    -

    Undefined

    +

    outputTextureSampled | StorageStoragedefault

    +

    Transition

    +

    Undefined

    -

    TransitionBarrier

    +

    TransitionBarrier

    -

    Submit()TimelineValueValue

    +

    Submit()TimelineValueValue

    producerconsumer

    ```csharp @@ -70,19 +70,19 @@ TimelineValue produced = producer.Submit(); TimelineValue consumed = consumer.Submit(produced); ``` -

    produced.Wait()consumed

    +

    produced.Wait()consumed

    ```csharp consumed.Wait(); ``` -

    Wait()queue.Timeline.Signal()Signal()

    +

    Wait()queue.Timeline.Signal()Signal()

    -

    IsCompleted

    -

    CommandBuffer.DownloadWait()

    -

    IsCompleted

    +

    IsCompleted

    +

    CommandBuffer.DownloadWait()

    +

    IsCompleted

    -

    SwapChain.Resize

    -

    SwapChain.Present()

    +

    SwapChain.Resize

    +

    SwapChain.Present()

    diff --git a/documents/learn/first-triangle.md b/documents/learn/first-triangle.md index 0ca319ac..0c288142 100644 --- a/documents/learn/first-triangle.md +++ b/documents/learn/first-triangle.md @@ -61,12 +61,12 @@ dotnet add package Silk.NET.Windowing

    AllowUnsafeBlocks

    3.

    -

    CocoaHelper.cs

    +

    CocoaHelper.csusing System.Runtime.InteropServices;

    Program.csMain

    ```csharp -global using System.Runtime.InteropServices; using System.Numerics; +using System.Runtime.InteropServices; using Silk.NET.Windowing; using Zenith.NET; using Zenith.NET.DirectX12; @@ -90,12 +90,12 @@ window.Dispose(); ```

    GraphicsAPI.NoneInitialize()Center()Run()Dispose()

    -

    using ZenithTutorialsBufferSystem.Buffer

    +

    using ZenithTutorialsBufferSystem.Buffer

    dotnet run

    4.

    -

    GraphicsContext

    +

    GraphicsContext

    IWindow window

    ```csharp @@ -116,7 +116,7 @@ else context.ValidationMessage += static (_, args) => Console.WriteLine($"[{args.Severity}] {args.Message}"); ``` -

    ValidationMessage

    +

    ValidationMessage

    window.Center()window.Run()

    @@ -139,7 +139,7 @@ else } ``` -

    SurfaceFramebufferSize

    +

    SurfaceFramebufferSize

    @@ -152,8 +152,8 @@ SwapChain swapChain = context.CreateSwapChain(new() }); ``` -

    SwapChainDrawableTexturePresent()

    -

    B8G8R8A8UNormUNormswapChain.Desc.Format

    +

    SwapChainDrawableTexturePresent()

    +

    B8G8R8A8UNormUNormswapChain.Desc.Format

    window.Dispose();Program.cs

    ```csharp @@ -195,14 +195,14 @@ window.Render += _ => ```

    -

    GraphicsQueue.CommandBuffer()

    -

    TransitiondefaultUndefined

    +

    GraphicsQueue.CommandBuffer()

    +

    TransitiondefaultUndefined

    -

    ColorAttachment.ClearBeginRenderPass

    +

    ColorAttachment.ClearBeginRenderPass

    null

    -

    BeginRenderPass

    -

    EndRenderPassSubmit()Wait()Present()

    +

    BeginRenderPass

    +

    EndRenderPassSubmit()Wait()Present()

    FramebufferResizewindow.Run();

    @@ -222,7 +222,7 @@ window.FramebufferResize += _ => ```

    -

    Present()

    +

    Present()

    dotnet run

    6.

    @@ -256,7 +256,7 @@ Vertex[] vertices =

    VertexnewVector3Vector4w = 1

    -

    Buffer

    +

    Buffer

    ```csharp Buffer vertexBuffer; @@ -282,10 +282,10 @@ unsafe } ``` -

    sizeof(Vertex) * vertices.LengthBufferUsages.VertexCpuWriteOnly

    -

    Upload

    -

    fixedUpload

    -

    vertexBuffer.Dispose();swapChain.Dispose();Program.cs

    +

    sizeof(Vertex) * vertices.LengthBufferUsages.VertexCpuWriteOnly

    +

    Upload

    +

    fixedUpload

    +

    vertexBuffer.Dispose();swapChain.Dispose();Program.cs

    7.

    @@ -349,7 +349,7 @@ Shader vertexShader = context.CreateShader(ZenithCompiler.CompileFromFile(contex Shader fragmentShader = context.CreateShader(ZenithCompiler.CompileFromFile(context.GraphicsApi, shaderPath, "FSMain")); ``` -

    ZenithCompilerCreateShadercontext.GraphicsApiVSMainFSMain

    +

    ZenithCompilerCreateShadercontext.GraphicsApiVSMainFSMain

    AppContext.BaseDirectory

    8.

    @@ -361,7 +361,7 @@ inputLayout.Add(new() { Format = ElementFormat.Float3, Semantic = ElementSemanti inputLayout.Add(new() { Format = ElementFormat.Float4, Semantic = ElementSemantic.Color }); ``` -

    InputLayout.Add

    +

    InputLayout.Add

    @@ -375,13 +375,13 @@ inputLayout.Add(new() { Format = ElementFormat.Float4, Semantic = ElementSemanti - + - + @@ -392,17 +392,17 @@ inputLayout.Add(new() { Format = ElementFormat.Float4, Semantic = ElementSemanti
    Vertex.Position 0Float3Float3 POSITION0
    Vertex.Color 12Float4Float4 COLOR0
    -

    SemanticIndexPOSITION0COLOR0

    +

    SemanticIndexPOSITION0COLOR0

    9.

    -

    GraphicsPipeline

    +

    GraphicsPipeline

    @@ -430,11 +430,11 @@ vertexShader.Dispose(); fragmentShader.Dispose(); ``` -

    InputLayouts

    -

    pipeline.Dispose();vertexBuffer.Dispose();

    +

    InputLayouts

    +

    pipeline.Dispose();vertexBuffer.Dispose();

    10.

    -

    window.Render// Add the triangle draw commands here later.BeginRenderPassEndRenderPass

    +

    window.Render// Add the triangle draw commands here later.BeginRenderPassEndRenderPass

    ```csharp commandBuffer.SetPipeline(pipeline); @@ -443,9 +443,9 @@ commandBuffer.SetVertexBuffer(vertexBuffer, 0, 0); commandBuffer.Draw(3, 1, 0, 0); ``` -

    SetPipeline

    -

    SetVertexBuffer(vertexBuffer, 0, 0)InputLayouts

    -

    Draw

    +

    SetPipeline

    +

    SetVertexBuffer(vertexBuffer, 0, 0)InputLayouts

    +

    Draw

    @@ -477,7 +477,7 @@ commandBuffer.Draw(3, 1, 0, 0);
    -

    Submit().Wait()Present()

    +

    Submit().Wait()Present()

    11.

    FirstTriangle

    @@ -517,7 +517,7 @@ window.Dispose(); context.Dispose(); ``` -

    Dispose()

    +

    Dispose()

    diff --git a/documents/learn/samples.md b/documents/learn/samples.md index 476595d0..a5eb613b 100644 --- a/documents/learn/samples.md +++ b/documents/learn/samples.md @@ -21,7 +21,7 @@ dotnet run --project ZenithTutorials/ZenithTutorials.csproj

    HelloTriangleRenderer.csHelloTriangle.slang

    -

    D32FloatS8UInt

    +

    D32FloatS8UInt

    SpinningCubeRenderer.csSpinningCube.slang

    Assets/Textures/shoko.png

    @@ -30,10 +30,10 @@ dotnet run --project ZenithTutorials/ZenithTutorials.csproj

    IndirectDrawingRenderer.csIndirectDrawing.slang

    -

    context.Capabilities.RayTracingSupported

    +

    context.Capabilities.RayTracingSupported

    RayTracingRenderer.csRayTracing.slang

    -

    context.Capabilities.MeshShadingSupported

    +

    context.Capabilities.MeshShadingSupported

    MeshShadingRenderer.csMeshShading.slang

    App.csIRenderer.cs

    diff --git a/documents/locales/en-US/strings.yml b/documents/locales/en-US/strings.yml index 048865bf..8e4cc3d0 100644 --- a/documents/locales/en-US/strings.yml +++ b/documents/locales/en-US/strings.yml @@ -9,19 +9,18 @@ concepts.execution.context.details: Choose the backend for the platform and pres concepts.execution.context.details.detail: mesh shading concepts.execution.context.details.link: ray tracing concepts.execution.context.title: The context connects resources and queues -concepts.execution.description: A Zenith.NET application creates GPU resources, such as buffers and textures, records - commands that use them, and submits those commands to a queue. The CPU can continue while the GPU executes the - submission. Understanding where that boundary lies tells you when data may be changed and when resources may be - released. +concepts.execution.description: A Zenith.NET application creates GPU resources, records commands that use them, + and submits those commands to a queue. The CPU can continue while the GPU executes the submission. Keep resources + valid until that work finishes, even after the recording calls have returned. concepts.execution.ownership.description: Here, ownership means responsibility for disposal. A C# reference keeps a managed object reachable; it does not prevent an explicit {dispose} from destroying the native resource. Likewise, submitting a command that uses a buffer does not transfer ownership of that buffer to the queue. concepts.execution.ownership.details: On shutdown, stop submitting new work, wait for the last uses on every queue involved, release the application's resources, then dispose the context. Context disposal releases its own queues and internal helpers; it does not wait for all application work or dispose every resource the application created. -concepts.execution.ownership.guidance: The same rule applies during normal rendering. A completion value can tell - you when a frame's buffer is safe to overwrite or a resized texture is safe to replace. Resource lifetime is covered - further in {link}. +concepts.execution.ownership.guidance: Apply the same lifetime rules during rendering. Retain the completion value + for a resource's last use so you know when its bytes can be overwritten or the resource can be replaced. See + {link} for views and backing-resource lifetimes. concepts.execution.ownership.guidance.link: Resource Management concepts.execution.ownership.table.applicationResources.object: Resources created by the application concepts.execution.ownership.table.applicationResources.ownership: The application disposes them after their last @@ -49,10 +48,9 @@ concepts.execution.pipelines.guidance.link: triangle's render callback concepts.execution.pipelines.title: A pipeline determines how commands interpret data concepts.execution.queues.description: Start with {graphicsQueue} when a frame combines drawing, compute and copies. Keeping dependent work on one queue makes its ordering easier to follow. -concepts.execution.queues.details: A queue accepts batches of recorded commands for execution. It does not necessarily - correspond to a dedicated hardware engine. Separate queue properties do not guarantee that their work runs simultaneously. - Use another queue when there is useful work to overlap, and make the handoff explicit when it shares resources - with the first queue. +concepts.execution.queues.details: A queue accepts batches of commands for execution. Separate queues do not necessarily + correspond to separate hardware engines, so their work may not run simultaneously. Use another queue when the + workload can benefit from overlap, and add an explicit dependency when one queue consumes another queue's results. concepts.execution.queues.guidance: When later commands depend on earlier writes, the application must also ensure that those writes are available to the later commands. Submitting both command buffers to the same queue does not establish every such dependency automatically. Commands can use different GPU stages, and later accesses may @@ -81,10 +79,10 @@ concepts.execution.recording.guidance: '{submit} schedules the work; {wait} keep operations. Neither recording the draw nor ending the pass waits for the GPU.' concepts.execution.recording.title: Recording does not execute commands concepts.execution.title: Execution Model -concepts.platforms.description: A renderer can present directly into a native window or draw through a UI framework's - control. The host is the application code or UI framework responsible for displaying frames. It determines who - manages the drawable—the texture rendered into for the current frame—as well as submission, presentation and resize. - Offscreen graphics and compute work do not require a window or swap chain. +concepts.platforms.description: Choose whether your application owns the native window and frame loop or uses + a UI rendering control. That choice determines who obtains the drawable, submits commands and presents the result. + The drawable is the texture used as the current frame's output. Offscreen graphics and compute work do not need + a window or swap chain. concepts.platforms.frame.context: Add your pipeline bindings and draw commands inside that pass. End the pass before returning. Do not submit the supplied command buffer or present independently, and do not dispose the command buffer or drawable. If your handler uses the drawable in another layout, return it to {colorAttachment} for the @@ -108,10 +106,9 @@ concepts.platforms.integration.context: WinForms, WPF and the Windows WinUI path Framework support and backend support must both be satisfied. concepts.platforms.integration.description: 'The controls share the event interface, but they do not all present in the same way:' -concepts.platforms.integration.details: Bitmap readback copies rendered pixels from GPU storage into CPU memory - before the UI displays them. Shared-texture interop avoids that pixel readback path but can still perform GPU - copies and synchronization. Do not assume a shared {renderRequested} interface implies the same presentation cost - or native interop requirements. +concepts.platforms.integration.details: Bitmap readback copies rendered pixels into CPU memory before the UI displays + them. Shared-texture interop avoids that readback but may still require GPU copies and synchronization. The + shared {renderRequested} interface therefore does not imply identical presentation costs or native interop requirements. concepts.platforms.integration.guidance: 'Use the package for the application''s framework; for example:' concepts.platforms.integration.table.avalonia.integration: Avalonia concepts.platforms.integration.table.avalonia.presentation: Renders to a texture and downloads pixels into a {writeableBitmap}. @@ -151,9 +148,9 @@ concepts.platforms.lifecycle.guidance: Recreate application-owned depth or offsc concepts.platforms.lifecycle.guidance.link: spinning cube renderer concepts.platforms.lifecycle.title: Keep the drawable's size and lifetime with its host concepts.platforms.ownership.description: The application owns the context it assigns and the resources it creates - for rendering. The control owns its own presentation resources. Changing {graphicsContext} makes the scheduler - recreate the control's resources; it does not recreate the application's pipelines, buffers or textures for the - new context. + for rendering. The control owns its own presentation resources. Changing the view's {graphicsContext} property + makes the scheduler recreate the control's resources; it does not recreate the application's pipelines, buffers + or textures for the new context. concepts.platforms.ownership.details: Coordinate resource replacement with the view's frame lifecycle. Stop the view's frame activity and finish outstanding GPU uses before disposing application resources or the assigned context. Removing a view does not transfer context ownership to the control. @@ -223,8 +220,8 @@ concepts.resources.memory.details: Residency describes the intended CPU access t that every device has separate physical CPU and GPU memory. The triangle uses {cpuWriteOnly} to initialize a small vertex buffer directly. A large static mesh may instead benefit from GPU-only storage with a one-time upload. concepts.resources.memory.guidance: '{textureDesc} has no residency field. Ordinary context-created textures use - GPU storage in the backends; the public texture API provides upload and download operations rather than a {map} - method. Explicit heaps provide placement control, described below.' + GPU storage. Their public API provides upload and download operations for CPU data transfers, without exposing + a direct mapping method. Explicit heaps provide placement control, described below.' concepts.resources.memory.table.cpuReadOnly.cPUAccess: Read mapped memory after the GPU copy finishes. concepts.resources.memory.table.cpuReadOnly.typicalRole: Readback data produced by the GPU concepts.resources.memory.table.cpuWriteOnly.cPUAccess: Write mapped memory after previous GPU readers finish. @@ -235,8 +232,8 @@ concepts.resources.memory.table.headings.cPUAccess: CPU access concepts.resources.memory.table.headings.residency: Residency concepts.resources.memory.table.headings.typicalRole: Typical role concepts.resources.memory.title: Choose memory for the CPU access you need -concepts.resources.textureUsages.description: '{transferSrc} and {transferDst} describe the direction of GPU copies. - CPU access is a separate memory-placement choice, described below.' +concepts.resources.textureUsages.description: Transfer usage flags describe the direction of GPU copies. CPU access + is a separate memory-placement choice, described below. concepts.resources.textureUsages.details: Combining usage flags declares several roles; it does not perform the operations or order their accesses. Textures still need the appropriate {link}, and their formats must support the requested uses on the selected device. @@ -306,11 +303,10 @@ concepts.shaders.binding.description: '{setConstantBuffer} binds a buffer and by ensure earlier GPU readers have finished before overwriting its bytes.' concepts.shaders.binding.details: 'Set the pipeline before its constant buffer. For a compute workload with resources already created and uploaded, recording uses this order:' -concepts.shaders.binding.guidance: This fragment assumes an already-recording {commandBuffer}, a {computePipeline}, - an uploaded {constantBuffer} with {bufferUsagesConstant}, and the thread-group counts for the workload. Offset - 0 binds the beginning of the buffer. If several constant-data records share a buffer, each record's starting offset - must satisfy the backend's binding alignment. That requirement is separate from the layout of fields inside each - record. +concepts.shaders.binding.guidance: This fragment assumes a recording {commandBuffer}, a {computePipeline}, an + uploaded {constantBuffer} with {bufferUsagesConstant} usage, and the thread-group counts for the workload. Offset + 0 binds the start of the buffer. If several constant-data records share one buffer, each record's starting offset + must meet the backend's binding alignment. That requirement is separate from the field layout inside the record. concepts.shaders.binding.notes: '{resourceHandle} stores two 32-bit fields, but its interpretation belongs to the backend. Do not treat it as a universal descriptor index, address or value that can be transferred between contexts. A handle does not create a resource, add a missing usage or perform synchronization.' @@ -333,9 +329,9 @@ concepts.shaders.compilation.description: '{zenithCompiler} compiles a named Sla 12, a Metal library for Metal, or SPIR-V for Vulkan.' concepts.shaders.compilation.details: 'For example, with an existing {context} and the triangle''s shader copied beside the executable:' -concepts.shaders.compilation.guidance: '{vSMain} must match the entry-point name in the file. Create the pipeline - while its shader objects are valid; they can be disposed after pipeline creation, as shown in {link}. Compile - shaders and create pipelines during initialization rather than repeating that work for every frame.' +concepts.shaders.compilation.guidance: '{vSMain} must exactly match the entry-point name in the shader file. Keep + shader objects valid while creating the pipeline, then dispose them after pipeline creation, as shown in {link}. + Perform this initialization once rather than recompiling for every frame.' concepts.shaders.compilation.guidance.link: First Triangle concepts.shaders.compilation.title: Compile an entry point for the selected context concepts.shaders.description: 'A shader receives data supplied by the application. Vertex attributes describe individual @@ -430,11 +426,10 @@ concepts.synchronization.dependencies.table.pipelineStages.mechanism: '{commandB and consuming stages.' concepts.synchronization.dependencies.table.pipelineStages.situation: Dependent GPU stages in a command stream concepts.synchronization.dependencies.title: Start with the producer and the consumer -concepts.synchronization.description: 'When one operation uses data written by another, the later operation must - wait for the writes it depends on and be able to read their results. This is a data dependency: the operation - writing the data is the producer, and the operation using it is the consumer. The CPU also needs to know when - it can read, overwrite or release that data. Zenith.NET exposes command barriers, texture transitions and queue - timelines for these different dependencies.' +concepts.synchronization.description: A command that reads data written by an earlier command depends on those + writes being finished and visible to it. The writer is the producer; the reader is the consumer. The CPU also + needs a completion point before reading, overwriting or releasing shared data. Zenith.NET provides barriers, + texture transitions and timelines for these different dependencies. concepts.synchronization.layouts.context: '{undefined} means the previous contents need not be preserved. It is suitable for a new image or an attachment that will be fully cleared. It is not a way to avoid tracking the layout of an image whose contents will be loaded, sampled or accumulated into.' @@ -481,9 +476,9 @@ concepts.synchronization.timelines.description: A timeline tracks completion on values from different timelines are not comparable just by their numeric {value} fields. concepts.synchronization.timelines.details: 'Suppose {producer} and {consumer} are already-recorded command buffers from two queues of the same context. The producer writes data that the consumer uses. Submit them like this:' -concepts.synchronization.timelines.guidance: The supplied value becomes a GPU-side queue wait before the consuming - work. The CPU does not call {producedWait} in this sequence. Keep the shared resources valid until {consumed} - has completed, and still record any texture layout changes required by the consumer. +concepts.synchronization.timelines.guidance: Passing the produced value makes the consuming queue wait for it + on the GPU. The CPU does not call {producedWait} here. Keep the shared resources valid until {consumed} completes, + and record any texture layout changes required by the consumer. concepts.synchronization.timelines.notes: '{wait} waits for that timeline value and then checks its owning queue for completed submissions. Finished command buffers are reset for reuse, and their staged downloads are copied into the supplied CPU destinations. {queueTimelineSignal} can also enqueue a completion point after work already @@ -525,8 +520,8 @@ learning.concepts.resources.description: Choose resource usages, memory placemen learning.concepts.shaders.description: Match C# layouts and resource handles to Slang. learning.concepts.synchronization.description: Order dependent accesses and know when work completes. learning.concepts.title: Core concepts -learning.description: Build your first frame, then use the samples and concepts to add rendering and compute work - to your application. +learning.description: Start with a complete triangle tutorial. Then use the focused samples and concept guides + to understand the resources, data and dependencies behind a larger renderer. learning.entries.samples.action: Browse samples learning.entries.samples.description: Find C# and Slang examples for geometry, compute, ray queries, and mesh shading. learning.entries.tutorial.action: Open tutorial @@ -552,13 +547,13 @@ samples.cube.description: Adds indexed drawing, model, view and projection matri object; the renderer uses a {d32FloatS8UInt} depth/stencil attachment. samples.cube.details: '{spinningCubeRendererCs} · {spinningCubeSlang}' samples.cube.title: Spinning Cube -samples.description: Use these examples to see how a particular rendering or compute workload fits together. The - focused examples link to both the C# code that creates resources and records commands and the Slang code executed - by the GPU. For a step-by-step application from an empty project, start with {link}. +samples.description: Choose a focused example for the feature you want to study. Each example links to the C# + renderer and its Slang shader. Start with {link} if you want a complete application explained from an empty + project. samples.description.link: First Triangle -samples.execution.description: '{link} contains six independent renderers in one desktop application. Use the .NET - 10 SDK and a supported desktop backend as described below. Build and run the application, then select a sample - from the console menu:' +samples.execution.description: '{link} contains six independent renderers in one desktop application. Use the + .NET 10 SDK and a supported desktop backend, as described below. Build and run the application, then choose + an example from the console menu:' samples.execution.description.link: ZenithTutorials samples.execution.details: The host selects DirectX 12 on Windows, Metal on macOS and Vulkan on Linux. Use a device, driver and shader compiler environment supported by the selected backend. The Linux window path requires X11 or @@ -621,21 +616,21 @@ samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: Attempt and reports device capabilities. A context-creation failure is reported as unsupported; that result can also indicate a missing driver or runtime dependency. samples.workloads.title: Explore larger workloads -tutorial.context.description: The window is ready, but it has no connection to a GPU yet. A {graphicsContext} provides - that connection and the queues that accept recorded commands for execution on the GPU. +tutorial.context.description: The window can now open, but we have not created the GPU objects that will render + into it. A {graphicsContext} provides access to the selected graphics backend and its command queues. tutorial.context.details: 'Insert this block {emphasis}:' tutorial.context.details.emphasis: after the using directives, before {iWindowWindow} -tutorial.context.guidance: For the three desktop platforms covered here, this chooses DirectX 12 on Windows, Metal - on macOS and Vulkan on Linux. The operations after initialization use the same Zenith.NET API. We request validation - during development and print diagnostics reported through {validationMessage}. The available diagnostics depend - on the backend and installed validation components. +tutorial.context.guidance: The branches select DirectX 12 on Windows, Metal on macOS and Vulkan on Linux. The + rendering code that follows uses the shared Zenith.NET API. We request validation during development and print + messages reported through {validationMessage}. Diagnostics depend on the backend and the validation components + available on the machine. tutorial.context.title: Create the graphics context -tutorial.description: In this tutorial, you will build a .NET console application that opens a window and draws - a triangle with a smooth color gradient between its corners. You will create the resources it needs, describe - how the GPU reads them, and record the commands that turn three vertices into a displayed image. -tutorial.details: The application has two parts. Initialization creates the window and the resources needed to draw. - The frame loop records drawing commands and presents the result repeatedly. Resources that stay the same between - frames are created once, before that loop. +tutorial.description: Build a .NET console application that opens a window and draws a triangle with a smooth + color gradient. You will learn how vertex data, shaders and pipeline state work together, then record and submit + the commands that produce the image. +tutorial.details: Work through the sections in order. You will first open an empty window, then display a background + color, and finally draw the triangle. Each checkpoint confirms one part of the application before you add the + next. Initialization runs once; the render callback records a new frame each time it is called. tutorial.draw.context: 'The arguments to {draw} are:' tutorial.draw.description: 'In the {windowRender} callback, replace {addTheTriangleDrawCommandsHereLater} with these three commands, between {beginRenderPass} and {endRenderPass}:' @@ -677,8 +672,9 @@ tutorial.frame.commands.guidance: '{beginRenderPass} sets a viewport and scissor maps the rendered coordinates to pixels, and the scissor limits which pixels can be written. These defaults cover the whole drawable, which is what this triangle needs.' tutorial.frame.commands.title: Clear, submit and present -tutorial.frame.description: Start by filling the image with one background color, an operation called a clear. Seeing - that color confirms that the context, surface, command submission and swap chain work together before we add geometry. +tutorial.frame.description: First fill the image with one background color. This operation is called a clear. + If that color appears in the window, the surface, command submission and presentation path are working together. + This checkpoint lets you verify the frame loop before adding geometry and shaders. tutorial.frame.details: 'A render callback is code that Silk.NET calls when it is time to draw a frame. This callback does not need the event''s elapsed-time argument, so it is named {value}. Register it {emphasis}:' tutorial.frame.details.emphasis: before {windowRun} @@ -695,11 +691,11 @@ tutorial.frame.title: Display a background color tutorial.geometry.data.description: Add this array {emphasis}. The following resource-creation steps also belong before that callback, in the order shown. tutorial.geometry.data.description.emphasis: before {windowRender} -tutorial.geometry.data.details: Each array entry creates a {vertex}; the two inner {new} expressions create its - {vector3} position and {vector4} color. These are the top, lower-right and lower-left corners. The vertex shader - will give each position a fourth coordinate, {w}, so x and y directly correspond to normalized device coordinates. - -1 and +1 are the image edges, and 0 is the center. The coordinates do not depend on the number of pixels in the - window. +tutorial.geometry.data.details: 'Each array entry creates a {vertex}. The two inner {new} expressions create its + {vector3} position and {vector4} color. The vertices describe the top, lower-right and lower-left corners. The + vertex shader will supply a fourth position coordinate, {w}. With w equal to 1, x and y directly describe normalized + device coordinates: -1 and +1 are the image edges, and 0 is the center. These coordinates do not depend on the + window''s pixel dimensions.' tutorial.geometry.data.guidance: Each color contains red, green, blue and alpha components. Alpha is 1 at all three corners. All three positions have z = 0, placing them in the same plane. These positions need no camera or transformation matrix because they already describe the coordinates we want to render. For this single flat triangle, we will @@ -733,10 +729,10 @@ tutorial.geometry.upload.notes: Add {vertexBufferDispose} immediately before {sw uploads instead. tutorial.geometry.upload.notes.link: Resource Management tutorial.geometry.upload.title: Allocate a buffer and upload the array -tutorial.input.description: 'The GPU now has the bytes and shader code, but it still needs to know how to interpret - each vertex. An attribute is one value carried by a vertex, such as its position or color. The layout identifies - each attribute''s format and byte offset, and the stride is the distance in bytes from one vertex to the next. - Add the following initialization block after shader creation:' +tutorial.input.description: 'The vertex bytes and shaders are ready. Next, describe how the GPU should read each + vertex. An attribute is one value, such as position or color. The input layout gives each attribute a format + and byte offset; the stride gives the distance in bytes from one vertex to the next. Add this initialization + block after shader creation:' tutorial.input.details: '{inputLayoutAdd} appends an element at the current stride and increases that stride by the element''s size. It does not inspect the C# struct. Here it produces the following agreement between CPU memory and shader inputs:' @@ -895,9 +891,9 @@ tutorial.swapChain.title: Create the swap chain tutorial.title: First Triangle tutorial.troubleshooting.description: 'Read any error in the console first, then use the earlier checkpoints to identify the stage that failed:' -tutorial.troubleshooting.details: For comparison, the {link} and {detail} use the same vertex data, input layout - and draw. The sample factors windowing and submission into its shared host; on this page, you have assembled those - parts in {programCs} as well. Continue with {context} for indexed geometry, transformations and depth testing. +tutorial.troubleshooting.details: Use the {link} and {detail} to compare the vertex data, input layout and draw + operation. That sample places windowing and submission in a shared host; this tutorial keeps the application + flow in {programCs}. Continue with {context} to learn indexed drawing, transformations and depth testing. tutorial.troubleshooting.details.context: Spinning Cube tutorial.troubleshooting.details.detail: Slang shader tutorial.troubleshooting.details.link: sample renderer @@ -918,10 +914,12 @@ tutorial.troubleshooting.table.window.check: Confirm the .NET project builds and desktop session. On Linux, check that X11 or XWayland is available. tutorial.troubleshooting.table.window.symptom: No window opens tutorial.troubleshooting.title: Check the stage that failed -tutorial.window.context: '{usingZenithTutorials} imports the helper''s namespace. The global using supplies its - interop attributes, and the {buffer} alias distinguishes Zenith.NET''s GPU buffer from {systemBuffer}.' -tutorial.window.description: Add {cocoaHelperCs} to the project. It handles the Metal layer on macOS; the program - calls it only on that platform. +tutorial.window.context: '{usingZenithTutorials} imports the helper''s namespace. Each C# file uses its own ordinary + using directives, so the interop import is needed in both files. The {buffer} alias refers to the Zenith.NET + buffer type and distinguishes it from {systemBuffer}.' +tutorial.window.description: Add {cocoaHelperCs} to the project, keeping its namespace. Add {interopUsing} at + the top of that file, before its namespace declaration. The helper attaches a Metal layer to the window on macOS; + the other platform branches do not call it. tutorial.window.details: 'Replace the generated {programCs} with the following code. It uses top-level statements, which execute in order without an explicit {main} method. Later sections will tell you where to add code to this same file:' @@ -984,7 +982,7 @@ ui.reference.examples: Examples ui.reference.exceptions: Exceptions ui.reference.extensionMethods: Extension methods ui.reference.fields: Fields -ui.reference.implementations: Explicit implementations +ui.reference.implementations: Explicit interface implementations ui.reference.implements: Implements ui.reference.inheritance: Inheritance ui.reference.inheritedMembers: Inherited members @@ -992,7 +990,7 @@ ui.reference.interfaces: Interfaces ui.reference.metadata: Type metadata ui.reference.methods: Methods ui.reference.namespace: Namespace -ui.reference.open: Open {name} reference +ui.reference.open: Open reference for {name} ui.reference.operators: Operators ui.reference.parameters: Parameters ui.reference.properties: Properties @@ -1006,7 +1004,7 @@ ui.reference.value: Value ui.reference.values: Values ui.search.close: Close search ui.search.empty: No results for “{query}”. -ui.search.hint: Search the docs, concepts, and API. +ui.search.hint: Search tutorials, concepts, samples, and the API reference. ui.search.loading: Loading search… ui.search.more: Show more results ui.search.pending: Searching… From 42bf6b62a8d4844764b6a132c50ab1726edebaa3 Mon Sep 17 00:00:00 2001 From: qian-o <1324771795@qq.com> Date: Mon, 21 Sep 2026 01:44:35 +0800 Subject: [PATCH 17/35] Update translations for Korean, Portuguese, Russian, Simplified Chinese, and Traditional Chinese - Revised resource and structure guidelines to clarify the use of the English resource dictionary as the sole source for translations. - Enhanced instructions on maintaining consistency in key names and values across translations. - Added detailed sections on text and placeholders, emphasizing the importance of preserving context and technical accuracy in translations. - Updated API link and technical meaning sections to ensure clarity in distinguishing between different concepts and terms. - Improved build and review instructions to streamline the translation process and ensure quality control before submission. - Adjusted terminology tables to reflect more precise translations and definitions for technical terms. --- documents/locales/de-DE/translation.md | 48 ++++++++++++++++++++++---- documents/locales/es-ES/translation.md | 48 ++++++++++++++++++++++---- documents/locales/fr-FR/translation.md | 48 ++++++++++++++++++++++---- documents/locales/ja-JP/translation.md | 48 ++++++++++++++++++++++---- documents/locales/ko-KR/translation.md | 48 ++++++++++++++++++++++---- documents/locales/pt-BR/translation.md | 48 ++++++++++++++++++++++---- documents/locales/ru-RU/translation.md | 48 ++++++++++++++++++++++---- documents/locales/zh-CN/translation.md | 46 +++++++++++++++++++++--- documents/locales/zh-TW/translation.md | 46 +++++++++++++++++++++--- 9 files changed, 376 insertions(+), 52 deletions(-) diff --git a/documents/locales/de-DE/translation.md b/documents/locales/de-DE/translation.md index 8a4a2a7f..a0d8b60a 100644 --- a/documents/locales/de-DE/translation.md +++ b/documents/locales/de-DE/translation.md @@ -2,21 +2,57 @@ ## Ressourcen und Aufbau -Englisch ist die einzige Ausgangssprache. Übersetzungen übernehmen ausschließlich die Schlüssel und Werte aus `locales/en-US/strings.yml` in die eigene `strings.yml`. Bis zur Übersetzung bleibt hier nur diese dauerhafte `translation.md`; sie wird nicht veröffentlicht. Die erste Zeile `### YamlMime:Resources` beibehalten. +Das [englische Ressourcenwörterbuch](../en-US/strings.yml) ist die einzige Textquelle. Die Projektregeln stehen im [Leitfaden zur Dokumentationspflege](../../authoring.md). Für eine neue Übersetzung die vollständige englische Datei als `strings.yml` in dieses Verzeichnis kopieren. Die erste Zeile `### YamlMime:Resources` und die UTF-8-Kodierung beibehalten. Spätere Änderungen mit dem englischen Stand abgleichen, ohne vorhandene Übersetzungen zu überschreiben. Diese `translation.md` bleibt dauerhaft erhalten und wird nicht auf der Website veröffentlicht. -Navigation, Kapitelreihenfolge, Anker, Links, Formatierung, Code und Bilder liegen außerhalb von `locales/` und werden gemeinsam genutzt. Keine Artikel, TOCs, Vorlagen, Skripte oder Konfigurationen in diesem Verzeichnis anlegen. +Navigation, Kapitelreihenfolge, Anker, Links, Formatierung, Code und Bilder werden außerhalb von `locales/` gemeinsam gepflegt. Hier keine Artikel, TOCs, Vorlagen, Skripte oder Konfigurationen anlegen. -Schlüsselnamen beschreiben beständige Aufgaben und Begriffe. Sie bleiben bei redaktionellen Änderungen unverändert; weder Formulierung noch Position, Nummerierung oder Sprache in neue Namen aufnehmen. Nur die englischen Werte in natürliches, sachliches Deutsch übersetzen. +Bei der Übersetzung nur die Werte der eigenen `strings.yml` ändern. Die Schlüsselmenge muss exakt der englischen entsprechen. Keine Schlüssel eigenständig hinzufügen, löschen oder umbenennen, auch nicht bei ähnlich lautenden oder noch nicht gesehenen Oberflächentexten. Fehler im Original mit dem betroffenen Schlüssel an die Projektverantwortlichen melden. Zuerst die englische Quelle und die gemeinsamen Seiten berichtigen, dann die Übersetzungen nachziehen. -Werte sind Text, kein HTML oder Markdown. Benannte Platzhalter wie `{context}` oder `{link}` binden gemeinsame Code- und Linkelemente ein. Ihre Reihenfolge darf sich ändern; Namen müssen vollständig erhalten bleiben. Keine Platzhalter hinzufügen oder entfernen. Alle englischen Schlüssel müssen vorhanden sein; fehlende Schlüssel oder abweichende Platzhalter lassen den Build fehlschlagen. +## Texte und Platzhalter -Die bisherigen DocFX-Befehle genügen. Nach dem Hinzufügen der vollständigen Wörterbuchdatei wird die Sprache automatisch verfügbar. Alle Sprachen verwenden dieselben Seitenpfade; `?lang=de-DE` wählt die Sprache. Sprachlisten bleiben nach Verzeichniscode sortiert. +Ganze Sätze oder Absätze in natürliches, sachliches Deutsch übersetzen. Voraussetzungen, Verneinungen, Einheiten, Handlungsschritte und Lebensdauerbedingungen erhalten. Keine zusätzlichen technischen Zusagen, Plattformanforderungen, Paketversionen oder Versionshinweise einführen. Produkt- und Paketnamen, Dateinamen sowie C#- und Slang-Bezeichner einschließlich Groß- und Kleinschreibung unverändert lassen. + +Jeder Wert muss eine nicht leere Zeichenfolge mit reinem Text sein, ohne HTML oder Markdown. YAML-Anführungszeichen und Escape-Sequenzen beachten; bei Doppelpunkten, Rauten oder zahlenähnlichen Werten nötigenfalls Anführungszeichen setzen. Die englische Schlüsselreihenfolge für die Prüfung beibehalten. + +Benannte Platzhalter wie `{context}` und `{link}` können gemeinsamen Code, Links oder hervorgehobenen Text einfügen. Platzhalter der Oberfläche wie `{name}`, `{query}` und `{count}` können auch zur Laufzeit mit Text gefüllt werden. Die Bedeutung anhand der jeweiligen Verwendung auf der gemeinsamen Seite oder in der Oberfläche prüfen, nicht aus dem Namen erraten. Linkbeschriftungen und hervorgehobene Texte mit eigenen Ressourcenschlüsseln ebenfalls übersetzen. + +Platzhalter dürfen der deutschen Satzstellung folgen. Für jeden Schlüssel müssen jedoch alle Namen, ihre Schreibweise und die geschweiften ASCII-Klammern unverändert erhalten bleiben. Keine Platzhalter hinzufügen, entfernen, umbenennen oder durch angezeigte API-Namen, Linktexte oder Beispielzahlen ersetzen. Keine Schlüssel aufteilen, um Sätze neu zusammenzusetzen. + +## API-Links und technische Bedeutung + +Links gehören zu den gemeinsamen Seiten. Eindeutige Verweise auf lokale API-Bezeichner in Fließtext und Tabellen führen zum jeweiligen Typ oder Member. Variablen, Parameternamen, Beispieltypen, Paket- und Dateinamen sowie externe Symbole ohne lokale Referenzseite bleiben einfacher Codetext. Gleiche Schreibweisen können verschiedene Symbole bezeichnen. Gewöhnliche Codeblöcke des Tutorials erhalten keine automatischen Links. Ganze Platzhalter dürfen verschoben werden; Linkziele, gemeinsamer Code und dessen Formatierung bleiben unverändert. + +Fehlt für eine API ein generierter Referenzeintrag, bleibt ihr Bezeichner auf der gemeinsamen Seite einfacher Codetext mit einem klar bezeichneten Quellcodelink in der Nähe. Keinen anderen Typ oder Member als Linkziel einsetzen. + +Bei der Übersetzung diese Unterschiede erhalten: + +- Befehle aufzeichnen, einreichen, auf der GPU ausführen und abschließen sind unterschiedliche Schritte. +- Ressourcennutzung, Speicherresidenz beziehungsweise vorgesehener CPU-Zugriff, Texturlayout und Pixelformat sind unterschiedliche Begriffe. +- Besitz bezeichnet die Verantwortung für die Freigabe. Ein Handle hält die Ressource nicht automatisch am Leben; das Einreichen von Befehlen überträgt keinen Besitz. +- GPU-Abschluss bedeutet nicht immer, dass zwischengespeicherte Rücklesedaten bereits am CPU-Ziel der Anwendung liegen. Die Hinweise zum Warten auf die zuständige Queue erhalten. +- Ein Drawable ist die Ausgabetextur des aktuellen Frames und nicht zwangsläufig ein Swapchain-Bild. Ressourcenansichten von UI-Steuerelementen unterscheiden. + +## Build und Prüfung vor der Abgabe + +Die Befehle im Stammverzeichnis des Repositorys mit dem vom Projekt benötigten .NET SDK und DocFX ausführen. In einem frischen Checkout fehlen die generierten Metadaten in `documents/api/`. Zuerst den vollständigen Build einschließlich API-Extraktion ausführen: ```sh docfx documents/docfx.json --warningsAsErrors +``` + +Sind die API-Metadaten bereits vorhanden und entsprechen dem aktuellen Quellcode, genügen für reine Wörterbuchänderungen der normale Build und die Vorschau: + +```sh +docfx build documents/docfx.json --warningsAsErrors docfx serve documents/_site --hostname 127.0.0.1 --port 8080 ``` +Deutsch ist bereits registriert. Das vollständige Wörterbuch wird nach einem erfolgreichen Build ohne Konfigurationsänderung verfügbar. Fehlende oder zusätzliche Schlüssel, leere Werte, Werte eines anderen Typs und abweichende Platzhalternamen lassen den Build fehlschlagen. Der Build erkennt weder ungenaue Übersetzungen noch verbliebenen englischen Text; eine redaktionelle Prüfung ist erforderlich. + +Alle Sprachen teilen dieselben Seitenpfade. `?lang=de-DE` wählt Deutsch; beim Sprachwechsel bleiben Pfad und Anker erhalten. Ohne ausdrückliche Auswahl gelten nacheinander die gespeicherte manuelle Auswahl, die Browsersprachen und Englisch. Ist diese Übersetzung noch nicht veröffentlicht oder scheitert das Laden beziehungsweise die Prüfung der Seitenressourcen, bleibt die Seite vollständig auf Englisch, statt einzelne Sätze zu mischen. Die Sprachliste ist nach Sprachcode sortiert. + +Vor der Abgabe Schlüssel und Platzhalter abgleichen. Startseite, Learn-Einstieg, Dreieck-Tutorial, Konzepte, Beispiele und API-Oberfläche auf dem Desktop und bei 320 Pixel Breite prüfen. Das Tutorial aus Sicht eines Einsteigers lesen; Terminologie, Schaltflächen, Suche, Codekopie, API-Links und den Abschnitt nach einem Sprachwechsel kontrollieren. Bezeichner, Deklarationen und Code bleiben gemeinsam; übersetzt werden nur die Texte im Wörterbuch. Testwörterbücher und Prüfdateien außerhalb des Repositorys halten und keine Platzhalterübersetzungen einreichen. + ## Terminologie | Englischer Begriff | Festgelegte Form | @@ -26,7 +62,7 @@ docfx serve documents/_site --hostname 127.0.0.1 --port 8080 | buffer | Puffer; `Buffer` bleibt unverändert | | command buffer | Befehlspuffer | | command queue | Befehlswarteschlange | -| drawable | Aktuelles darstellbares Bild; `Drawable` bleibt unverändert | +| drawable | Ausgabetextur des aktuellen Frames; `Drawable` bleibt unverändert, nicht grundsätzlich als Swapchain-Bild bezeichnen | | graphics context | Grafikkontext | | pipeline | Pipeline | | readback | Rücklesen von GPU-Daten | diff --git a/documents/locales/es-ES/translation.md b/documents/locales/es-ES/translation.md index 856a6c49..65fee19c 100644 --- a/documents/locales/es-ES/translation.md +++ b/documents/locales/es-ES/translation.md @@ -2,21 +2,57 @@ ## Recursos y estructura -El inglés es la única fuente original. Copiar únicamente las claves y valores de `locales/en-US/strings.yml` a la propia `strings.yml`. Hasta empezar la traducción, conservar solo esta `translation.md` permanente, que no se publica. Mantener la primera línea `### YamlMime:Resources`. +El [diccionario de recursos en inglés](../en-US/strings.yml) es la única fuente del texto. Las normas del proyecto están en la [guía de mantenimiento de la documentación](../../authoring.md). Para iniciar una traducción, copie el archivo inglés completo como `strings.yml` en este directorio. Conserve la primera línea `### YamlMime:Resources` y la codificación UTF-8. En futuras revisiones, incorpore los cambios del original sin sobrescribir las traducciones existentes. Este archivo `translation.md` se conserva permanentemente y no se publica en el sitio. -La navegación, el orden de capítulos, las anclas, los enlaces, el formato, el código y las imágenes se comparten fuera de `locales/`. No crear aquí artículos, TOC, plantillas, scripts ni configuraciones. +La navegación, el orden de los capítulos, las anclas, los enlaces, el formato, el código y las imágenes se mantienen fuera de `locales/` y se comparten entre idiomas. No cree aquí artículos, TOC, plantillas, scripts ni configuraciones. -Las claves describen funciones y conceptos estables. No renombrarlas al retocar el texto; evitar nombres ligados a una frase, posición, numeración o idioma. Traducir únicamente los valores ingleses con un español técnico claro y natural. +Modifique únicamente los valores de la propia `strings.yml`. El conjunto de claves debe coincidir exactamente con el inglés. No añada, elimine ni renombre claves por iniciativa propia, aunque parezcan repetidas o correspondan a textos de interfaz que aún no haya visto. Si encuentra un error en el original, comunique la clave y el problema a los responsables del proyecto. Primero se corrigen la fuente inglesa y las páginas compartidas; después, las traducciones. -Los valores son texto, no HTML ni Markdown. Marcadores con nombre como `{context}` o `{link}` insertan elementos compartidos de código y enlaces. Se pueden reordenar, pero deben conservarse todos sus nombres. No añadir ni eliminar marcadores. Deben estar presentes todas las claves inglesas; si faltan claves o cambian los marcadores, la compilación falla. +## Texto y marcadores -Se mantienen los comandos habituales de DocFX. El idioma se habilita al añadir el diccionario completo. Todas las lenguas usan las mismas rutas; `?lang=es-ES` selecciona el idioma. Las listas se ordenan por código de carpeta. +Traduzca frases o párrafos completos con un español técnico claro y natural. Conserve las condiciones, negaciones, unidades, pasos y restricciones de vida útil. No añada garantías técnicas, requisitos de plataforma, versiones de paquetes ni notas de versiones ausentes del original. Mantenga los nombres de productos, paquetes y archivos, así como los identificadores de C# y Slang, incluidas sus mayúsculas y minúsculas. + +Cada valor debe ser una cadena no vacía de texto sin HTML ni Markdown. Respete las comillas y los escapes de YAML; utilice comillas cuando sean necesarias para evitar que los dos puntos, las almohadillas o los valores parecidos a números se interpreten incorrectamente. Mantenga el orden de las claves del inglés para facilitar la revisión. + +Los marcadores con nombre, como `{context}` y `{link}`, pueden insertar código, enlaces o texto destacado de las páginas compartidas. Los marcadores de interfaz, como `{name}`, `{query}` y `{count}`, también pueden recibir texto durante la ejecución. Compruebe su uso en la página o interfaz correspondiente; no deduzca el contenido solo por el nombre. Traduzca también las etiquetas de enlace y los textos destacados que tengan su propia clave de recurso. + +Puede reordenar los marcadores según la sintaxis española. En cada clave, conserve todos los nombres, sus mayúsculas y minúsculas y las llaves ASCII. No añada, elimine ni renombre marcadores, ni los sustituya por nombres de API, etiquetas de enlace o números de ejemplo. No divida las claves para recomponer frases. + +## Enlaces de API y significado técnico + +Los enlaces se mantienen en las páginas compartidas. Los identificadores que designan una API local en el texto y las tablas enlazan con su tipo o miembro. Las variables, los parámetros, los tipos definidos por el ejemplo, los nombres de paquetes y archivos y los símbolos externos sin referencia local permanecen como texto de código. Una misma grafía puede designar símbolos distintos. Los bloques de código habituales del tutorial no reciben enlaces automáticos. Puede mover un marcador completo, pero no cambiar enlaces, código compartido ni su formato. + +Si una API no tiene una entrada de referencia generada, su identificador permanece como texto de código en la página compartida, con un enlace al código fuente claramente identificado cerca. No lo sustituya por un enlace a otro tipo o miembro. + +Conserve estas distinciones: + +- Grabar comandos, enviarlos, ejecutarlos en la GPU y completarlos son pasos distintos. +- El uso de un recurso, la residencia de memoria o intención de acceso de la CPU, el layout de una textura y su formato de píxel son conceptos distintos. +- La propiedad indica quién debe liberar el recurso. Un handle no mantiene el recurso vivo por sí solo; enviar comandos tampoco transfiere su propiedad. +- La finalización en la GPU no siempre implica que los datos de lectura temporal ya se hayan copiado al destino de CPU de la aplicación. Conserve las indicaciones sobre esperar a la cola responsable. +- Un drawable es la textura de salida del fotograma actual y no necesariamente una imagen de la cadena de intercambio. Distinga las vistas de recursos de los controles de interfaz. + +## Compilación y revisión de entrega + +Ejecute los comandos desde la raíz del repositorio, con el SDK de .NET requerido por el proyecto y DocFX instalados. En una copia nueva del repositorio aún no existen los metadatos generados en `documents/api/`. Primero ejecute la compilación completa, incluida la extracción de la API: ```sh docfx documents/docfx.json --warningsAsErrors +``` + +Si los metadatos de API ya existen y corresponden al código fuente actual, para cambios limitados al diccionario puede usar la compilación normal y la vista previa: + +```sh +docfx build documents/docfx.json --warningsAsErrors docfx serve documents/_site --hostname 127.0.0.1 --port 8080 ``` +Este idioma ya está registrado. El diccionario completo queda disponible tras una compilación correcta, sin cambiar la configuración. La compilación falla si faltan o sobran claves, hay valores vacíos o de otro tipo, o cambian los nombres de los marcadores. No detecta traducciones inexactas ni texto que siga en inglés; es necesaria una revisión humana. + +Todos los idiomas comparten las rutas. `?lang=es-ES` selecciona español; el cambio de idioma conserva la ruta y el ancla. Sin selección explícita, se consultan primero la selección manual guardada, después las preferencias del navegador y, por último, el inglés. Si esta traducción no está publicada, o falla la carga o validación de los recursos de la página, se muestra la página en inglés, sin mezclar idiomas frase a frase. La lista de idiomas se ordena por código. + +Antes de entregar, compruebe las claves y los marcadores. Revise la página de inicio, la entrada de Learn, el tutorial del triángulo, los conceptos, los ejemplos y la interfaz de API en escritorio y a 320 píxeles de ancho. Lea el tutorial como principiante y compruebe terminología, botones, búsqueda, copia de código, enlaces de API y la posición del apartado tras cambiar de idioma. Los identificadores, las declaraciones y el código siguen siendo compartidos; solo se traducen los textos del diccionario. Mantenga los diccionarios de prueba y archivos temporales fuera del repositorio y no entregue traducciones provisionales de relleno. + ## Terminología | Término inglés | Forma acordada | @@ -26,7 +62,7 @@ docfx serve documents/_site --hostname 127.0.0.1 --port 8080 | buffer | búfer; conservar `Buffer` | | command buffer | búfer de comandos | | command queue | cola de comandos | -| drawable | imagen actual disponible para presentación; conservar `Drawable` | +| drawable | textura de salida del fotograma actual; conservar `Drawable`, sin asumir que sea una imagen de la cadena de intercambio | | graphics context | contexto gráfico | | pipeline | canalización | | readback | lectura de datos desde la GPU | diff --git a/documents/locales/fr-FR/translation.md b/documents/locales/fr-FR/translation.md index 8bd44ddb..dba1c860 100644 --- a/documents/locales/fr-FR/translation.md +++ b/documents/locales/fr-FR/translation.md @@ -2,21 +2,57 @@ ## Ressources et structure -L’anglais est l’unique langue source. Copier uniquement les clés et valeurs de `locales/en-US/strings.yml` dans la propre `strings.yml`. Avant la traduction, conserver seulement cette `translation.md` permanente, non publiée. Garder la première ligne `### YamlMime:Resources`. +Le [dictionnaire de ressources anglais](../en-US/strings.yml) est l’unique source du texte. Les règles du projet figurent dans le [guide de maintenance de la documentation](../../authoring.md). Pour commencer une traduction, copier l’intégralité du fichier anglais dans `strings.yml`, dans ce répertoire. Conserver la première ligne `### YamlMime:Resources` et l’encodage UTF-8. Pour les mises à jour, reporter les changements de l’original sans écraser les traductions existantes. Ce fichier `translation.md` est conservé durablement et n’est pas publié sur le site. -La navigation, l’ordre des chapitres, les ancres, les liens, la mise en forme, le code et les images sont communs et restent hors de `locales/`. Ne pas ajouter ici d’articles, de TOC, de modèles, de scripts ou de configuration. +La navigation, l’ordre des chapitres, les ancres, les liens, la mise en forme, le code et les images sont partagés et restent hors de `locales/`. Ne pas ajouter ici d’articles, de TOC, de modèles, de scripts ou de configuration. -Les clés décrivent des fonctions et concepts stables. Elles ne changent pas lors d’une retouche du texte ; éviter les noms liés à une formulation, une position, une numérotation ou une langue. Traduire uniquement les valeurs anglaises dans un français technique clair et naturel. +Modifier uniquement les valeurs du fichier `strings.yml` de cette langue. L’ensemble des clés doit être strictement identique à celui de l’anglais. Ne pas ajouter, supprimer ou renommer de clés de sa propre initiative, même si les textes semblent identiques ou ne sont pas encore apparus dans l’interface. Signaler toute erreur de l’original aux responsables du projet en indiquant la clé concernée. Corriger d’abord la source anglaise et les pages communes, puis les traductions. -Les valeurs sont du texte, sans HTML ni Markdown. Les paramètres nommés comme `{context}` ou `{link}` insèrent les éléments de code et les liens communs. Leur ordre peut changer, mais tous leurs noms doivent être conservés. Ne pas ajouter ni supprimer de paramètres. Toutes les clés anglaises sont obligatoires ; une clé manquante ou des paramètres différents font échouer la compilation. +## Texte et espaces réservés -Les commandes DocFX habituelles restent valables. L’ajout du dictionnaire complet rend la langue disponible automatiquement. Toutes les langues partagent les mêmes chemins ; `?lang=fr-FR` choisit la langue. Les listes suivent l’ordre des codes de dossier. +Traduire des phrases ou paragraphes complets dans un français technique clair et naturel. Préserver les conditions, négations, unités, étapes et contraintes de durée de vie. Ne pas ajouter de garanties techniques, de prérequis de plateforme, de versions de paquets ou de notes de version absents de l’original. Conserver les noms de produits, de paquets et de fichiers, ainsi que les identifiants C# et Slang, en respectant leur casse. + +Chaque valeur doit être une chaîne de caractères non vide, en texte brut, sans HTML ni Markdown. Respecter les guillemets et les échappements YAML ; utiliser des guillemets si nécessaire pour éviter une mauvaise interprétation des deux-points, des dièses ou des valeurs ressemblant à des nombres. Conserver l’ordre des clés de l’anglais pour faciliter la relecture. + +Les espaces réservés nommés, comme `{context}` et `{link}`, peuvent insérer du code, des liens ou du texte mis en évidence provenant des pages communes. Ceux de l’interface, comme `{name}`, `{query}` et `{count}`, peuvent aussi recevoir du texte à l’exécution. Vérifier leur utilisation dans la page ou l’interface concernée sans déduire leur contenu du seul nom. Traduire également les libellés de liens et les textes mis en évidence qui disposent de leur propre clé. + +L’ordre des espaces réservés peut suivre la syntaxe française. Pour chaque clé, conserver tous les noms, leur casse et les accolades ASCII. Ne pas ajouter, supprimer ou renommer d’espaces réservés, ni les remplacer par des noms d’API, des libellés de liens ou des nombres d’exemple. Ne pas scinder les clés pour recomposer une phrase. + +## Liens d’API et sens technique + +Les liens sont maintenus dans les pages communes. Les identifiants désignant explicitement une API locale dans le texte ou les tableaux renvoient au type ou au membre correspondant. Les variables, noms de paramètres, types propres aux exemples, noms de paquets et de fichiers, ainsi que les symboles externes sans page de référence locale restent du texte de code. Une même orthographe peut désigner des symboles différents. Les blocs de code ordinaires du tutoriel ne reçoivent pas de liens automatiques. Déplacer un espace réservé entier est permis ; modifier les liens, le code commun ou sa mise en forme ne l’est pas. + +Si une API ne possède pas d’entrée de référence générée, son identifiant reste du texte de code dans la page commune, accompagné d’un lien explicite vers le code source. Ne pas le remplacer par un lien vers un autre type ou membre. + +Préserver les distinctions suivantes : + +- L’enregistrement des commandes, leur soumission, leur exécution sur le GPU et leur achèvement sont des étapes distinctes. +- L’usage d’une ressource, la résidence mémoire ou l’accès CPU prévu, le layout d’une texture et son format de pixel sont des notions distinctes. +- La propriété désigne la responsabilité de libérer une ressource. Un handle ne maintient pas à lui seul la ressource en vie ; la soumission de commandes ne transfère pas sa propriété. +- L’achèvement sur le GPU ne signifie pas toujours que les données de lecture intermédiaires ont été copiées vers la destination CPU de l’application. Conserver les indications sur l’attente de la file responsable. +- Un drawable est la texture de sortie de l’image en cours de rendu, pas nécessairement une image de la chaîne d’échange. Distinguer les vues de ressources des contrôles d’interface. + +## Compilation et vérification avant livraison + +Exécuter les commandes à la racine du dépôt, avec le SDK .NET requis par le projet et DocFX installés. Dans une nouvelle copie du dépôt, les métadonnées générées dans `documents/api/` sont absentes. Commencer par la compilation complète, qui inclut l’extraction de l’API : ```sh docfx documents/docfx.json --warningsAsErrors +``` + +Si les métadonnées d’API existent et correspondent au code source actuel, une modification du dictionnaire seul peut utiliser la compilation normale et la prévisualisation : + +```sh +docfx build documents/docfx.json --warningsAsErrors docfx serve documents/_site --hostname 127.0.0.1 --port 8080 ``` +Cette langue est déjà enregistrée. Le dictionnaire complet devient disponible après une compilation réussie, sans modifier la configuration. Une clé manquante ou supplémentaire, une valeur vide ou d’un autre type, ou un nom d’espace réservé différent fait échouer la compilation. Celle-ci ne détecte ni les traductions inexactes ni les passages restés en anglais ; une relecture humaine est nécessaire. + +Les langues partagent les mêmes chemins. `?lang=fr-FR` sélectionne le français ; changer de langue conserve le chemin et l’ancre. Sans choix explicite, la sélection manuelle enregistrée est prioritaire, puis les préférences du navigateur, puis l’anglais. Si cette traduction n’est pas publiée, ou si le chargement ou la validation des ressources de la page échoue, la page reste en anglais sans mélange de langues phrase par phrase. La liste des langues est triée par code. + +Avant livraison, vérifier les clés et les espaces réservés. Contrôler l’accueil, l’entrée Learn, le tutoriel du triangle, les concepts, les exemples et l’interface de référence API sur ordinateur et à 320 pixels de largeur. Relire le tutoriel du point de vue d’un débutant ; vérifier la terminologie, les boutons, la recherche, la copie du code, les liens d’API et la position de la section après un changement de langue. Les identifiants, déclarations et extraits de code restent communs ; seuls les textes du dictionnaire sont traduits. Garder les dictionnaires de test et les fichiers temporaires hors du dépôt et ne pas livrer de traductions de remplissage. + ## Terminologie | Terme anglais | Forme retenue | @@ -26,7 +62,7 @@ docfx serve documents/_site --hostname 127.0.0.1 --port 8080 | buffer | tampon ; conserver `Buffer` | | command buffer | tampon de commandes | | command queue | file de commandes | -| drawable | image courante à présenter ; conserver `Drawable` | +| drawable | texture de sortie de l’image en cours de rendu ; conserver `Drawable`, sans supposer qu’elle appartient à une chaîne d’échange | | graphics context | contexte graphique | | pipeline | pipeline | | readback | lecture de données depuis le GPU | diff --git a/documents/locales/ja-JP/translation.md b/documents/locales/ja-JP/translation.md index 59634adf..84a2c96c 100644 --- a/documents/locales/ja-JP/translation.md +++ b/documents/locales/ja-JP/translation.md @@ -2,21 +2,57 @@ ## リソースと構成 -英語を唯一の原文とします。`locales/en-US/strings.yml` のキーと値だけを各言語の `strings.yml` にコピーします。翻訳を始めるまでは、この永続的な `translation.md` だけを残し、サイトには公開しません。先頭の `### YamlMime:Resources` は維持してください。 +[英語のリソース辞書](../en-US/strings.yml)を唯一の原文とします。プロジェクトの規約は[ドキュメント保守ガイド](../../authoring.md)を参照してください。新しい翻訳を始めるときは、英語のファイル全体をこのディレクトリの `strings.yml` にコピーします。先頭行の `### YamlMime:Resources` と UTF-8 エンコーディングを維持してください。更新時は英語の変更点を既存の訳文に反映し、ファイル全体を上書きしないでください。この `translation.md` は翻訳後も保持し、サイトには公開しません。 -ナビゲーション、章の順序、アンカー、リンク、書式、コード、画像は `locales/` の外で共有します。このディレクトリに記事、TOC、テンプレート、スクリプト、設定を追加しません。 +ナビゲーション、章の順序、アンカー、リンク、書式、コード、画像は `locales/` の外で共通管理します。このディレクトリに記事、TOC、テンプレート、スクリプト、設定を追加しないでください。 -キーは安定した役割や概念を表します。文言を調整してもキーを改名せず、文言そのもの、表示位置、番号、言語に依存する名前は避けます。英語の値だけを簡潔で自然な「です・ます」調の日本語に翻訳します。 +翻訳では、この言語の `strings.yml` の値だけを変更します。キーの集合は英語と完全に一致させます。同じ文言に見えるキーや、まだ画面で見ていないキーも含め、独自の追加・削除・改名はしません。原文に問題があれば、該当キーと問題点を保守担当者に伝えてください。英語と共通ページを先に修正し、その後で訳文を更新します。 -値はプレーンテキストであり、HTML や Markdown ではありません。`{context}` や `{link}` のような名前付きプレースホルダーには、共通のコードやリンクが挿入されます。順序は変更できますが、すべての名前を保持し、追加・削除はしません。英語の全キーが必要です。キーの欠落やプレースホルダーの不一致はビルドエラーになります。 +## テキストとプレースホルダー -既存の DocFX コマンドを使います。完全な辞書ファイルを追加すると言語が自動的に有効になります。全言語でページのパスを共有し、`?lang=ja-JP` で言語を選択します。言語一覧はディレクトリコード順です。 +文または段落全体を、簡潔で自然な「です・ます」調の日本語に翻訳します。前提条件、否定、単位、操作順序、リソースの有効期間に関する制約を維持してください。原文にない技術的な保証、プラットフォーム要件、パッケージのバージョン、リリース情報を追加しません。製品名、パッケージ名、ファイル名、C# と Slang の識別子は、大文字と小文字も含めて変更しません。 + +値はすべて、空でない文字列のプレーンテキストにします。HTML や Markdown は記述しません。YAML の引用符とエスケープに注意し、コロン、シャープ記号、数値に見える値などが誤って解析されないよう、必要に応じて引用符で囲みます。照合しやすいよう、キーの順序も英語に合わせてください。 + +`{context}` や `{link}` などの名前付きプレースホルダーには、共通ページのコード、リンク、強調表示が入る場合があります。UI の `{name}`、`{query}`、`{count}` などには、実行時に通常のテキストが入る場合もあります。名前だけで内容を判断せず、対応するページや UI での使われ方を確認してください。リンクのラベルや強調される文言に独立したリソースキーがあれば、その値も翻訳します。 + +日本語の語順に合わせてプレースホルダーを移動できます。ただし、各キーのすべての名前、大文字と小文字、半角の波括弧を維持してください。追加・削除・改名や、表示された API 名、リンクのラベル、例示の数値への置き換えはしません。文を組み直すためにリソースキーを分割しないでください。 + +## API リンクと技術的な意味 + +リンクは共通ページで管理します。本文と表でサイト内の API を明示する識別子は、対応する型またはメンバーにリンクします。変数、パラメーター名、サンプル独自の型、パッケージ名、ファイル名、サイト内に参照ページのない外部シンボルは通常のコード表記のままです。同じつづりでも同じシンボルとは限りません。通常のチュートリアルのコードブロックには、自動でリンクを追加しません。プレースホルダー全体は移動できますが、リンク先、共通コード、その書式は変更しないでください。 + +API の参照項目が生成されていない場合、共通ページでは識別子を通常のコード表記にし、その近くにソースコードへのリンクを明示します。別の型やメンバーへのリンクに置き換えないでください。 + +特に次の区別を維持してください。 + +- コマンドの記録、サブミット、GPU での実行、完了は別の段階です。 +- リソースの用途、メモリの常駐特性や想定する CPU アクセス、テクスチャレイアウト、ピクセル形式は異なる概念です。 +- 所有権はリソースを解放する責任を表します。ハンドルだけではリソースの存続は保証されず、コマンドのサブミットで所有権が移るわけでもありません。 +- GPU の処理が完了しても、一時領域のリードバックデータがアプリケーションの CPU 側の転送先にコピー済みとは限りません。処理を管理するキューでの待機に関する説明を維持してください。 +- drawable は現在のフレームの出力テクスチャであり、必ずしもスワップチェーンの画像ではありません。リソースビューと UI コントロールも文脈に応じて区別してください。 + +## ビルドと提出前の確認 + +プロジェクトに必要な .NET SDK と DocFX がある環境で、リポジトリのルートから実行します。新しくチェックアウトしたリポジトリには、`documents/api/` の生成メタデータがまだありません。最初に API の抽出を含む完全なビルドを実行してください。 ```sh docfx documents/docfx.json --warningsAsErrors +``` + +API メタデータが生成済みで現在のソースコードと一致している場合、辞書だけの変更には通常のビルドとプレビューを使えます。 + +```sh +docfx build documents/docfx.json --warningsAsErrors docfx serve documents/_site --hostname 127.0.0.1 --port 8080 ``` +この言語は登録済みです。完全な辞書でビルドが成功すると、設定を変更せずに利用できます。キーの不足・余剰、空の値、文字列以外の値、プレースホルダー名の不一致はビルドエラーになります。翻訳の正確さや英語の訳し残しはビルドでは判定できないため、人による通読が必要です。 + +全言語でページのパスを共有し、`?lang=ja-JP` で日本語を選びます。言語を切り替えてもパスとアンカーは維持されます。明示的な指定がない場合は、保存済みの手動選択、ブラウザーの言語設定、英語の順に選ばれます。この訳文が未公開の場合や、辞書の読み込み・ページのリソース検証に失敗した場合は、文ごとに言語を混在させず、英語でページを表示します。言語一覧は言語コード順です。 + +提出前にキーとプレースホルダーを照合し、ホーム、Learn の入口、三角形チュートリアル、概念、サンプル、API の UI をデスクトップと幅 320 ピクセルで確認してください。初心者の順序でチュートリアルを読み、用語、ボタン、検索、コードのコピー、API リンク、言語切り替え後の節の位置を確認します。識別子、宣言、コードは共通のまま、辞書が提供する本文と UI の文言だけを翻訳します。テスト用辞書や一時的な確認ファイルはリポジトリの外に置き、仮の訳文を提出しないでください。 + ## 用語 | 英語 | 使用する表現 | @@ -26,7 +62,7 @@ docfx serve documents/_site --hostname 127.0.0.1 --port 8080 | buffer | バッファー。`Buffer` は変更しない | | command buffer | コマンドバッファー | | command queue | コマンドキュー | -| drawable | 現在の表示対象画像。`Drawable` は変更しない | +| drawable | 現在のフレームの出力テクスチャ。`Drawable` は変更せず、常にスワップチェーンの画像とは解釈しない | | graphics context | グラフィックスコンテキスト | | pipeline | パイプライン | | readback | リードバック | diff --git a/documents/locales/ko-KR/translation.md b/documents/locales/ko-KR/translation.md index 7bb8fe2f..4ac951a0 100644 --- a/documents/locales/ko-KR/translation.md +++ b/documents/locales/ko-KR/translation.md @@ -2,21 +2,57 @@ ## 리소스와 구조 -영어를 유일한 원문으로 사용합니다. `locales/en-US/strings.yml`의 키와 값만 해당 언어의 `strings.yml`로 복사합니다. 번역 전에는 게시되지 않는 이 영구적인 `translation.md`만 유지합니다. 첫 줄의 `### YamlMime:Resources`를 보존합니다. +[영문 리소스 사전](../en-US/strings.yml)을 유일한 원문으로 사용합니다. 프로젝트 규칙은 [문서 유지 관리 지침](../../authoring.md)을 참고합니다. 새 번역을 시작할 때는 영문 파일 전체를 이 디렉터리의 `strings.yml`로 복사하고, 첫 줄의 `### YamlMime:Resources`와 UTF-8 인코딩을 유지합니다. 이후에는 영문 변경 사항을 기존 번역에 반영하며, 번역 파일 전체를 원문으로 덮어쓰지 않습니다. 이 `translation.md`는 번역 후에도 보존하며 사이트에는 게시하지 않습니다. -탐색 구조, 장 순서, 앵커, 링크, 서식, 코드 및 이미지는 `locales/` 밖에서 공유합니다. 이 디렉터리에 문서, TOC, 템플릿, 스크립트 또는 설정을 추가하지 않습니다. +탐색 구조, 장 순서, 앵커, 링크, 서식, 코드 및 이미지는 `locales/` 밖에서 공통으로 관리합니다. 이 디렉터리에 문서, TOC, 템플릿, 스크립트 또는 설정을 추가하지 않습니다. -키는 안정적인 역할과 개념을 나타냅니다. 문구를 수정해도 키 이름을 바꾸지 않으며 문구 자체, 표시 위치, 번호 또는 언어에 종속된 이름을 피합니다. 영어 값만 명확하고 자연스러운 한국어로 번역합니다. +번역 시에는 이 언어의 `strings.yml` 값만 수정합니다. 키 집합은 영문과 정확히 같아야 합니다. 문구가 같아 보이거나 아직 화면에서 보지 못한 키도 임의로 추가, 삭제하거나 이름을 바꾸지 않습니다. 원문에 문제가 있으면 해당 키와 문제를 유지 관리자에게 알립니다. 영문과 공유 페이지를 먼저 수정한 다음 번역에 반영합니다. -값은 일반 텍스트이며 HTML이나 Markdown이 아닙니다. `{context}`나 `{link}` 같은 이름 있는 자리 표시자는 공유 코드와 링크를 삽입합니다. 순서는 바꿀 수 있지만 이름은 모두 보존하고 추가하거나 제거하지 않습니다. 영어의 모든 키가 필요합니다. 키가 없거나 자리 표시자가 다르면 빌드가 실패합니다. +## 텍스트와 자리 표시자 -기존 DocFX 명령을 그대로 사용합니다. 완성된 사전을 추가하면 언어가 자동으로 활성화됩니다. 모든 언어는 같은 페이지 경로를 사용하며 `?lang=ko-KR`로 언어를 선택합니다. 언어 목록은 디렉터리 코드순으로 정렬합니다. +문장이나 문단 전체를 명확하고 자연스러운 한국어로 번역합니다. 전제 조건, 부정 표현, 단위, 작업 순서 및 수명 제약을 유지합니다. 원문에 없는 기술적 보장, 플랫폼 요구 사항, 패키지 버전 또는 릴리스 설명을 추가하지 않습니다. 제품명, 패키지명, 파일명과 C# 및 Slang 식별자는 대소문자까지 그대로 유지합니다. + +모든 값은 비어 있지 않은 일반 텍스트 문자열이어야 하며 HTML이나 Markdown을 넣지 않습니다. YAML 따옴표와 이스케이프 규칙을 지키고, 콜론, 샵 기호 또는 숫자처럼 보이는 값이 잘못 해석되지 않도록 필요할 때 따옴표를 사용합니다. 검토하기 쉽도록 영문의 키 순서도 유지합니다. + +`{context}`, `{link}` 같은 이름 있는 자리 표시자는 공유 페이지의 코드, 링크 또는 강조된 내용을 삽입할 수 있습니다. UI의 `{name}`, `{query}`, `{count}` 등에는 실행 중 일반 텍스트가 들어갈 수도 있습니다. 이름만으로 내용을 추측하지 말고 해당 페이지나 UI에서 쓰이는 문맥을 확인합니다. 링크 레이블이나 강조 문구에 별도의 리소스 키가 있으면 그 값도 번역합니다. + +한국어 어순에 맞게 자리 표시자를 옮길 수 있습니다. 단, 각 키의 모든 이름과 대소문자, ASCII 중괄호를 유지해야 합니다. 자리 표시자를 추가, 삭제하거나 이름을 바꾸지 않으며, 화면에 보이는 API 이름, 링크 문구 또는 예시 숫자로 대체하지 않습니다. 문장을 재구성하려고 리소스 키를 나누지 않습니다. + +## API 링크와 기술적 의미 + +링크는 공유 페이지에서 관리합니다. 본문과 표에서 사이트 내 API를 명확히 가리키는 식별자는 해당 형식이나 멤버로 연결됩니다. 변수, 매개 변수 이름, 예제에서 정의한 형식, 패키지명, 파일명 및 사이트 내 참조 페이지가 없는 외부 기호는 일반 코드 텍스트로 유지합니다. 철자가 같아도 같은 기호는 아닐 수 있습니다. 일반적인 튜토리얼 코드 블록에는 링크를 자동으로 추가하지 않습니다. 자리 표시자 전체를 옮길 수는 있지만 링크 대상, 공유 코드 및 서식은 바꾸지 않습니다. + +API의 참조 항목이 생성되지 않은 경우, 공유 페이지에서 식별자를 일반 코드 텍스트로 두고 주변에 소스 코드 링크를 명확히 제공합니다. 다른 형식이나 멤버의 링크로 대체하지 않습니다. + +특히 다음 차이를 유지합니다. + +- 명령 기록, 제출, GPU 실행, 완료는 서로 다른 단계입니다. +- 리소스 용도, 메모리 상주 특성 또는 의도한 CPU 접근, 텍스처 레이아웃, 픽셀 형식은 서로 다른 개념입니다. +- 소유권은 리소스를 해제할 책임을 뜻합니다. 핸들만 보유한다고 리소스의 수명이 유지되는 것은 아니며, 명령 제출로 소유권이 이전되지도 않습니다. +- GPU 작업이 완료되어도 임시 리드백 데이터가 애플리케이션의 CPU 대상에 복사되었다고 단정할 수 없습니다. 작업을 관리하는 큐에서 기다려야 한다는 원문의 설명을 유지합니다. +- drawable은 현재 프레임의 출력 텍스처이며 항상 스왑 체인 이미지인 것은 아닙니다. 리소스 뷰와 UI 컨트롤도 문맥에 맞게 구분합니다. + +## 빌드와 제출 전 검토 + +프로젝트에 필요한 .NET SDK와 DocFX가 설치된 환경에서 저장소 루트에서 명령을 실행합니다. 새로 체크아웃한 저장소에는 `documents/api/`의 생성된 메타데이터가 아직 없습니다. 먼저 API 추출을 포함한 전체 빌드를 실행합니다. ```sh docfx documents/docfx.json --warningsAsErrors +``` + +API 메타데이터가 이미 생성되어 있고 현재 소스 코드와 일치하면, 사전만 수정할 때 일반 빌드와 미리 보기를 사용할 수 있습니다. + +```sh +docfx build documents/docfx.json --warningsAsErrors docfx serve documents/_site --hostname 127.0.0.1 --port 8080 ``` +이 언어는 이미 등록되어 있습니다. 완전한 사전으로 빌드가 성공하면 설정 변경 없이 사용할 수 있습니다. 누락되거나 추가된 키, 빈 값, 문자열이 아닌 값, 일치하지 않는 자리 표시자 이름은 빌드 오류를 일으킵니다. 빌드가 부정확한 번역이나 번역되지 않은 영어를 판단하지는 못하므로 사람이 전체 내용을 읽고 검토해야 합니다. + +모든 언어는 같은 페이지 경로를 사용하며 `?lang=ko-KR`로 한국어를 선택합니다. 언어를 바꿔도 경로와 앵커가 유지됩니다. 명시적으로 지정하지 않으면 저장된 수동 선택, 브라우저 언어 설정, 영어 순서로 선택합니다. 이 번역이 아직 게시되지 않았거나 사전 로드 또는 페이지 리소스 검증이 실패하면 문장별로 언어를 섞지 않고 페이지 전체를 영어로 표시합니다. 언어 목록은 언어 코드순으로 정렬합니다. + +제출 전에 키와 자리 표시자를 대조하고, 데스크톱 및 320픽셀 너비에서 홈, Learn 시작 페이지, 삼각형 튜토리얼, 개념, 예제, API UI를 확인합니다. 초보자의 순서로 튜토리얼을 읽으며 용어, 버튼, 검색, 코드 복사, API 링크, 언어 전환 후의 절 위치를 점검합니다. 식별자, 선언 및 코드는 공통으로 유지하고 사전이 제공하는 본문과 UI 문구만 번역합니다. 테스트 사전과 임시 검증 파일은 저장소 밖에 두고 임시 문구를 채운 번역을 제출하지 않습니다. + ## 용어 | 영어 | 사용할 표현 | @@ -26,7 +62,7 @@ docfx serve documents/_site --hostname 127.0.0.1 --port 8080 | buffer | 버퍼. `Buffer`는 유지 | | command buffer | 명령 버퍼 | | command queue | 명령 큐 | -| drawable | 현재 표시할 이미지. `Drawable`은 유지 | +| drawable | 현재 프레임의 출력 텍스처. `Drawable`은 유지하며 항상 스왑 체인 이미지로 해석하지 않음 | | graphics context | 그래픽스 컨텍스트 | | pipeline | 파이프라인 | | readback | 리드백 | diff --git a/documents/locales/pt-BR/translation.md b/documents/locales/pt-BR/translation.md index ccf1a50f..d1283533 100644 --- a/documents/locales/pt-BR/translation.md +++ b/documents/locales/pt-BR/translation.md @@ -2,21 +2,57 @@ ## Recursos e estrutura -O inglês é a única fonte original. Copie apenas as chaves e os valores de `locales/en-US/strings.yml` para a própria `strings.yml`. Antes de traduzir, mantenha somente esta `translation.md` permanente, que não é publicada. Preserve a primeira linha `### YamlMime:Resources`. +O [dicionário de recursos em inglês](../en-US/strings.yml) é a única fonte do texto. Consulte as regras do projeto no [guia de manutenção da documentação](../../authoring.md). Para iniciar uma tradução, copie o arquivo inglês completo para `strings.yml` neste diretório. Preserve a primeira linha `### YamlMime:Resources` e a codificação UTF-8. Nas atualizações, incorpore as mudanças do original sem sobrescrever as traduções existentes. Este arquivo `translation.md` permanece no diretório e não é publicado no site. -Navegação, ordem dos capítulos, âncoras, links, formatação, código e imagens são compartilhados fora de `locales/`. Não adicione artigos, TOC, templates, scripts ou configurações neste diretório. +Navegação, ordem dos capítulos, âncoras, links, formatação, código e imagens são mantidos fora de `locales/` e compartilhados entre idiomas. Não adicione artigos, TOC, templates, scripts ou configurações neste diretório. -As chaves descrevem funções e conceitos estáveis. Não as renomeie ao ajustar o texto; evite nomes ligados à redação, posição, numeração ou idioma. Traduza apenas os valores ingleses para um português brasileiro técnico, claro e natural. +Altere apenas os valores da `strings.yml` deste idioma. O conjunto de chaves deve corresponder exatamente ao inglês. Não adicione, remova ou renomeie chaves por conta própria, mesmo que os textos pareçam iguais ou ainda não tenham aparecido na interface. Se encontrar um problema no original, informe a chave e o problema aos responsáveis pelo projeto. Corrija primeiro a fonte inglesa e as páginas compartilhadas; depois, atualize as traduções. -Os valores são texto simples, sem HTML ou Markdown. Marcadores nomeados, como `{context}` ou `{link}`, inserem elementos compartilhados de código e links. É possível mudar a ordem, mas todos os nomes devem ser preservados. Não adicione nem remova marcadores. Todas as chaves inglesas são obrigatórias; chaves ausentes ou marcadores diferentes fazem o build falhar. +## Texto e marcadores -Use os comandos habituais do DocFX. Ao adicionar o dicionário completo, o idioma fica disponível automaticamente. Todos os idiomas compartilham os caminhos das páginas; `?lang=pt-BR` seleciona o idioma. As listas seguem a ordem dos códigos dos diretórios. +Traduza frases ou parágrafos completos para um português brasileiro técnico, claro e natural. Preserve condições, negações, unidades, etapas e restrições de tempo de vida. Não acrescente garantias técnicas, requisitos de plataforma, versões de pacotes ou notas de versão ausentes no original. Mantenha nomes de produtos, pacotes e arquivos, além dos identificadores C# e Slang, inclusive maiúsculas e minúsculas. + +Cada valor deve ser uma string não vazia de texto simples, sem HTML ou Markdown. Respeite as aspas e os escapes do YAML; use aspas quando necessário para evitar que dois-pontos, cerquilhas ou valores parecidos com números sejam interpretados incorretamente. Preserve a ordem das chaves do inglês para facilitar a revisão. + +Marcadores nomeados como `{context}` e `{link}` podem inserir código, links ou texto destacado das páginas compartilhadas. Marcadores de interface como `{name}`, `{query}` e `{count}` também podem receber texto em tempo de execução. Confira o uso na página ou interface correspondente, sem deduzir o conteúdo apenas pelo nome. Traduza também os rótulos de links e os textos destacados que tenham sua própria chave de recurso. + +A ordem dos marcadores pode seguir a sintaxe do português. Para cada chave, preserve todos os nomes, suas maiúsculas e minúsculas e as chaves ASCII que delimitam o marcador. Não adicione, remova ou renomeie marcadores, nem os substitua por nomes de API, rótulos de links ou números de exemplo. Não divida chaves de recurso para recompor frases. + +## Links de API e significado técnico + +Os links são mantidos nas páginas compartilhadas. Identificadores que designam uma API local no texto e nas tabelas levam ao tipo ou membro correspondente. Variáveis, nomes de parâmetros, tipos definidos pelo exemplo, nomes de pacotes e arquivos e símbolos externos sem uma página de referência local permanecem como texto de código. A mesma grafia pode designar símbolos diferentes. Blocos de código comuns do tutorial não recebem links automáticos. É permitido mover um marcador inteiro, mas não alterar links, código compartilhado ou sua formatação. + +Se uma API não tiver uma entrada de referência gerada, o identificador permanece como texto de código na página compartilhada, com um link para o código-fonte claramente identificado por perto. Não o substitua por um link para outro tipo ou membro. + +Preserve estas distinções: + +- Gravar comandos, enviá-los, executá-los na GPU e concluí-los são etapas distintas. +- Uso de recursos, residência de memória ou intenção de acesso da CPU, layout de textura e formato de pixel são conceitos distintos. +- A propriedade indica a responsabilidade de liberar um recurso. Um handle não mantém o recurso vivo por si só; o envio de comandos também não transfere a propriedade. +- A conclusão na GPU nem sempre significa que os dados de leitura temporários já foram copiados para o destino de CPU da aplicação. Preserve as instruções sobre aguardar a fila responsável. +- Um drawable é a textura de saída do quadro atual, não necessariamente uma imagem da cadeia de troca. Distinga as visualizações de recursos dos controles de interface. + +## Build e revisão antes da entrega + +Execute os comandos na raiz do repositório, com o SDK do .NET exigido pelo projeto e o DocFX instalados. Em uma cópia nova do repositório, os metadados gerados em `documents/api/` ainda não existem. Primeiro execute o build completo, que inclui a extração da API: ```sh docfx documents/docfx.json --warningsAsErrors +``` + +Se os metadados de API já existem e correspondem ao código-fonte atual, alterações apenas no dicionário podem usar o build normal e a prévia: + +```sh +docfx build documents/docfx.json --warningsAsErrors docfx serve documents/_site --hostname 127.0.0.1 --port 8080 ``` +Este idioma já está registrado. O dicionário completo fica disponível após um build bem-sucedido, sem alterar a configuração. Chaves ausentes ou extras, valores vazios ou de outro tipo e nomes de marcadores diferentes fazem o build falhar. O build não detecta traduções imprecisas nem trechos que continuem em inglês; a leitura e revisão humanas são necessárias. + +Todos os idiomas compartilham os caminhos das páginas. `?lang=pt-BR` seleciona português brasileiro; a troca de idioma mantém o caminho e a âncora. Sem uma escolha explícita, são usadas, nesta ordem, a escolha manual salva, as preferências do navegador e o inglês. Se esta tradução ainda não estiver publicada, ou se o carregamento ou a validação dos recursos da página falhar, a página fica em inglês, sem misturar idiomas frase a frase. A lista de idiomas é ordenada por código. + +Antes de entregar, confira as chaves e os marcadores. Revise a página inicial, a entrada de Learn, o tutorial do triângulo, os conceitos, os exemplos e a interface de API no desktop e com 320 pixels de largura. Leia o tutorial como iniciante e confira terminologia, botões, busca, cópia de código, links de API e a posição da seção após trocar de idioma. Identificadores, declarações e código continuam compartilhados; traduza apenas os textos fornecidos pelo dicionário. Mantenha dicionários de teste e arquivos temporários fora do repositório e não entregue traduções com texto de preenchimento. + ## Terminologia | Termo em inglês | Forma adotada | @@ -26,7 +62,7 @@ docfx serve documents/_site --hostname 127.0.0.1 --port 8080 | buffer | buffer; preservar `Buffer` | | command buffer | buffer de comandos | | command queue | fila de comandos | -| drawable | imagem atual disponível para apresentação; preservar `Drawable` | +| drawable | textura de saída do quadro atual; preservar `Drawable`, sem presumir que seja uma imagem da cadeia de troca | | graphics context | contexto gráfico | | pipeline | pipeline | | readback | leitura de dados da GPU | diff --git a/documents/locales/ru-RU/translation.md b/documents/locales/ru-RU/translation.md index 101b50cf..691d7166 100644 --- a/documents/locales/ru-RU/translation.md +++ b/documents/locales/ru-RU/translation.md @@ -2,21 +2,57 @@ ## Ресурсы и структура -Английский — единственный исходный язык. Скопируйте только ключи и значения из `locales/en-US/strings.yml` в собственный `strings.yml`. До перевода сохраняйте лишь этот постоянный файл `translation.md`, который не публикуется. Сохраните первую строку `### YamlMime:Resources`. +[Английский словарь ресурсов](../en-US/strings.yml) — единственный источник текста. Правила проекта описаны в [руководстве по сопровождению документации](../../authoring.md). Начиная новый перевод, скопируйте английский файл целиком в `strings.yml` в этом каталоге. Сохраните первую строку `### YamlMime:Resources` и кодировку UTF-8. При обновлении учитывайте изменения оригинала, не перезаписывая существующие переводы. Этот файл `translation.md` сохраняется постоянно и не публикуется на сайте. -Навигация, порядок глав, якоря, ссылки, форматирование, код и изображения общие и находятся вне `locales/`. Не добавляйте в этот каталог статьи, TOC, шаблоны, сценарии или настройки. +Навигация, порядок глав, якоря, ссылки, форматирование, код и изображения общие для всех языков и находятся вне `locales/`. Не добавляйте в этот каталог статьи, TOC, шаблоны, сценарии или настройки. -Ключи обозначают устойчивые роли и понятия. Не переименовывайте их при редактировании формулировок; избегайте имён, зависящих от текста, позиции, нумерации или языка. Переводите только английские значения ясным техническим русским языком. +При переводе меняйте только значения в `strings.yml` этого языка. Набор ключей должен точно совпадать с английским. Не добавляйте, не удаляйте и не переименовывайте ключи по собственной инициативе, даже если тексты похожи или ещё не встретились в интерфейсе. Об ошибке в оригинале сообщите сопровождающим проект, указав ключ и суть проблемы. Сначала исправляются английский текст и общие страницы, затем переводы. -Значения — обычный текст, не HTML и не Markdown. Именованные параметры, например `{context}` и `{link}`, вставляют общие элементы кода и ссылки. Их порядок можно менять, но все имена должны сохраняться. Не добавляйте и не удаляйте параметры. Обязательны все английские ключи; отсутствие ключа или несовпадение параметров приводит к ошибке сборки. +## Текст и заполнители -Используйте прежние команды DocFX. Полный словарь автоматически делает язык доступным. Пути страниц одинаковы для всех языков; `?lang=ru-RU` выбирает язык. Списки языков сортируются по коду каталога. +Переводите предложения или абзацы целиком ясным и естественным техническим русским языком. Сохраняйте условия, отрицания, единицы измерения, порядок действий и ограничения времени жизни. Не добавляйте технических гарантий, требований к платформе, версий пакетов или примечаний к выпускам, которых нет в оригинале. Названия продуктов, пакетов и файлов, а также идентификаторы C# и Slang сохраняйте без изменений, включая регистр. + +Каждое значение должно быть непустой строкой обычного текста, без HTML и Markdown. Соблюдайте правила кавычек и экранирования YAML. При необходимости заключайте значения в кавычки, чтобы двоеточия, решётки или текст, похожий на число, не были истолкованы неверно. Для удобства сверки сохраняйте английский порядок ключей. + +Именованные заполнители, например `{context}` и `{link}`, могут подставлять код, ссылки или выделенный текст из общих страниц. Заполнители интерфейса, такие как `{name}`, `{query}` и `{count}`, могут также получать обычный текст во время выполнения. Проверяйте использование ресурса на соответствующей странице или в интерфейсе, не определяя содержимое только по имени. Подписи ссылок и выделенный текст с отдельными ключами ресурсов тоже нужно переводить. + +Порядок заполнителей можно менять согласно русскому синтаксису. В каждом ключе сохраняйте все имена, их регистр и фигурные скобки ASCII. Не добавляйте, не удаляйте и не переименовывайте заполнители; не заменяйте их отображаемыми именами API, подписями ссылок или числами из примеров. Не разделяйте ключи ресурсов ради перестройки предложения. + +## Ссылки на API и технический смысл + +Ссылки поддерживаются в общих страницах. Идентификаторы, явно обозначающие локальный API в тексте и таблицах, ведут к соответствующему типу или члену. Переменные, имена параметров, типы из примеров, названия пакетов и файлов, а также внешние символы без локальной справочной страницы остаются обычным текстом кода. Одинаковое написание не всегда означает один и тот же символ. В обычные блоки кода учебника ссылки автоматически не добавляются. Можно перемещать заполнитель целиком, но нельзя менять ссылки, общий код или его форматирование. + +Если для API не создан справочный элемент, его идентификатор остаётся обычным текстом кода на общей странице, а рядом размещается явно обозначенная ссылка на исходный код. Не заменяйте её ссылкой на другой тип или член. + +Сохраняйте следующие различия: + +- Запись команд, их отправка, выполнение на GPU и завершение — разные этапы. +- Назначение ресурса, резидентность памяти или предполагаемый доступ CPU, состояние доступа к текстуре (layout) и формат пикселя — разные понятия. +- Владение означает ответственность за освобождение ресурса. Один лишь дескриптор не продлевает время жизни ресурса; отправка команд не передаёт владение. +- Завершение работы GPU не всегда означает, что промежуточные данные считывания уже скопированы в целевую память CPU приложения. Сохраняйте указания об ожидании очереди, управляющей этой операцией. +- Drawable — выходная текстура текущего кадра, не обязательно изображение цепочки обмена. Различайте представления ресурсов и элементы управления интерфейса. + +## Сборка и проверка перед передачей + +Выполняйте команды из корня репозитория в среде с требуемым проекту .NET SDK и установленным DocFX. В новой копии репозитория ещё нет сгенерированных метаданных в `documents/api/`. Сначала выполните полную сборку, включающую извлечение API: ```sh docfx documents/docfx.json --warningsAsErrors +``` + +Если метаданные API уже созданы и соответствуют текущему исходному коду, для изменений только в словаре достаточно обычной сборки и предпросмотра: + +```sh +docfx build documents/docfx.json --warningsAsErrors docfx serve documents/_site --hostname 127.0.0.1 --port 8080 ``` +Этот язык уже зарегистрирован. Полный словарь становится доступен после успешной сборки без изменения настроек. Отсутствующие или лишние ключи, пустые значения, значения другого типа и несовпадающие имена заполнителей приводят к ошибке сборки. Сборка не выявляет неточный перевод или оставшийся английский текст: необходима ручная вычитка. + +Все языки используют одинаковые пути страниц. `?lang=ru-RU` выбирает русский язык; при переключении сохраняются путь и якорь. Без явного указания сначала учитывается сохранённый ручной выбор, затем языковые настройки браузера, затем английский. Если этот перевод ещё не опубликован либо загрузка или проверка ресурсов страницы завершается ошибкой, страница отображается на английском без смешивания языков по предложениям. Список языков отсортирован по коду. + +Перед передачей сверьте ключи и заполнители. Проверьте главную страницу, входную страницу Learn, учебник с треугольником, концепции, примеры и интерфейс справочника API на настольном экране и при ширине 320 пикселей. Пройдите учебник с позиции начинающего: проверьте термины, кнопки, поиск, копирование кода, ссылки на API и положение раздела после смены языка. Идентификаторы, объявления и код остаются общими; переводится только текст словаря. Тестовые словари и временные файлы проверки храните вне репозитория; не сдавайте перевод с текстом-заглушкой. + ## Терминология | Английский термин | Принятый вариант | @@ -26,7 +62,7 @@ docfx serve documents/_site --hostname 127.0.0.1 --port 8080 | buffer | буфер; `Buffer` не изменять | | command buffer | командный буфер | | command queue | очередь команд | -| drawable | текущее изображение для представления; `Drawable` не изменять | +| drawable | выходная текстура текущего кадра; `Drawable` не изменять и не считать обязательно изображением цепочки обмена | | graphics context | графический контекст | | pipeline | конвейер | | readback | считывание данных с GPU | diff --git a/documents/locales/zh-CN/translation.md b/documents/locales/zh-CN/translation.md index ed6e720a..5dfaef19 100644 --- a/documents/locales/zh-CN/translation.md +++ b/documents/locales/zh-CN/translation.md @@ -2,21 +2,57 @@ ## 资源与结构 -英文是唯一原文。翻译时只将 `locales/en-US/strings.yml` 的键值复制到本语言的 `strings.yml`。开始翻译前只保留本文件;`translation.md` 永久保留且不发布。保留首行 `### YamlMime:Resources`。 +[英文资源字典](../en-US/strings.yml)是唯一原文;项目约定见[文档维护指南](../../authoring.md)。开始新译本时,将英文文件完整复制为本目录的 `strings.yml`,保留首行 `### YamlMime:Resources`,使用 UTF-8 编码。后续更新应对照英文变更修订现有译文,不要重新覆盖整个文件。本文件 `translation.md` 永久保留,不发布到网站。 导航、章节顺序、锚点、链接、格式、代码和图片都在 `locales/` 外统一维护。不要在语言目录内新增文章、TOC、模板、脚本或配置。 -键名表达稳定的用途与概念。修改措辞时不改键;新增键不要绑定具体句子、显示位置、编号或语言。只翻译英文值,使用自然、简洁的技术中文,保留原意、前提、否定、单位和生命周期约束。 +翻译只修改本目录 `strings.yml` 的值。键集合必须与英文完全一致,不得自行新增、删除或重命名键,包括看起来相同或暂未遇到的界面文案。如果原文存在问题,向维护者指出资源键和问题,由英文及共享页面先统一修正,再同步译文。 -资源值是纯文本,不解析 HTML 或 Markdown。`{context}`、`{link}` 等命名占位符引用公共页中的代码、链接或强调内容。可以按中文语序调整占位符顺序,但必须保留全部名称,不新增或删除占位符。必须包含英文的全部键;缺键、额外旧键或占位符不匹配都会导致构建失败。 +## 文本与占位符 -沿用原有 DocFX 命令。补齐资源文件后自动启用语言,无需修改配置。各语言共用页面路径,通过 `?lang=zh-CN` 选择语言;语言列表始终按目录代码排序。 +使用自然、简洁的技术中文,以完整句子或段落为单位翻译,保留前提、否定、单位、操作顺序和生命周期约束。不要逐词拼接译文,也不要添加原文没有的技术保证、平台要求、包版本或发布说明。产品名、包名、文件名、C#/Slang 标识符和大小写保持原样。 + +每个资源值都必须是非空字符串、纯文本,不写 HTML 或 Markdown。注意 YAML 引号和转义,避免冒号、井号或类似数字的值被误解析;需要时使用引号。保留英文键的排列顺序,方便人工核对。 + +`{context}`、`{link}` 等命名占位符可对应共享页面中的代码、链接或强调内容;`{name}`、`{query}`、`{count}` 等界面占位符也可能由程序填入普通文本。不要凭占位符名称推断内容,应检查对应资源在共享页面或界面中的用途。链接标签或强调文字若有独立资源键,也需要翻译。 + +可以按中文语序移动占位符,但每个键都必须保留原有名称、大小写和半角花括号,不新增、删除或改名。不要用显示出的 API 名称、链接文字或示例数字替换占位符,也不要拆分资源键来重组句子。 + +## API 链接与技术含义 + +链接由共享页面维护。正文和表格中明确指向站内 API 的标识符链接到对应类型或成员;变量、参数名、示例自定义类型、包名、文件名及没有本站参考页的外部符号保持普通代码文字。相同拼写不代表同一个符号。普通教程代码块不自动添加链接。译者可以移动整个占位符,但不补写链接、不修改目标,也不改动共享代码及其格式。 + +如果某个 API 没有生成的参考条目,共享页面会保留普通代码文字,并在附近提供明确的源码链接。不要自行改成其他类型或成员的链接。 + +翻译时尤其注意以下区别: + +- 命令录制、提交、GPU 执行和完成不是同一步。 +- 资源用途、内存驻留/CPU 访问意图、纹理布局和像素格式是不同概念。 +- 所有权表示释放资源的责任;持有句柄不等于保活资源,提交命令也不转移所有权。 +- GPU 完成不一定表示暂存的回读数据已复制到应用程序的 CPU 目标;保留原文关于等待所属队列的说明。 +- `drawable` 指当前帧的输出纹理,不一律等同于交换链图像;资源视图与 UI 控件也要按上下文区分。 + +## 构建与交付检查 + +在已具备项目所需 .NET SDK 和 DocFX 的环境中,从仓库根目录运行命令。首次检出时,`documents/api/` 的生成元数据尚不存在,需要先执行包含 API 提取的完整构建: ```sh docfx documents/docfx.json --warningsAsErrors +``` + +之后,如果 API 元数据已生成且与当前源码一致,只修改字典时可使用普通构建并预览: + +```sh +docfx build documents/docfx.json --warningsAsErrors docfx serve documents/_site --hostname 127.0.0.1 --port 8080 ``` +本语言已注册,完整字典经构建成功后即可使用,无需改配置。缺键、多余键、空值、非字符串值或占位符名称不匹配会导致构建失败。构建不会判断译文是否准确或是否仍残留未翻译的英文,必须人工通读。 + +各语言共用页面路径,通过 `?lang=zh-CN` 选择语言,切换时保留路径和锚点。没有明确指定语言时,依次采用已保存的手动选择、浏览器语言偏好、英文。该译本尚未发布,或字典加载/页面资源校验失败时,页面回退到英文,而不是逐句混用语言。语言列表按语言代码排序。 + +交付前核对键和占位符,并在桌面及 320 像素宽度检查首页、Learn 入口、三角形教程、概念页、示例页和 API 界面。按初学者的顺序通读教程,检查术语、按钮、搜索、代码复制、API 跳转,以及切换语言后的当前章节位置。标识符、声明和代码仍使用共享原文;只翻译字典提供的界面与正文。测试字典和临时检查文件放在仓库外,不提交占位译文。 + ## 术语 | 英文 | 约定译法或处理 | @@ -45,7 +81,7 @@ docfx serve documents/_site --hostname 127.0.0.1 --port 8080 | viewport / scissor | 视口/裁剪区域 | | swap chain / presentation | 交换链/呈现 | | surface(呈现语境) | 原生呈现目标;`Surface` 标识符不译 | -| drawable | 当前可绘制图像;`Drawable` 标识符不译,按原文说明其呈现关系 | +| drawable | 当前帧的输出纹理;`Drawable` 标识符不译,不一律称为交换链图像 | | framebuffer | 帧缓冲区;尺寸以原文规定的像素单位表述 | | barrier / timeline | 屏障/时间线 | | bindless | 首次写“无绑定(bindless)”,保留 API 标识符 | diff --git a/documents/locales/zh-TW/translation.md b/documents/locales/zh-TW/translation.md index 09541468..a92c46b7 100644 --- a/documents/locales/zh-TW/translation.md +++ b/documents/locales/zh-TW/translation.md @@ -2,21 +2,57 @@ ## 資源與結構 -英文是唯一原文。翻譯時只將 `locales/en-US/strings.yml` 的鍵值複製到本語言的 `strings.yml`。開始翻譯前只保留本檔案;`translation.md` 永久保留且不發布。保留首行 `### YamlMime:Resources`。 +[英文資源字典](../en-US/strings.yml)是唯一原文;專案規範請參閱[文件維護指南](../../authoring.md)。建立新譯本時,將英文檔案完整複製為本目錄的 `strings.yml`,保留首行 `### YamlMime:Resources`,並使用 UTF-8 編碼。後續更新應對照英文變更修訂既有譯文,不要重新覆寫整個檔案。本檔案 `translation.md` 永久保留,不發布至網站。 導覽、章節順序、錨點、連結、格式、程式碼和圖片都在 `locales/` 外統一維護。不要在語言目錄內新增文章、TOC、範本、指令碼或設定。 -鍵名表達穩定的用途與概念。修改措辭時不改鍵;新增鍵不要綁定特定句子、顯示位置、編號或語言。只翻譯英文值,使用自然、簡潔的臺灣繁體中文,保留原意、前提、否定、單位與生命週期限制。 +翻譯僅修改本目錄 `strings.yml` 的值。鍵集合必須與英文完全一致,不得自行新增、刪除或重新命名鍵,包括看似相同或尚未遇到的介面文字。如果原文有問題,請向維護者指出資源鍵及問題,先統一修正英文與共用頁面,再同步譯文。 -資源值是純文字,不解析 HTML 或 Markdown。`{context}`、`{link}` 等具名預留位置引用共用頁面中的程式碼、連結或強調內容。可以依中文語序調整順序,但必須保留全部名稱,不新增或刪除。必須包含英文的全部鍵;缺鍵、多餘舊鍵或預留位置不符都會使建置失敗。 +## 文字與預留位置 -沿用既有 DocFX 命令。補齊資源檔案後自動啟用語言,無須修改設定。各語言共用頁面路徑,以 `?lang=zh-TW` 選擇語言;語言清單一律依目錄代碼排序。 +使用自然、簡潔的臺灣繁體中文,以完整句子或段落為單位翻譯,保留前提、否定、單位、操作順序及生命週期限制。不要逐字拼接譯文,也不要加入原文沒有的技術保證、平台需求、套件版本或版本說明。產品名稱、套件名稱、檔名、C#/Slang 識別項及大小寫保持原樣。 + +每個資源值都必須是非空字串、純文字,不寫 HTML 或 Markdown。注意 YAML 引號與逸出,避免冒號、井字號或類似數字的值遭到誤解析;必要時使用引號。保留英文鍵的排列順序,方便人工核對。 + +`{context}`、`{link}` 等具名預留位置可對應共用頁面中的程式碼、連結或強調內容;`{name}`、`{query}`、`{count}` 等介面預留位置也可能由程式填入純文字。不要只憑名稱推斷內容,應查看對應資源在共用頁面或介面中的用途。連結標籤或強調文字若有獨立資源鍵,也需要翻譯。 + +可以依中文語序移動預留位置,但每個鍵都必須保留原有名稱、大小寫與半形大括號,不新增、刪除或改名。不要用顯示出的 API 名稱、連結文字或範例數字取代預留位置,也不要拆分資源鍵來重組句子。 + +## API 連結與技術含義 + +連結由共用頁面維護。正文與表格中明確指向站內 API 的識別項連結至對應型別或成員;變數、參數名稱、範例自訂型別、套件名稱、檔名及沒有本站參考頁面的外部符號維持一般程式碼文字。相同拼寫不代表同一個符號。一般教學程式碼區塊不會自動加入連結。譯者可以移動整個預留位置,但不補寫連結、不修改目標,也不改動共用程式碼及其格式。 + +若某個 API 沒有產生的參考項目,共用頁面會保留一般程式碼文字,並在附近提供明確的原始碼連結。不要自行改成其他型別或成員的連結。 + +翻譯時尤其注意以下區別: + +- 命令記錄、提交、GPU 執行及完成並非同一步驟。 +- 資源用途、記憶體駐留/CPU 存取意圖、紋理配置與像素格式是不同概念。 +- 所有權表示釋放資源的責任;持有控制代碼不等於維持資源存活,提交命令也不會移轉所有權。 +- GPU 完成不一定代表暫存的回讀資料已複製至應用程式的 CPU 目標;保留原文關於等待所屬佇列的說明。 +- `drawable` 指目前影格的輸出紋理,不一律等同於交換鏈影像;資源檢視與 UI 控制項也須依情境區分。 + +## 建置與交付檢查 + +在已具備專案所需 .NET SDK 與 DocFX 的環境中,從儲存庫根目錄執行命令。首次取出儲存庫時,`documents/api/` 的產生中繼資料尚不存在,需要先執行包含 API 擷取的完整建置: ```sh docfx documents/docfx.json --warningsAsErrors +``` + +之後,若 API 中繼資料已產生且與目前原始碼一致,僅修改字典時可使用一般建置並預覽: + +```sh +docfx build documents/docfx.json --warningsAsErrors docfx serve documents/_site --hostname 127.0.0.1 --port 8080 ``` +本語言已註冊,完整字典建置成功後即可使用,無須修改設定。缺鍵、多餘鍵、空值、非字串值或預留位置名稱不符都會使建置失敗。建置不會判斷譯文是否準確或是否仍留有未翻譯的英文,必須人工通讀。 + +各語言共用頁面路徑,以 `?lang=zh-TW` 選擇語言,切換時保留路徑與錨點。未明確指定語言時,依序採用已儲存的手動選擇、瀏覽器語言偏好、英文。此譯本尚未發布,或字典載入/頁面資源驗證失敗時,頁面回復為英文,而非逐句混用語言。語言清單依語言代碼排序。 + +交付前核對鍵與預留位置,並在桌面及 320 像素寬度檢查首頁、Learn 入口、三角形教學、概念頁、範例頁與 API 介面。依初學者的順序通讀教學,檢查術語、按鈕、搜尋、程式碼複製、API 跳轉,以及切換語言後的目前章節位置。識別項、宣告與程式碼仍使用共用原文;僅翻譯字典提供的介面與正文。測試字典及暫存檢查檔案放在儲存庫外,不提交暫代譯文。 + ## 術語 | 英文 | 約定用語 | @@ -30,7 +66,7 @@ docfx serve documents/_site --hostname 127.0.0.1 --port 8080 | command queue | 命令佇列 | | command recording | 命令記錄 | | depth/stencil | 深度/樣板 | -| drawable | 目前可呈現的影像;`Drawable` 不變 | +| drawable | 目前影格的輸出紋理;`Drawable` 不變,不一律稱為交換鏈影像 | | framebuffer | 畫面緩衝區,尺寸依原文的像素單位表述 | | graphics context | 圖形上下文 | | heap | 堆積 | From 53a75e7426ab1ce51700102996e8923b4ead5ff1 Mon Sep 17 00:00:00 2001 From: qian-o <1324771795@qq.com> Date: Mon, 21 Sep 2026 10:36:25 +0800 Subject: [PATCH 18/35] Refactor code structure for improved readability and maintainability --- documents/locales/de-DE/strings.yml | 604 ++++++++++++++++++++++++ documents/locales/es-ES/strings.yml | 604 ++++++++++++++++++++++++ documents/locales/fr-FR/strings.yml | 604 ++++++++++++++++++++++++ documents/locales/ja-JP/strings.yml | 604 ++++++++++++++++++++++++ documents/locales/ko-KR/strings.yml | 604 ++++++++++++++++++++++++ documents/locales/pt-BR/strings.yml | 604 ++++++++++++++++++++++++ documents/locales/ru-RU/strings.yml | 604 ++++++++++++++++++++++++ documents/locales/zh-CN/strings.yml | 604 ++++++++++++++++++++++++ documents/locales/zh-TW/strings.yml | 604 ++++++++++++++++++++++++ documents/templates/public/resources.js | 5 +- documents/templates/public/search.js | 10 +- documents/templates/resources.common.js | 1 + 12 files changed, 5448 insertions(+), 4 deletions(-) create mode 100644 documents/locales/de-DE/strings.yml create mode 100644 documents/locales/es-ES/strings.yml create mode 100644 documents/locales/fr-FR/strings.yml create mode 100644 documents/locales/ja-JP/strings.yml create mode 100644 documents/locales/ko-KR/strings.yml create mode 100644 documents/locales/pt-BR/strings.yml create mode 100644 documents/locales/ru-RU/strings.yml create mode 100644 documents/locales/zh-CN/strings.yml create mode 100644 documents/locales/zh-TW/strings.yml diff --git a/documents/locales/de-DE/strings.yml b/documents/locales/de-DE/strings.yml new file mode 100644 index 00000000..2c7df811 --- /dev/null +++ b/documents/locales/de-DE/strings.yml @@ -0,0 +1,604 @@ +### YamlMime:Resources +concepts.execution.context.description: "Ein {graphicsContext} repräsentiert ein Backend-Gerät und stellt dessen Grafik-, Compute- und Transferwarteschlangen bereit. Erstellen Sie die Puffer, Texturen, Shader und Pipelines für eine Arbeitslast über denselben Kontext. Ressourcen oder Handles aus einem anderen Kontext können nicht einfach an die Befehlspuffer dieses Kontexts gebunden werden." +concepts.execution.context.details: Wählen Sie das Backend für die Plattform und die Präsentationsoberfläche. Die API bleibt gemeinsam, aber die Geräteunterstützung spielt weiterhin eine Rolle. {capabilities} macht den Gerätenamen sowie die Flags {rayTracingSupported} und {meshShadingSupported} verfügbar. Überprüfen Sie das entsprechende Flag, bevor Sie eine optionale Arbeitslast erstellen, wie es die Beispiele {link} und {detail} tun. Diese Flags sind keine vollständige Liste von Format-, Speicher- oder Plattformbeschränkungen. +concepts.execution.context.details.detail: Mesh-Shading +concepts.execution.context.details.link: Raytracing +concepts.execution.context.title: Der Kontext verbindet Ressourcen und Warteschlangen +concepts.execution.description: Eine Zenith.NET-Anwendung erstellt GPU-Ressourcen, zeichnet Befehle auf, die diese verwenden, und reicht diese Befehle bei einer Warteschlange ein. Die CPU kann fortfahren, während die GPU die Übermittlung ausführt. Halten Sie Ressourcen gültig, bis diese Arbeit abgeschlossen ist, selbst nachdem die Aufzeichnungsaufrufe zurückgekehrt sind. +concepts.execution.ownership.description: "Hier bedeutet Besitz die Verantwortung für die Freigabe. Eine C#-Referenz hält ein verwaltetes Objekt erreichbar; sie verhindert nicht, dass ein explizites {dispose} die native Ressource zerstört. Ebenso überträgt das Einreichen eines Befehls, der einen Puffer verwendet, nicht den Besitz dieses Puffers an die Warteschlange." +concepts.execution.ownership.details: "Stoppen Sie beim Herunterfahren das Einreichen neuer Arbeit, warten Sie auf die letzten Verwendungen in jeder beteiligten Warteschlange, geben Sie die Ressourcen der Anwendung frei und anschließend den Kontext. Die Kontextfreigabe gibt dessen Warteschlangen und interne Hilfsobjekte frei; sie wartet nicht auf alle Anwendungsarbeiten und gibt nicht jede von der Anwendung erstellte Ressource frei." +concepts.execution.ownership.guidance: Wenden Sie beim Rendern dieselben Lebensdauerregeln an. Behalten Sie den Fertigstellungswert für die letzte Verwendung einer Ressource bei, damit Sie wissen, wann ihre Bytes überschrieben werden können oder die Ressource ersetzt werden kann. Siehe {link} für Ansichten und die Lebensdauer von zugrunde liegenden Ressourcen. +concepts.execution.ownership.guidance.link: Ressourcenverwaltung +concepts.execution.ownership.table.applicationResources.object: Von der Anwendung erstellte Ressourcen +concepts.execution.ownership.table.applicationResources.ownership: Die Anwendung gibt sie nach ihrer letzten GPU-Verwendung frei. +concepts.execution.ownership.table.commandBuffers.object: Geliehene Befehlspuffer +concepts.execution.ownership.table.commandBuffers.ownership: Die Warteschlange verwaltet und recycelt sie. +concepts.execution.ownership.table.headings.object: Objekt +concepts.execution.ownership.table.headings.ownership: Wer gibt es frei? +concepts.execution.ownership.table.queues.object: Kontext-Warteschlangen und deren Zeitleisten +concepts.execution.ownership.table.queues.ownership: Der Kontext und die Warteschlangen verwalten sie. +concepts.execution.ownership.table.swapChainDrawable.ownership: Die Swapchain verwaltet sie. +concepts.execution.ownership.title: Besitz von der GPU-Fertigstellung trennen +concepts.execution.pipelines.description: Eine Grafikpipeline kombiniert Shader, das Scheitelpunkteingabelayout, die Regel für das Zusammensetzen von Scheitelpunkten zu Primitiven, Attachment-Formate und den Renderzustand. Legen Sie sie fest, bevor Sie Scheitelpunkt-, Index- oder Konstantendaten binden und Zeichenbefehle ausgeben. Ihre Attachment-Formate und die Sample-Anzahl müssen mit den Attachments des Renderpasses übereinstimmen. +concepts.execution.pipelines.details: Eine Compute-Pipeline stellt den Shader-Einstiegspunkt für einen Dispatch bereit, der Gruppen von GPU-Threads startet. Legen Sie sie und ihre Konstanten vor dem Dispatching fest. Compute-Dispatches gehören außerhalb von Grafik-Renderpässen. Das Ändern der Pipeline ändert die Art und Weise, wie nachfolgende Befehle ihre Eingaben interpretieren; binden Sie die für die ausgewählte Pipeline erforderlichen Daten vor deren Verwendung. +concepts.execution.pipelines.guidance: Der {link} zeigt die vollständige Grafiksequenz. Das {detail} zeichnet einen Dispatch gefolgt von einem Grafikpass auf, der das Ergebnis anzeigt. +concepts.execution.pipelines.guidance.detail: Compute-Beispiel +concepts.execution.pipelines.guidance.link: Render-Callback des Dreiecks +concepts.execution.pipelines.title: Eine Pipeline bestimmt, wie Befehle Daten interpretieren +concepts.execution.queues.description: Beginnen Sie mit {graphicsQueue}, wenn ein Frame Zeichnen, Compute und Kopiervorgänge kombiniert. Wenn abhängige Arbeiten auf einer einzigen Warteschlange verbleiben, lässt sich deren Reihenfolge leichter nachvollziehen. +concepts.execution.queues.details: Eine Warteschlange nimmt Batches von Befehlen zur Ausführung entgegen. Getrennte Warteschlangen entsprechen nicht zwangsläufig getrennten Hardware-Engines, sodass ihre Arbeiten möglicherweise nicht gleichzeitig ausgeführt werden. Verwenden Sie eine andere Warteschlange, wenn die Arbeitslast von Überlappung profitieren kann, und fügen Sie eine explizite Abhängigkeit hinzu, wenn eine Warteschlange die Ergebnisse einer anderen Warteschlange verbraucht. +concepts.execution.queues.guidance: Wenn spätere Befehle von früheren Schreibvorgängen abhängen, muss die Anwendung auch sicherstellen, dass diese Schreibvorgänge für die späteren Befehle verfügbar sind. Das Übermitteln beider Befehlspuffer an dieselbe Warteschlange stellt nicht automatisch jede solche Abhängigkeit her. Befehle können unterschiedliche GPU-Stufen verwenden, und spätere Zugriffe erfordern möglicherweise eine Barriere oder einen Texturübergang. {link} erläutert den Unterschied zwischen Übermittlungsreihenfolge und Ressourcensichtbarkeit. +concepts.execution.queues.guidance.link: Synchronisation +concepts.execution.queues.table.computeQueue.workToRecord: Compute-Dispatches und kompatible Transferarbeiten, ohne Grafik-Renderpässe. +concepts.execution.queues.table.graphicsQueue.workToRecord: Renderpässe und Zeichnen sowie vom Frame verwendete Compute- und Transferoperationen. +concepts.execution.queues.table.headings.queue: Warteschlange +concepts.execution.queues.table.headings.workToRecord: Aufzuzeichnende Arbeit +concepts.execution.queues.table.transferQueue.workToRecord: Upload-, Download- und Kopierarbeiten, ohne Zeichnen oder Compute-Dispatches. +concepts.execution.queues.title: Wählen Sie eine Warteschlange für die auszuführende Arbeit +concepts.execution.recording.context: Die Warteschlange fragt die Fertigstellung ab und recycelt fertige Befehlspuffer. Rufen Sie {queueCommandBuffer} für jede neue Aufzeichnung auf; dies kann eine recycelte Instanz zurückgeben. Geben Sie einen geliehenen Befehlspuffer nicht frei, reichen Sie ihn nicht zweimal ein und zeichnen Sie nach dem Einreichen nicht weiter darin auf. Zeichnen Sie einen bestimmten Befehlspuffer jeweils nur von einem Thread aus auf; die interne Sperre der Warteschlange schützt nicht vor gleichzeitigen Bearbeitungen eines Befehlspuffers. +concepts.execution.recording.description: "{queueCommandBuffer} gibt einen {commandBuffer} zurück, dessen Aufzeichnung bereits begonnen hat. Zeichnen Sie die Befehle und deren Abhängigkeiten auf und rufen Sie dann einmal {submit} auf. Das Einreichen beendet die Aufzeichnung und gibt einen {timelineValue} zurück, der einen Fertigstellungspunkt auf dieser Warteschlange identifiziert." +concepts.execution.recording.details: "Nachdem beispielsweise ein Frame in {commandBuffer} aufgezeichnet wurde, reicht das Dreieck diesen ein und wartet auf die Fertigstellung mit:" +concepts.execution.recording.guidance: "{submit} plant die Arbeit ein; {wait} hindert die CPU daran fortzufahren, bis diese Übermittlung abgeschlossen ist. Das Aufzeichnen eines Zeichenbefehls, das Beenden eines Renderpasses und das Einreichen eines Befehlspuffers sind getrennte Operationen. Weder das Aufzeichnen des Zeichenbefehls noch das Beenden des Passes wartet auf die GPU." +concepts.execution.recording.title: Aufzeichnen führt Befehle nicht aus +concepts.execution.title: Ausführungsmodell +concepts.platforms.description: Wählen Sie, ob Ihre Anwendung das native Fenster und die Frame-Schleife selbst besitzt oder ein UI-Rendering-Steuerelement verwendet. Diese Wahl bestimmt, wer die Ausgabetextur bezieht, Befehle einreicht und das Ergebnis präsentiert. Die Ausgabetextur ist die Textur, die als Ausgabe des aktuellen Frames dient. Offscreen-Grafik- und Compute-Arbeiten benötigen weder ein Fenster noch eine Swapchain. +concepts.platforms.frame.context: Fügen Sie Ihre Pipeline-Bindungen und Zeichenbefehle innerhalb dieses Passes hinzu. Beenden Sie den Pass vor der Rückgabe. Reichen Sie den bereitgestellten Befehlspuffer nicht unabhängig ein, präsentieren Sie nicht selbst und geben Sie weder den Befehlspuffer noch die Ausgabetextur frei. Wenn Ihr Handler die Ausgabetextur in einem anderen Layout verwendet, überführen Sie sie für den abschließenden Übergang des Steuerelements zurück in {colorAttachment}. +concepts.platforms.frame.description: Die Integrationen implementieren {iZenithView}. Die Anwendung stellt ihren {graphicsContext} bereit, aktualisiert Szenendaten in {updateRequested} und zeichnet das Rendering in {renderRequested} unter Verwendung von {renderEventArgs} auf. +concepts.platforms.frame.details: "Das Steuerelement steuert den Ablauf eines Frames. Es bezieht die Ausgabetextur und den Befehlspuffer, überführt die Ausgabetextur in {colorAttachment}, ruft die Handler auf und übernimmt dann die für das Framework erforderliche Einreichung und Präsentation." +concepts.platforms.frame.guidance: "Für ein initialisiertes {iZenithView} namens {view}, dem ein Kontext zugewiesen ist, zeichnet dieser Handler einen vollständigen Löschpass auf. Er erfordert {usingZenithNET}:" +concepts.platforms.frame.notes: Die Steuerelemente gehen zu Beginn jedes Frames von {undefined} aus, sodass Anwendungen sich nicht darauf verlassen können, dass vorherige Inhalte der Ausgabetextur erhalten bleiben. Löschen oder rendern Sie das erforderliche Bild in jedem Frame. Halten Sie persistente Akkumulationen oder zwischengespeichertes Rendering in einer anwendungseigenen Textur und zeigen Sie diese Textur über die Ansicht an. +concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat} liefert das Standardfarbformat der Integrationen. Überprüfen Sie die tatsächliche Ausgabetextur des Ereignisses beim Abgleich von Attachment-Formaten, Sample-Anzahlen und Abmessungen." +concepts.platforms.frame.title: In den von einem UI-Steuerelement bereitgestellten Frame aufzeichnen +concepts.platforms.integration.context: WinForms, WPF und der Windows-WinUI-Pfad erfordern Windows. MAUI-Anwendungen benötigen die Arbeitslast ihrer Zielplattform und müssen den Steuerelement-Handler mit {useZenithView} registrieren; siehe {extensionsCs}. Sowohl die Framework-Unterstützung als auch die Backend-Unterstützung müssen erfüllt sein. +concepts.platforms.integration.description: "Die Steuerelemente teilen sich die Ereignisschnittstelle, präsentieren jedoch nicht alle auf dieselbe Weise:" +concepts.platforms.integration.details: Bitmap-Rücklesen kopiert gerenderte Pixel in den CPU-Speicher, bevor die Benutzeroberfläche sie anzeigt. Die Interoperabilität über geteilte Texturen vermeidet dieses Rücklesen, kann jedoch weiterhin GPU-Kopien und Synchronisation erfordern. Die gemeinsame Schnittstelle {renderRequested} bedeutet daher nicht identische Präsentationskosten oder native Interop-Anforderungen. +concepts.platforms.integration.guidance: "Verwenden Sie das Paket für das Framework der Anwendung; zum Beispiel:" +concepts.platforms.integration.table.avalonia.integration: Avalonia +concepts.platforms.integration.table.avalonia.presentation: Rendert in eine Textur und lädt Pixel in eine {writeableBitmap} herunter. Siehe {zenithViewCs} und {surfaceCs}. +concepts.platforms.integration.table.headings.integration: Integration +concepts.platforms.integration.table.headings.presentation: Wie das Bild die Benutzeroberfläche erreicht +concepts.platforms.integration.table.maui.integration: .NET MAUI +concepts.platforms.integration.table.maui.presentation: Verwendet native Oberflächen unter Android, iOS und Mac Catalyst sowie Komposition über geteilte Texturen unter Windows. Siehe die {link}. +concepts.platforms.integration.table.maui.presentation.link: Plattformimplementierungen +concepts.platforms.integration.table.uno.integration: Uno-Pfad +concepts.platforms.integration.table.uno.presentation: Lädt Pixel in eine {writeableBitmap} herunter. Siehe {zenithViewUnoCs}. +concepts.platforms.integration.table.winForms.integration: WinForms +concepts.platforms.integration.table.winForms.presentation: Erstellt eine Zenith.NET-Swapchain für das {hWND} des Steuerelements. Siehe {zenithViewCs}. +concepts.platforms.integration.table.winUI.integration: WinUI unter Windows +concepts.platforms.integration.table.winUI.presentation: Rendert in eine importierte geteilte Direct3D 11-Textur und kopiert dann in eine an {swapChainPanel} angebundene Kompositions-Swapchain. Siehe {zenithViewWinUICs}. +concepts.platforms.integration.table.wpf.integration: WPF +concepts.platforms.integration.table.wpf.presentation: Importiert eine geteilte Direct3D 11-Textur und kopiert dann über Direct3D-Interop in eine von {d3DImage} angezeigte Oberfläche. Siehe {surfaceCs}. +concepts.platforms.integration.title: Sowohl den Präsentationspfad als auch das Framework auswählen +concepts.platforms.lifecycle.context: Verwenden Sie bei einer UI-Ansicht die Eigenschaften {descWidth}, {descHeight}, {descFormat} und {descSampleCount} der Ausgabetextur des Ereignisses, wenn Sie passende Rendering-Ressourcen erstellen. Das Steuerelement bestimmt die Auflösung dieser Ausgabetextur; gehen Sie nicht davon aus, dass seine logischen Abmessungen oder die Anzeigeskalierung stets den Texturabmessungen entsprechen. +concepts.platforms.lifecycle.description: Übergeben Sie bei einer nativen Swapchain Framebuffer-Abmessungen in Pixeln. In logischen Einheiten ausgedrückte Fenstergrößen können abweichen, wenn die Anzeigeskalierung aktiviert ist. Überspringen Sie Framebuffer der Größe null, passen Sie die Größe der Swapchain an, wenn sich ihre Pixelgröße ändert, und fordern Sie {swapChainDrawable} für jeden Frame an. Die Ausgabetextur gehört der Swapchain und kann sich nach der Präsentation oder Größenänderung ändern. +concepts.platforms.lifecycle.details: "{swapChainResize} ändert die Abmessungen der vorhandenen Oberfläche. {swapChainRefresh} ersetzt die Oberflächenbeschreibung einschließlich ihrer nativen Handles. Schließen Sie vor beiden Operationen ausstehende Verwendungen der betroffenen Ressourcen ab. Geben Sie die Swapchain frei, bevor Sie ihr natives Präsentationsziel zerstören." +concepts.platforms.lifecycle.guidance: "Erstellen Sie anwendungseigene Tiefen- oder Offscreen-Texturen, deren Größe dem Fenster folgt, neu und aktualisieren Sie Konstanten, die ihre Handles enthalten. Eine Pipeline kann bei einer Größenänderung erhalten bleiben, wenn ihre Attachment-Formate und die Sample-Anzahl kompatibel bleiben. Der {link} behält seine Pipeline bei, während er seine Tiefentextur ersetzt." +concepts.platforms.lifecycle.guidance.link: Renderer des rotierenden Würfels +concepts.platforms.lifecycle.title: Größe und Lebensdauer der Ausgabetextur beim Host belassen +concepts.platforms.ownership.description: Die Anwendung besitzt den von ihr zugewiesenen Kontext und die Ressourcen, die sie für das Rendering erstellt. Das Steuerelement besitzt seine eigenen Präsentationsressourcen. Eine Änderung der Eigenschaft {graphicsContext} der Ansicht veranlasst den Scheduler, die Ressourcen des Steuerelements neu zu erstellen; die Pipelines, Puffer oder Texturen der Anwendung werden für den neuen Kontext nicht neu erstellt. +concepts.platforms.ownership.details: Stimmen Sie den Ressourcenersatz mit dem Frame-Lebenszyklus der Ansicht ab. Stoppen Sie die Frame-Aktivität der Ansicht und schließen Sie ausstehende GPU-Verwendungen ab, bevor Sie Anwendungsressourcen oder den zugewiesenen Kontext freigeben. Das Entfernen einer Ansicht überträgt den Kontextbesitz nicht auf das Steuerelement. +concepts.platforms.ownership.guidance: Der gemeinsame {frameSchedulerCs} verteilt die Frame-Arbeit über den UI-Dispatcher der Ansicht. Halten Sie Frame-Handler auf das Aktualisieren und Aufzeichnen des Frames fokussiert; langwierige CPU-Arbeiten dort verzögern auch die Benutzeroberfläche. +concepts.platforms.ownership.title: Anwendungsressourcen außerhalb des Besitzes des Steuerelements halten +concepts.platforms.surface.context: Die Unterstützung eines Betriebssystems durch eine Fensterbibliothek oder ein UI-Framework garantiert nicht, dass das ausgewählte GPU-Backend dort verfügbar ist. Gerätefunktionen, Treiber und native Oberflächenunterstützung müssen dennoch zusammenpassen. Überprüfen Sie optionales Raytracing und Mesh-Shading über {contextCapabilities}, bevor Sie diese Arbeitslasten erstellen. +concepts.platforms.surface.description: Das {link} verwendet Silk.NET, um ein Fenster zu erstellen und Ereignisse zu verarbeiten. Zenith.NET verbindet sich mit diesem Fenster über eine {surface}-Beschreibung und eine {swapChain}. Eine Oberfläche enthält native Handles und Abmessungen; das Erstellen der Beschreibung erstellt oder besitzt das Betriebssystemfenster nicht. +concepts.platforms.surface.description.link: Dreieck +concepts.platforms.surface.details: "Das Handle muss zum ausgewählten Backend passen:" +concepts.platforms.surface.guidance: Die Datei {appCs} des Tutorials zeigt die Auswahlmöglichkeiten für Windows, macOS und X11. Ihr Linux-Host liefert Xlib-Handles; die Verwendung in einer Wayland-Sitzung erfordert XWayland. Eine native Wayland-Anwendung würde andere Handles über {surfaceWayland} bereitstellen. +concepts.platforms.surface.table.android.backend: Vulkan unter Android. +concepts.platforms.surface.table.apple.backend: Metal auf Apple-Plattformen. +concepts.platforms.surface.table.headings.backend: Backend-Pfad +concepts.platforms.surface.table.headings.factory: Oberflächen-Factory +concepts.platforms.surface.table.headings.handles: Vom Host bereitgestellte Handles +concepts.platforms.surface.table.wayland.backend: Vulkan mit einem nativen Wayland-Host. +concepts.platforms.surface.table.wayland.handles: Wayland-Display und -Surface +concepts.platforms.surface.table.win32.backend: DirectX 12 oder Vulkan unter Windows. +concepts.platforms.surface.table.xlib.backend: Vulkan unter Linux mit X11 oder XWayland. +concepts.platforms.surface.table.xlib.handles: X11-Display und -Fenster +concepts.platforms.surface.title: Eine native Oberfläche bereitstellen, wenn die Anwendung die Präsentation besitzt +concepts.platforms.title: Plattformintegration +concepts.resources.allocation.context: "Verwenden Sie zunächst über den Kontext erstellte Ressourcen, sofern Sie keinen eigenen Speicherallokator benötigen. Warten Sie bei einem Heap zunächst auf alle GPU-Arbeiten, die seine Ressourcen verwenden. Geben Sie dann die platzierten Ressourcen und erst danach den Heap selbst frei." +concepts.resources.allocation.description: "Ein {heap} stellt Speicher bereit, in dem Ressourcen an ausdrücklich gewählten Byte-Offsets platziert werden. Die Anwendung wählt diese Offsets und verfolgt, welche Bereiche belegt sind." +concepts.resources.allocation.details: "Verwenden Sie vor dem Platzieren {contextGetSizeAndAlignment} mit der genauen Puffer- oder Texturbeschreibung. Wählen Sie einen Offset, der ein Vielfaches der zurückgegebenen Ausrichtung ist, reservieren Sie die zurückgegebene Größe und halten Sie die Ressource innerhalb der Gesamtgröße des Heaps. Noch verwendete Allokationen dürfen sich nicht überlappen. Texturspeicher kann backendabhängige Auffüllung und Ausrichtung enthalten; Pixelzahl mal Bytes pro Pixel ergibt daher nicht die benötigte Allokationsgröße." +concepts.resources.allocation.guidance: "Bei platzierten Puffern muss die Speicherresidenz des Puffers mit der des Heaps übereinstimmen. Verwenden Sie GPU-only-Heaps für die hier beschriebenen gewöhnlichen GPU-Texturen. Größe und Ausrichtung sind Platzierungsanforderungen; sie garantieren nicht, dass jede Ressource auf jedem Backend in jeden Heap passt." +concepts.resources.allocation.title: Ressourcen in einem Heap platzieren, wenn Allokationskontrolle erforderlich ist +concepts.resources.bufferUsages.table.constant.role: Shader-Parameter, die über eine Konstantenpuffer-Bindung gelesen werden. +concepts.resources.bufferUsages.table.headings.role: "Rolle" +concepts.resources.bufferUsages.table.headings.usage: Nutzung +concepts.resources.bufferUsages.table.index.role: Indizes, die beim indexierten Zeichnen verwendet werden. +concepts.resources.bufferUsages.table.indirect.role: "Argumente, die indirekte Zeichen- oder Dispatch-Befehle lesen." +concepts.resources.bufferUsages.table.none.role: "Es sind keine Puffernutzungsflags deklariert." +concepts.resources.bufferUsages.table.storageReadOnly.role: "Pufferdaten, auf die über eine schreibgeschützte Shader-Bindung zugegriffen wird." +concepts.resources.bufferUsages.table.storageReadWrite.role: "Pufferdaten, auf die über eine Shader-Bindung mit Lese- und Schreibzugriff zugegriffen wird." +concepts.resources.bufferUsages.table.transferDst.role: "Zielspeicher für eine GPU-Kopie." +concepts.resources.bufferUsages.table.transferSrc.role: "Quelldaten für eine GPU-Kopie." +concepts.resources.bufferUsages.table.vertex.role: Scheitelpunktattribute, die für das Zeichnen abgerufen werden. +concepts.resources.bufferUsages.title: Puffernutzungen +concepts.resources.description: "Wählen Sie die Ressourcenbeschreibung anhand der geplanten Operationen. Eine Textur, in die gerendert wird, die ein Shader abtastet und deren Daten zur CPU zurückgelesen werden, benötigt alle drei Nutzungen sowie die Synchronisation zwischen ihnen. Speicherplatzierung und Ressourcenlebensdauer sind zusätzliche Entscheidungen." +concepts.resources.memory.context: Für einen CPU-zugänglichen Puffer liefert {map} der CPU eine Adresse. Es wartet nicht darauf, dass die GPU den Zugriff auf dieselben Bytes beendet. {unmap} reicht ebenfalls keine Arbeit ein und wartet nicht auf den Abschluss. Bevor Sie CPU-beschreibbare Daten überschreiben, schließen Sie die GPU-Lesevorgänge ab, die noch den alten Inhalt benötigen. +concepts.resources.memory.description: "Ein {bufferDesc} besitzt ein {residency}-Feld. Wählen Sie es danach aus, wie CPU und GPU auf die Daten zugreifen werden:" +concepts.resources.memory.details: Residenz beschreibt den beabsichtigten CPU-Zugriff auf die Allokation. Sie bedeutet nicht, dass jedes Gerät über separaten physischen CPU- und GPU-Speicher verfügt. Das Dreieck verwendet {cpuWriteOnly}, um einen kleinen Scheitelpunktpuffer direkt zu initialisieren. Ein großes statisches Mesh kann stattdessen von reinem GPU-Speicher mit einem einmaligen Upload profitieren. +concepts.resources.memory.guidance: "{textureDesc} besitzt kein Residenzfeld. Gewöhnliche vom Kontext erstellte Texturen verwenden GPU-Speicher. Ihre öffentliche API bietet Upload- und Download-Operationen für CPU-Datenübertragungen, ohne eine direkte Mapping-Methode offenzulegen. Explizite Heaps bieten Platzierungskontrolle, wie unten beschrieben." +concepts.resources.memory.table.cpuReadOnly.cPUAccess: "Zugeordneten Speicher nach Abschluss der GPU-Kopie lesen." +concepts.resources.memory.table.cpuReadOnly.typicalRole: "Von der GPU erzeugte Rücklesedaten" +concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "Zugeordneten Speicher erst beschreiben, wenn frühere GPU-Lesezugriffe beendet sind." +concepts.resources.memory.table.cpuWriteOnly.typicalRole: "Von der CPU bereitgestellte oder aktualisierte Daten" +concepts.resources.memory.table.gpuOnly.cPUAccess: "Bytes über einen Upload- oder Rücklesepuffer übertragen." +concepts.resources.memory.table.gpuOnly.typicalRole: "Statische Geometrie und GPU-Arbeitsdaten" +concepts.resources.memory.table.headings.cPUAccess: CPU-Zugriff +concepts.resources.memory.table.headings.residency: Residenz +concepts.resources.memory.table.headings.typicalRole: Typische Rolle +concepts.resources.memory.title: "Speicher nach dem benötigten CPU-Zugriff wählen" +concepts.resources.textureUsages.description: "Transfer-Nutzungsflags beschreiben die Richtung von GPU-Kopien. Der CPU-Zugriff ist eine eigene Entscheidung zur Speicherplatzierung, die weiter unten erläutert wird." +concepts.resources.textureUsages.details: "Die Kombination von Nutzungsflags deklariert mehrere Rollen; sie führt die Operationen weder aus noch ordnet sie deren Zugriffe. Für Texturen müssen außerdem {link} stimmen, und ihre Formate müssen die angeforderten Nutzungen auf dem ausgewählten Gerät unterstützen." +concepts.resources.textureUsages.details.link: "Layout und Synchronisation" +concepts.resources.textureUsages.table.colorAttachment.role: "Ein Farb-Attachment in einem Renderpass." +concepts.resources.textureUsages.table.depthStencilAttachment.role: "Ein Tiefen-/Stencil-Attachment in einem Renderpass." +concepts.resources.textureUsages.table.headings.role: "Rolle" +concepts.resources.textureUsages.table.headings.usage: Nutzung +concepts.resources.textureUsages.table.none.role: "Es sind keine Texturnutzungsflags deklariert." +concepts.resources.textureUsages.table.sampled.role: "Texturdaten, die über eine Bindung für abgetastete Texturen gelesen werden." +concepts.resources.textureUsages.table.storage.role: "Texturdaten, auf die Shader über eine Storage-Textur-Bindung lesend oder schreibend zugreifen." +concepts.resources.textureUsages.table.transferDst.role: "Zielbildspeicher für eine GPU-Kopie." +concepts.resources.textureUsages.table.transferSrc.role: "Quellbilddaten für eine GPU-Kopie." +concepts.resources.textureUsages.title: Texturnutzungen +concepts.resources.title: Ressourcenverwaltung +concepts.resources.transfers.context: Ein Download zeichnet eine GPU-Kopie in internen Rücklesespeicher auf. Die Bibliothek kopiert diese Bytes in das angegebene CPU-Ziel, wenn sie den abgeschlossenen Befehlspuffer zur Wiederverwendung zurücksetzt. Halten Sie das Ziel alloziiert und verwalteten Speicher fixiert, bis das {wait} des Übermittlungswerts zurückkehrt. +concepts.resources.transfers.description: "Ein Upload kopiert CPU-Daten zu einer GPU-Ressource; ein Download liest Ressourcendaten in den CPU-Speicher zurück. Die Methoden direkt an der Ressource schließen ihre Übertragung vor der Rückkehr ab:" +concepts.resources.transfers.details: "Diese Warteoperationen decken nur die von der jeweiligen Methode eingereichte Übertragung ab. Sie erkennen keine Abhängigkeiten von einer anderen Warteschlange, die bereits auf die Ressource liest oder schreibt. Stellen Sie diese Abhängigkeiten vor dem Aufruf der Ressourcenmethode her. Auch bei einer direkten Kopie über zugeordneten Speicher muss der Aufrufer sicherstellen, dass die betreffende GPU-Arbeit abgeschlossen ist." +concepts.resources.transfers.guidance: "Verwenden Sie {commandBufferUpload} oder {commandBufferDownload}, wenn Kopiervorgänge zusammen mit anderer Arbeit aufgezeichnet werden sollen. Die Lebensdauern ihrer Zeiger unterscheiden sich:" +concepts.resources.transfers.item: "Ein Upload kopiert die CPU-Quelldaten während des Aufrufs in einen internen Upload-Puffer, auch Staging-Speicher genannt. Der Quellzeiger muss nur für die Dauer dieses Aufrufs gültig bleiben." +concepts.resources.transfers.notes: "Bei Texturen bezeichnet der Zeilenabstand den Byte-Abstand zwischen aufeinanderfolgenden Zeilen der CPU-Daten, der Schichtabstand den Byte-Abstand zwischen aufeinanderfolgenden Tiefenschichten. Beide beschreiben nicht das interne GPU-Speicherlayout der Textur. {link} erläutert den Unterschied zwischen Abschluss und Rücklesen." +concepts.resources.transfers.notes.link: Synchronisation +concepts.resources.transfers.table.bufferDownload.transfer: Direkte CPU-Kopie für {cpuReadOnly}; andernfalls reicht es einen Download auf der Transferwarteschlange ein und wartet. +concepts.resources.transfers.table.bufferUpload.transfer: Direkte CPU-Kopie für {cpuWriteOnly}; andernfalls reicht es einen Upload auf der Transferwarteschlange ein und wartet. +concepts.resources.transfers.table.headings.method: Methode +concepts.resources.transfers.table.headings.transfer: "Art der Datenübertragung" +concepts.resources.transfers.table.textureTransfers.method: "{textureUpload} / {textureDownload}" +concepts.resources.transfers.table.textureTransfers.transfer: "Verwendet die Grafikwarteschlange, überführt die gewählte Unterressource in das Kopierlayout und anschließend in das angeforderte Endlayout und wartet auf den Abschluss." +concepts.resources.transfers.title: "Zwischen sofort abgeschlossenen und aufgezeichneten Übertragungen wählen" +concepts.resources.usages.description: "{bufferUsages} und {textureUsages} sind Flag-Enums, die die vorgesehenen Rollen einer Ressource deklarieren. Sie werden {bufferDescUsages} beziehungsweise {textureDescUsages} zugewiesen. Ein Flag-Enum ermöglicht es, mehrere Member mit {value} zu kombinieren, wenn eine Ressource mehr als eine Rolle hat." +concepts.resources.usages.title: Deklarieren Sie die erforderlichen Verwendungen vor dem Erstellen einer Ressource +concepts.resources.views.description: "Eine {bufferView} beschreibt einen Pufferbereich und dessen Interpretation. Eine {textureView} wählt einen kompatiblen Texturtyp, ein Format und einen Unterressourcenbereich. Eine Ansicht teilt den zugrunde liegenden Speicher; sie kopiert keine Daten und ergänzt keine bei der Ressourcenerstellung fehlenden Nutzungen. Ihr Bereich garantiert auch nicht auf allen Backends eine Prüfung der Shader-Zugriffsgrenzen." +concepts.resources.views.details: "Verwenden Sie das Handle der Ressource für ihre Standardansicht oder erstellen Sie eine Ansicht, wenn Sie einen anderen Bereich oder eine andere kompatible Interpretation benötigen. Halten Sie C#-Referenzen auf die Ansicht und ihre zugrunde liegende Ressource, solange GPU-Arbeit darauf zugreifen kann; ein Ressourcenhandle allein hält keines der Objekte am Leben. Geben Sie beide erst nach ihrer letzten GPU-Verwendung frei. Aktualisieren Sie nach dem Ersetzen eines der Objekte auch die Konstanten mit dessen altem {link}." +concepts.resources.views.details.link: "Ressourcenhandle" +concepts.resources.views.guidance: "Das {link} zeigt, wie eine Tiefentextur bei einer Größenänderung ersetzt wird. Das {detail} hält die Eingabetextur von der beschreibbaren Ausgabe getrennt. In beiden Fällen richtet sich die Lebensdauer der Ressource nach der Arbeit, die sie tatsächlich verwendet." +concepts.resources.views.guidance.detail: "Compute-Beispiel" +concepts.resources.views.guidance.link: "Beispiel des rotierenden Würfels" +concepts.resources.views.title: "Ansichten und zugrunde liegende Ressourcen gemeinsam gültig halten" +concepts.shaders.binding.context: "Im Compute-Beispiel wird {input} mit {inputTextureSampledHandle} und {output} mit {outputTextureStorageHandle} befüllt. Das typisierte {descriptorHandle} von Slang teilt dem Shader mit, wie auf die jeweilige Ressource zugegriffen werden soll:" +concepts.shaders.binding.description: "{setConstantBuffer} bindet einen Puffer und einen Byte-Offset für die Konstantendaten der aktuellen Pipeline. Es bindet vorhandenen GPU-sichtbaren Speicher; es lädt keinen C#-Wert hoch. Füllen Sie zuerst den Puffer und stellen Sie sicher, dass frühere GPU-Leser fertig sind, bevor Sie dessen Bytes überschreiben." +concepts.shaders.binding.details: "Setzen Sie die Pipeline vor ihrem Konstantenpuffer. Bei einer Compute-Arbeitslast mit bereits erstellten und hochgeladenen Ressourcen verwendet die Aufzeichnung diese Reihenfolge:" +concepts.shaders.binding.guidance: Dieses Fragment setzt einen aufzeichnenden {commandBuffer}, eine {computePipeline}, einen hochgeladenen {constantBuffer} mit der Nutzung {bufferUsagesConstant} und die Threadgruppen-Anzahlen für die Arbeitslast voraus. Offset 0 bindet den Anfang des Puffers. Wenn sich mehrere Konstantendatensätze einen Puffer teilen, muss der Start-Offset jedes Datensatzes die Bindungsausrichtung des Backends erfüllen. Diese Anforderung ist unabhängig vom Feldlayout innerhalb des Datensatzes. +concepts.shaders.binding.notes: "{resourceHandle} speichert zwei 32-Bit-Felder, seine Interpretation obliegt jedoch dem Backend. Behandeln Sie es nicht als universellen Deskriptorindex, Adresse oder Wert, der zwischen Kontexten übertragen werden kann. Ein Handle erstellt keine Ressource, fügt keine fehlende Verwendung hinzu und führt keine Synchronisation durch." +concepts.shaders.binding.reference: Behalten Sie Referenzen auf die Ressource und jede Ansicht, die zum Beziehen ihres Handles verwendet wurde, und geben Sie sie erst frei, nachdem die letzte Verwendung durch den Shader abgeschlossen ist. Wenn Sie eine Textur oder Ansicht ersetzen, aktualisieren Sie die Konstanten, die ihr altes Handle enthalten. {link} erläutert diese Lebensdauerbeziehung. +concepts.shaders.binding.reference.link: Ressourcenverwaltung +concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: Strukturierte Elemente des Shader-Typs {t} lesen. +concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: Strukturierte Elemente des Shader-Typs {t} lesen oder schreiben. +concepts.shaders.binding.table.headings.access: Beabsichtigter Zugriff +concepts.shaders.binding.table.headings.cHandle: "C#-Handle" +concepts.shaders.binding.table.headings.slangFieldType: Slang-Feldtyp +concepts.shaders.binding.table.samplerHandle.access: Textur-Abtastzustand bereitstellen. +concepts.shaders.binding.table.textureSampledHandle.access: Eine Textur lesen. +concepts.shaders.binding.table.textureStorageHandle.access: Eine Speichertextur lesen oder schreiben. +concepts.shaders.binding.title: Den Konstantenpuffer und die darin beschriebenen Ressourcen binden +concepts.shaders.compilation.description: "{zenithCompiler} kompiliert einen benannten Slang-Einstiegspunkt und gibt eine {shaderDesc} zurück. Verwenden Sie {graphicsApi} des Kontexts, damit das Ergebnis auf das Backend abzielt, das den Shader erstellen wird: DXIL für DirectX 12, eine Metal-Bibliothek für Metal oder SPIR-V für Vulkan." +concepts.shaders.compilation.details: "Zum Beispiel mit einem vorhandenen {context} und dem neben der ausführbaren Datei kopierten Dreieck-Shader:" +concepts.shaders.compilation.guidance: "{vSMain} muss exakt mit dem Namen des Einstiegspunkts in der Shader-Datei übereinstimmen. Halten Sie Shader-Objekte während der Erstellung der Pipeline gültig und geben Sie sie nach der Pipeline-Erstellung frei, wie in {link} gezeigt. Führen Sie diese Initialisierung einmalig durch, anstatt für jeden Frame neu zu kompilieren." +concepts.shaders.compilation.guidance.link: Erstes Dreieck +concepts.shaders.compilation.title: Einen Einstiegspunkt für den ausgewählten Kontext kompilieren +concepts.shaders.description: "Ein Shader empfängt von der Anwendung bereitgestellte Daten. Scheitelpunktattribute beschreiben einzelne Scheitelpunkte; Puffer enthalten Parameter oder Arrays; Ressourcen-Handles identifizieren andere Ressourcen, auf die der Shader zugreift. Die C#-Deklarationen und Slang-Deklarationen müssen darin übereinstimmen, was diese Werte bedeuten. Das bloße Übereinstimmen eines Feldnamens reicht nicht aus: Layout, Ressourcenzugriff und Bindung müssen alle übereinstimmen." +concepts.shaders.dispatch.description: "{dispatch} nimmt die Anzahl der Threadgruppen entgegen. Der Einstiegspunkt {numthreads} des Compute-Beispiels führt 16 × 16 Threads pro Gruppe aus. Teilen Sie die Bildabmessungen durch 16 und runden Sie auf, um die Gruppenanzahlen zu ermitteln. Ein 17 × 19 Bild benötigt beispielsweise 2 × 2 Gruppen. Der Shader vergleicht seine Pixelkoordinaten mit den Bildabmessungen, da die letzten Gruppen Threads außerhalb des Bildes enthalten können." +concepts.shaders.dispatch.details: Der Compiler speichert die deklarierte Gruppengröße des Einstiegspunkts in {shaderDescThreadGroupSize}; er rechnet die an {dispatch} übergebenen Pixelabmessungen nicht in Gruppenanzahlen um. Verwenden Sie {computeShaderRendererCs} mit seinem Shader für das vollständige Binde- und Dispatch-Beispiel und {link}, bevor ein anderer Pass die Ausgabe verbraucht. +concepts.shaders.dispatch.details.link: Synchronisation +concepts.shaders.dispatch.title: Threadgruppen dispatchen, nicht Pixel +concepts.shaders.layout.context: "Die {link} machen ihre Offsets explizit. Diese Deklaration benötigt {systemRuntimeInteropServices} und {zenithNET} im Gültigkeitsbereich:" +concepts.shaders.layout.context.link: "C#-Konstanten des Compute-Beispiels" +concepts.shaders.layout.description: "Für Scheitelpunkteingaben beschreibt das {inputLayout} der Pipeline Formate, Offsets, Stride und Semantiken. Die {float3}-Position des Dreiecks gefolgt von einer {float4}-Farbe belegt 28 Bytes, wobei die Farbe bei Byte 12 liegt. {inputLayoutAdd} berechnet dieses gepackte Layout; es überprüft die C#-Struktur nicht. Wenn die C#-Felder Padding enthalten, stellen Sie ein passendes Layout bereit, anstatt davon auszugehen, dass die Felder gepackt sind." +concepts.shaders.layout.details: "Konstantenpuffer enthalten Shader-Parameter, während strukturierte Puffer Arrays von Elementen eines deklarierten Typs enthalten. Beide werden gemäß ihren Slang-Deklarationen gelesen. Sie verwenden kein {inputLayout}. Überprüfen Sie Feldoffsets und Elementgrößen für die kompilierte Shader-Repräsentation einschließlich Padding. Ein nicht verwalteter C#-Typ eignet sich zum Kopieren als Bytes, dies allein beweist jedoch nicht, dass er mit einem Shader-Typ übereinstimmt. Wenden Sie insbesondere nicht das dicht gepackte {float3}-Layout eines Scheitelpunkts auf jeden Shader-Puffer an." +concepts.shaders.layout.guidance: Ein Ressourcen-Handle ist ein kleiner Wert, der auf eine vorhandene Ressource verweist. Das Kopieren des Handles in einen Konstantenpuffer kopiert nicht den Inhalt der Ressource. +concepts.shaders.layout.notes: "Die entsprechende Deklaration in {computeShaderSlang} lautet:" +concepts.shaders.layout.reference: "Die Dimensionen belegen die ersten acht Bytes, gefolgt von zwei Acht-Byte-Ressourcen-Handles. Das C#-Beispiel reserviert insgesamt 256 Bytes. Diese Größe ist die vom Beispiel gewählte Speichergröße und keine Regel, dass alle Slang-Strukturen oder Konstanten-Nutzlasten 256 Bytes belegen müssen. Das Auffüllen der Gesamtgröße korrigiert auch kein Feld an einem falschen Offset." +concepts.shaders.layout.title: Scheitelpunkteingabe und Shader-Daten haben unterschiedliche Layout-Regeln +concepts.shaders.matrices.description: Der Compiler fordert zeilenweise Matrixspeicherung (row-major) an, bei der die Elemente jeder Zeile zusammenhängend gespeichert werden. Der {link} platziert drei {matrix4x4}-Werte an den Offsets 0, 64 und 128. Sein {detail} verwendet {mulVectorMatrix} in der Reihenfolge Modell, Ansicht und Projektion. +concepts.shaders.matrices.description.detail: Shader +concepts.shaders.matrices.description.link: Renderer des rotierenden Würfels +concepts.shaders.matrices.details: Die Speicherreihenfolge bestimmt, wie Matrixelemente den Speicher belegen; die Multiplikationsreihenfolge bestimmt die Transformation. Halten Sie beide Seiten konsistent. Das Hinzufügen einer Transposition ohne Überprüfung dieser beiden Optionen kann eine Nichtübereinstimmung verbergen, während eine andere eingeführt wird. +concepts.shaders.matrices.title: Matrixspeicherung und -multiplikation konsistent halten +concepts.shaders.title: Shader-Daten und Bindung +concepts.synchronization.backends.description: DirectX 12 und Vulkan kodieren Texturübergänge mit Layout- und Zugriffsinformationen. Metal hat keine Operation in der {transition}-Implementierung von Zenith.NET. Metal gruppiert aufgezeichnete Arbeiten in Render- und Compute-Encoder. Das Backend fügt Sichtbarkeitsbarrieren ein, wenn es diese Gruppen beendet, wodurch frühere Schreibvorgänge für spätere Arbeiten verfügbar werden. Explizite {barrier}-Aufrufe behandeln Abhängigkeiten wie aufeinanderfolgende Compute-Dispatches innerhalb desselben Encoders. +concepts.synchronization.backends.details: Dieser Unterschied ist wichtig, wenn eine Arbeitslast geändert wird. Im {link} folgt auf den Dispatch ein Grafik-Renderpass, der auch auf Metal eine Encoder-Grenze erzeugt. Zwei abhängige Compute-Dispatches erzeugen diese Grenze nicht allein durch Ändern des deklarierten Layouts der Textur. Behalten Sie die von der gemeinsamen API geforderten Übergänge bei und identifizieren Sie separat die Abhängigkeit zwischen den tatsächlichen erzeugenden und verbrauchenden Befehlen. +concepts.synchronization.backends.details.link: Compute-Beispiel +concepts.synchronization.backends.title: Ein Übergang ist nicht auf jedem Backend identisch +concepts.synchronization.barriers.context: "{barrierStagesAll} ist ein breiterer Gültigkeitsbereich, kein automatischer Abhängigkeitsdetektor. Wählen Sie Stufen aus, die die Arbeit tatsächlich abdecken, und verwenden Sie sie nur auf einer Warteschlange, die diese Operationen unterstützt." +concepts.synchronization.barriers.description: "Betrachten Sie zwei Compute-Dispatches: Der erste schreibt Simulationsdaten, und der zweite liest diese Daten, um den nächsten Schritt durchzuführen. Beide verwenden Speicherpuffer, sodass kein Texturlayout zu ändern ist. Fügen Sie Folgendes zwischen den Dispatches in deren Befehlspuffer ein:" +concepts.synchronization.barriers.details: Das erste Argument identifiziert die Erzeugerstufe und das zweite die Verbraucherstufe. Die Barriere stellt die entsprechende Ausführungs- und Speicherabhängigkeit auf der GPU her. Das Backend übersetzt diese Stufen in seine Ausführungs- und Speicherzugriffsregeln. Diese Barriere ändert nicht das Layout einer Textur und wartet nicht auf alle Arbeiten auf dem Gerät. +concepts.synchronization.barriers.guidance: Die {link} verwendet dieses Muster zwischen abhängigen Dispatches. Platzieren Sie eine Barriere dort, wo die Abhängigkeit auftritt. Eine Barriere, nachdem der Verbraucher bereits aufgezeichnet wurde, kann diesen Verbraucher nicht nach einem früheren Erzeuger ordnen. +concepts.synchronization.barriers.guidance.link: FluidTank-Simulation +concepts.synchronization.barriers.title: Abhängige Befehle mit einer Barriere ordnen +concepts.synchronization.dependencies.description: Identifizieren Sie für jede gemeinsam genutzte Ressource die Operation, die zuerst darauf zugreift, die nachfolgende Operation und ob einer der Zugriffe ein Schreibzugriff ist. Das zweimalige Lesen derselben Daten erfordert keine Ordnung zum Schutz ihres Inhalts, obwohl Layoutänderungen oder Präsentationen andere Anforderungen auferlegen können. Ein Schreibvorgang gefolgt von einem Lesevorgang, ein Lesevorgang gefolgt von einem Überschreiben oder zwei Schreibvorgänge können eine Abhängigkeit erfordern. +concepts.synchronization.dependencies.details: "Wählen Sie dann den Mechanismus dafür aus, wo diese Operationen ausgeführt werden:" +concepts.synchronization.dependencies.guidance: Diese Mechanismen hängen zusammen, sind aber nicht austauschbar. Das Einreichen von Befehlen in der richtigen Reihenfolge ersetzt nicht jede Speicherabhängigkeit. Ein Warten auf einer Warteschlange deklariert kein neues Texturlayout, und eine Befehlsbarriere wartet nicht auf dem aufrufenden CPU-Thread. +concepts.synchronization.dependencies.table.cpuAccess.mechanism: "{wait} auf dem relevanten Fertigstellungswert aufrufen." +concepts.synchronization.dependencies.table.cpuAccess.situation: Die CPU muss vor dem Zugriff auf oder der Freigabe von Daten warten +concepts.synchronization.dependencies.table.crossQueue.mechanism: Seinen {timelineValue} an das {submit} des verbrauchenden Befehlspuffers übergeben. +concepts.synchronization.dependencies.table.crossQueue.situation: Eine Übermittlung auf einer anderen Warteschlange erzeugt die Daten +concepts.synchronization.dependencies.table.headings.mechanism: Mechanismus +concepts.synchronization.dependencies.table.headings.situation: Situation +concepts.synchronization.dependencies.table.layoutChange.mechanism: "{commandBufferTransition} mit vorherigem und folgendem Layout." +concepts.synchronization.dependencies.table.layoutChange.situation: Eine Textur-Unterressource ändert ihre Verwendungsart +concepts.synchronization.dependencies.table.pipelineStages.mechanism: "{commandBufferBarrier} mit den Erzeuger- und Verbraucherstufen." +concepts.synchronization.dependencies.table.pipelineStages.situation: Abhängige GPU-Stufen in einem Befehlsstrom +concepts.synchronization.dependencies.title: Mit dem Erzeuger und dem Verbraucher beginnen +concepts.synchronization.description: Ein Befehl, der von einem früheren Befehl geschriebene Daten liest, hängt davon ab, dass diese Schreibvorgänge abgeschlossen und für ihn sichtbar sind. Der Schreiber ist der Erzeuger (Producer); der Leser ist der Verbraucher (Consumer). Auch die CPU benötigt einen Fertigstellungspunkt, bevor sie gemeinsame Daten liest, überschreibt oder freigibt. Zenith.NET stellt Barrieren, Texturübergänge und Zeitleisten für diese unterschiedlichen Abhängigkeiten bereit. +concepts.synchronization.layouts.context: "{undefined} bedeutet, dass die vorherigen Inhalte nicht beibehalten werden müssen. Es eignet sich für ein neues Bild oder ein Attachment, das vollständig gelöscht wird. Es ist keine Möglichkeit, die Nachverfolgung des Layouts eines Bildes zu vermeiden, dessen Inhalte geladen, abgetastet oder akkumuliert werden sollen." +concepts.synchronization.layouts.description: "Verwendungs-Flags beschreiben, welche Rollen eine Textur unterstützt. {textureLayout} beschreibt, wie auf eine bestimmte Unterressource für eine Operation zugegriffen wird. Eine Unterressource ist ein ausgewählter Mip-Level und Array-Layer. Das Ändern ihres Layouts bereitet diesen Zugriff vor; es konvertiert die Textur nicht in ein anderes Pixelformat. Das Compute-Beispiel schreibt beispielsweise eine Ausgabetextur im Layout {storage} und tastet sie dann in einem Grafikpass ab. Zwischen diesen Verwendungen zeichnet es Folgendes auf:" +concepts.synchronization.layouts.details: Dieses Fragment setzt voraus, dass {outputTexture} mit der Nutzung {sampledStorage} erstellt wurde und sich seine ausgewählte Unterressource im Layout {storage} befindet. {default} wählt Mip-Level 0 und Array-Layer 0 aus. Die Operation überführt nicht jeden Mip-Level oder Layer einer Textur. +concepts.synchronization.layouts.guidance: Die Anwendung stellt das vorherige Layout bereit. {transition} führt keinen für die Anwendung sichtbaren Layout-Tracker und leitet diesen Wert nicht aus früheren Befehlen ab. Verfolgen Sie das Layout überall dort nach, wo eine Ressource zwischen Rendering-Stufen übergeben wird. +concepts.synchronization.layouts.title: Das Layout jeder Textur-Unterressource nachverfolgen +concepts.synchronization.readback.description: "{isCompleted} fragt nur ab, ob die GPU-Zeitleiste einen Wert erreicht hat. Es fordert nicht selbst Befehlspuffer zurück und kopiert keine zwischengespeicherten Downloads in den Zielzeiger der Anwendung." +concepts.synchronization.readback.details: "{commandBufferDownload} zeichnet zunächst eine Kopie in den internen Rücklesespeicher auf. Beim Zurücksetzen des abgeschlossenen Befehlspuffers zur Wiederverwendung werden die Daten per CPU-Kopie an den angegebenen Zeiger übertragen. Halten Sie das Ziel gültig und verwalteten Speicher fixiert, bis {wait} für die Download-Übermittlung zurückkehrt. Erst danach dürfen Sie die Daten lesen oder den Speicher freigeben. Das Warten auf eine spätere Übermittlung einer anderen Warteschlange fragt die zuständige Warteschlange des Downloads nicht selbst ab." +concepts.synchronization.readback.guidance: Aus diesem Grund reicht das Abfragen von {isCompleted} und das sofortige Lesen eines asynchronen Download-Ziels nicht aus. {link} behandelt die direkten Kopier- und gestuften Transferpfade. +concepts.synchronization.readback.guidance.link: Ressourcenverwaltung +concepts.synchronization.readback.title: GPU-Fertigstellung und heruntergeladene CPU-Daten sind getrennte Schritte +concepts.synchronization.reuse.description: Für einen ersten Renderer ist ein sofortiges Warten nach jedem Frame unkompliziert. Um Arbeiten zu überlappen, weisen Sie ausstehenden Frames separate veränderliche Daten zu und behalten Sie den Fertigstellungswert der letzten Verwendung jedes Frames bei. Schließen Sie vor dem Aktualisieren eines Konstantenpuffers, dem Ersetzen einer Textur oder dem Freigeben einer Pipeline jeden ausstehenden Zugriff auf die betroffene Ressource ab. +concepts.synchronization.reuse.details: Stoppen Sie bei Größenänderungen oder beim Herunterfahren neue Verwendungen, bevor Sie auf alte warten. {swapChainResize}, Ressourcenfreigabe und Kontextfreigabe dienen nicht als allgemeine Warteoperationen für Anwendungsarbeiten. Das Dreieck kann die Größe zwischen Callbacks sicher anpassen, da jeder vorherige Frame seine Übermittlung bereits abgeschlossen hat. +concepts.synchronization.reuse.guidance: Das aktuelle {swapChainPresent} signalisiert und wartet nach seiner Präsentationsoperation ebenfalls auf der Grafikwarteschlange. Das Entfernen des expliziten Übermittlungswartens des Dreiecks stellt daher für sich allein noch keine überlappende Präsentationsschleife her. Ein Warten auf der Grafikwarteschlange sagt zudem nichts über unabhängige Arbeiten aus, die noch auf einer anderen Warteschlange laufen. +concepts.synchronization.reuse.title: Daten erst nach ihrem letzten Zugriff wiederverwenden +concepts.synchronization.timelines.context: "Bevor die CPU diese Ressourcen liest, überschreibt oder freigibt, warten Sie auf deren letzte Verwendung:" +concepts.synchronization.timelines.description: Eine Zeitleiste verfolgt die Fertigstellung auf einer Warteschlange anhand aufsteigender Werte. {submit} gibt einen {timelineValue} zurück, der diese Zeitleiste und den mit der Übermittlung verknüpften Wert enthält. Fertigstellungswerte aus verschiedenen Zeitleisten sind nicht allein anhand ihrer numerischen {value}-Felder vergleichbar. +concepts.synchronization.timelines.details: "Angenommen, {producer} und {consumer} sind bereits aufgezeichnete Befehlspuffer aus zwei Warteschlangen desselben Kontexts. Der Erzeuger schreibt Daten, die der Verbraucher verwendet. Reichen Sie sie wie folgt ein:" +concepts.synchronization.timelines.guidance: Das Übergeben des erzeugten Werts veranlasst die verbrauchende Warteschlange, auf der GPU darauf zu warten. Die CPU ruft hier nicht {producedWait} auf. Halten Sie die gemeinsam genutzten Ressourcen gültig, bis {consumed} abgeschlossen ist, und zeichnen Sie alle vom Verbraucher benötigten Texturlayoutänderungen auf. +concepts.synchronization.timelines.notes: "{wait} wartet auf diesen Zeitleistenwert und prüft dann die besitzende Warteschlange auf abgeschlossene Übermittlungen. Fertige Befehlspuffer werden zur Wiederverwendung zurückgesetzt, und ihre zwischengespeicherten Downloads werden in die bereitgestellten CPU-Ziele kopiert. {queueTimelineSignal} kann auch einen Fertigstellungspunkt nach bereits an diese Warteschlange übermittelter Arbeit einreihen. Das Aufrufen von {signal} bedeutet nicht, dass die GPU den Punkt bereits erreicht hat." +concepts.synchronization.timelines.title: Eine Zeitleiste für Fertigstellung und Warteschlangenübergaben verwenden +concepts.synchronization.title: Synchronisation +home.actions.reference: API durchsuchen +home.actions.tutorial: Mit einem Dreieck beginnen +home.entries.description: Ein erster Frame. Ein zielgerichtetes Beispiel. Ein genauerer Blick auf die API. +home.entries.label: Dokumentation erkunden +home.entries.reference.action: API erkunden +home.entries.reference.category: Referenz +home.entries.reference.description: Finden Sie die Typen, Signaturen und Member hinter Ihrer Anwendung. +home.entries.reference.title: API-Referenz +home.entries.samples.action: Beispiele durchsuchen +home.entries.samples.category: Beispiele +home.entries.samples.description: Erkunden Sie zielgerichtete Rendering- und Compute-Techniken anhand ihres Quellcodes. +home.entries.samples.title: Beispiele +home.entries.title: Beginnen Sie mit der Entwicklung. +home.entries.tutorial.action: Tutorial starten +home.entries.tutorial.category: Tutorial +home.entries.tutorial.description: Erstellen Sie eine vollständige Rendering-Anwendung, von der Einrichtung bis zum ersten Frame. +home.entries.tutorial.title: Erstes Dreieck +home.introduction.accent: "In C#." +home.introduction.description: Erstellen Sie Ressourcen, zeichnen Sie Befehle auf und reichen Sie Grafik- oder Compute-Arbeit über eine einheitliche .NET-API ein. +home.introduction.title: Entwickeln Sie Ihren Renderer. +home.meta.description: "Eine konsistente C#-API für Grafik und Compute über DirectX, Metal und Vulkan hinweg." +home.scene.description: Studie rotierender Geometrie. Ziehen Sie mit der Maus oder verwenden Sie die Pfeiltasten, um die Ansicht anzupassen. +home.scene.label: Geometrieanzeige +home.scene.surface: Oberfläche +home.scene.wireframe: Drahtgitter +home.title: Modernes RHI für .NET +learning.concepts.description: Verstehen Sie das Zusammenspiel von Befehlen, Ressourcen, Shader-Daten und Synchronisation, bevor Sie Renderpässe kombinieren. +learning.concepts.execution.description: GPU-Arbeit aufzeichnen, einreichen und die zugehörigen Ressourcen gültig halten. +learning.concepts.platforms.description: Ein natives Fenster oder ein UI-Rendering-Steuerelement anbinden. +learning.concepts.resources.description: Ressourcennutzungen, Speicherplatzierung und Ansichten auswählen. +learning.concepts.shaders.description: "C#-Layouts und Ressourcen-Handles auf Slang abstimmen." +learning.concepts.synchronization.description: Abhängige Zugriffe ordnen und wissen, wann Arbeit abgeschlossen ist. +learning.concepts.title: Kernkonzepte +learning.description: Beginnen Sie mit einem vollständigen Dreieck-Tutorial. Nutzen Sie anschließend die zielgerichteten Beispiele und Konzeptleitfäden, um die Ressourcen, Daten und Abhängigkeiten hinter einem größeren Renderer zu verstehen. +learning.entries.samples.action: Beispiele durchsuchen +learning.entries.samples.description: "Finden Sie C#- und Slang-Beispiele für Geometrie, Compute, Ray-Queries und Mesh-Shading." +learning.entries.tutorial.action: Tutorial öffnen +learning.entries.tutorial.description: Erstellen Sie eine Konsolenanwendung, öffnen Sie ein Fenster und zeichnen Sie ein Dreieck. +learning.meta.description: Erste Schritte mit Zenith.NET und Erkundung seines Programmiermodells. +learning.title: Lernen +reference.description: Schlagen Sie Ressourcentypen, Befehlssignaturen und Plattformintegrationen nach. +reference.entries.commands.description: Grafik-, Compute- und Transferbefehle aufzeichnen. +reference.entries.commands.label: Arbeit aufzeichnen +reference.entries.context.description: GPU-Ressourcen für das ausgewählte Backend erstellen. +reference.entries.context.label: Hier beginnen +reference.meta.description: Erkunden Sie die Typen und Member in Zenith.NET. +reference.navigation.core: Die Kern-API durchsuchen. +reference.title: API-Referenz +samples.computeShader.description: Konvertiert ein Bild mit einem Compute-Dispatch in Graustufen und zeigt die resultierende Textur an. Es demonstriert Ressourcen-Handles für eine abgetastete Eingabetextur und eine schreibbare Ausgabetextur, aufgerundete Threadgruppen-Anzahlen sowie eine Bereichsprüfung im Shader. Behalten Sie das enthaltene Asset {assetsTexturesShokoPng} bei; der Renderer verarbeitet es einmal und präsentiert das Ergebnis in nachfolgenden Frames. +samples.computeShader.details: "{computeShaderRendererCs} · {computeShaderSlang}" +samples.computeShader.title: Compute-Shader +samples.cube.description: Fügt indexiertes Zeichnen, Modell-, Ansichts- und Projektionsmatrizen in einem Konstantenpuffer sowie Tiefentests hinzu. Die Tiefentextur wird bei Größenänderungen neu erstellt. Nutzen Sie dieses Beispiel beim Übergang von Clip-Space-Geometrie zu einem transformierten Objekt; der Renderer verwendet ein {d32FloatS8UInt}-Tiefen-/Stencil-Attachment. +samples.cube.details: "{spinningCubeRendererCs} · {spinningCubeSlang}" +samples.cube.title: Rotierender Würfel +samples.description: "Wählen Sie ein zielgerichtetes Beispiel für die Funktion, die Sie untersuchen möchten. Jedes Beispiel verlinkt auf den C#-Renderer und seinen Slang-Shader. Beginnen Sie mit {link}, wenn Sie eine vollständige Anwendung von einem leeren Projekt an erklärt haben möchten." +samples.description.link: Erstes Dreieck +samples.execution.description: "{link} enthält sechs unabhängige Renderer in einer Desktop-Anwendung. Verwenden Sie das .NET 10 SDK und ein unterstütztes Desktop-Backend, wie unten beschrieben. Erstellen Sie die Anwendung und führen Sie sie aus, und wählen Sie dann ein Beispiel aus dem Konsolenmenü:" +samples.execution.description.link: ZenithTutorials +samples.execution.details: Der Host wählt DirectX 12 unter Windows, Metal unter macOS und Vulkan unter Linux. Verwenden Sie ein Gerät, einen Treiber und eine Shader-Compiler-Umgebung, die vom ausgewählten Backend unterstützt werden. Der Linux-Fensterpfad erfordert X11 oder XWayland. Die {link} deklariert Paketabhängigkeiten und kopiert die zur Laufzeit benötigten Shader- und Textur-Assets. +samples.execution.details.link: Projektdatei +samples.execution.guidance: Die Beispiele teilen sich den Code für Fensterverwaltung und Präsentation. Sie können jedes Beispiel unabhängig danach auswählen, welche Funktion Sie untersuchen möchten. +samples.execution.title: Tutorial-Beispiele ausführen +samples.host.description: "{appCs} erstellt den Kontext, das Fenster und die Swapchain. Es bezieht einen Befehlspuffer, ruft den ausgewählten Renderer auf, reicht den Frame ein und präsentiert ihn. {iRendererCs} definiert die Update-, Render-, Resize- und Freigabemethoden des Renderers." +samples.host.details: Compute und Raytracing erzeugen Offscreen-Texturen. {texturePresenterCs} und {presentTextureSlang} zeichnen diese Texturen in die Ausgabetextur des aktuellen Frames des Fensters. Der Host besitzt weiterhin das Einreichen und die Swapchain-Präsentation. +samples.host.title: Gemeinsamer Host und Präsentation +samples.indirectDrawing.description: Zeichnet mehrere Kopien eines Würfels unter Verwendung eines indexierten indirekten Argumentpuffers und Instanzdaten in einem strukturierten Puffer. Die CPU liefert die Zeichenargumente und aktualisiert die Transformationen. Nutzen Sie dies, um das Layout indirekter Argumente und den Shader-Zugriff auf Instanzdaten zu verstehen, bevor Sie GPU-generierte Argumente hinzufügen. +samples.indirectDrawing.details: "{indirectDrawingRendererCs} · {indirectDrawingSlang}" +samples.indirectDrawing.title: Indirektes Zeichnen +samples.meshShading.description: "Verwendet einen Task-Shader, um Kugelinstanzen für das Zeichnen auszusortieren und die Indizes der verbleibenden Instanzen an einen Mesh-Shader weiterzugeben, der Geometrie ausgibt. Der Renderer prüft {contextCapabilitiesMeshShadingSupported}, bevor er seine Pipeline erstellt. Nutzen Sie das Beispiel, um Ressourcen-Handles und Nutzdaten durch die Task- und Mesh-Stufen zu verfolgen." +samples.meshShading.details: "{meshShadingRendererCs} · {meshShadingSlang}" +samples.meshShading.title: Mesh-Shading +samples.rayTracing.description: Erstellt Bottom-Level- und Top-Level-Beschleunigungsstrukturen für einen Boden und prozedurale Kugeln und führt dann Inline-Ray-Queries in einem Compute-Shader aus. Der Renderer prüft {contextCapabilitiesRayTracingSupported}, bevor er die Arbeitslast konstruiert. Nutzen Sie dieses Beispiel für Beschleunigungsstruktureingaben und shaderseitige Strahlendurchquerung. +samples.rayTracing.details: "{rayTracingRendererCs} · {rayTracingSlang}" +samples.rayTracing.title: Raytracing +samples.title: Beispiele +samples.triangle.description: Erstellt einen Scheitelpunktpuffer und ein passendes Eingabelayout und zeichnet dann drei Scheitelpunkte über eine Grafikpipeline. Nutzen Sie dies, um die Ressourcenerstellung mit den Befehlen in einem Renderpass zu verknüpfen. +samples.triangle.details: "{helloTriangleRendererCs} · {helloTriangleSlang} · {link}" +samples.triangle.details.link: Vollständiges Tutorial +samples.triangle.title: Hallo Dreieck +samples.workloads.description: "Das {link} des Haupt-Repositorys enthält Anwendungen, die mehrere Funktionen kombinieren. Ihre Projekte verweisen auf den Bibliotheksquellcode. Führen Sie aus einem Checkout von Zenith.NET das gewünschte Projekt aus, zum Beispiel:" +samples.workloads.description.link: Verzeichnis Experiments +samples.workloads.details: Die fensterbasierten Experimente verwenden dieselben Host-Optionen für Windows, macOS und Linux/X11. Informationen zum Zeichnen innerhalb von Avalonia, WinForms, WPF, WinUI/Uno oder MAUI sowie zum Frame-Lebenszyklus und zu Implementierungslinks finden Sie unter {link}. +samples.workloads.details.link: Plattformintegration +samples.workloads.table.cornellBox.example: "{link}" +samples.workloads.table.cornellBox.example.link: CornellBox +samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: Pfadverfolgung, Rauschunterdrückung, Tone-Mapping, Hochskalierung und ImGui-Steuerelemente. Erfordert Raytracing-Unterstützung und die Shader-Kompilierungsumgebung für das jeweilige Desktop-Backend. +samples.workloads.table.fluidTank.example: "{link}" +samples.workloads.table.fluidTank.example.link: FluidTank +samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: Compute-Fluidsimulation, Abhängigkeiten zwischen Simulationsstufen und mehrpassiges Oberflächen-Rendering. Erfordert das jeweilige Desktop-Backend und die Shader-Kompilierungsumgebung. +samples.workloads.table.headings.example: Beispiel +samples.workloads.table.headings.whatItDemonstratesAndRequires: Was es demonstriert und erfordert +samples.workloads.table.inkCanvas.example: "{link}" +samples.workloads.table.inkCanvas.example.link: InkCanvas +samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: Skia-Zeichnen und Eingabeverarbeitung in einem nativen Fenster. Erfordert das Backend und die native Skia-Bibliothek für die Zielplattform. +samples.workloads.table.platformDetection.example: "{link}" +samples.workloads.table.platformDetection.example.link: PlatformDetection +samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: Versucht die Kontexterstellung für jedes Backend und meldet Gerätefunktionen. Ein Fehler bei der Kontexterstellung wird als nicht unterstützt gemeldet; dieses Ergebnis kann auch auf einen fehlenden Treiber oder eine fehlende Laufzeitabhängigkeit hinweisen. +samples.workloads.title: Größere Arbeitslasten erkunden +tutorial.context.description: Das Fenster kann sich nun öffnen, aber wir haben noch nicht die GPU-Objekte erstellt, die darin rendern werden. Ein {graphicsContext} bietet Zugriff auf das ausgewählte Grafik-Backend und seine Befehlswarteschlangen. +tutorial.context.details: "Fügen Sie diesen Block {emphasis} ein:" +tutorial.context.details.emphasis: nach den using-Direktiven, vor {iWindowWindow} +tutorial.context.guidance: Die Verzweigungen wählen DirectX 12 unter Windows, Metal unter macOS und Vulkan unter Linux aus. Der nachfolgende Rendering-Code verwendet die gemeinsame Zenith.NET-API. Wir fordern die Validierung während der Entwicklung an und geben über {validationMessage} gemeldete Meldungen aus. Die Diagnose hängt vom Backend und den auf dem Computer verfügbaren Validierungskomponenten ab. +tutorial.context.title: Grafikkontext erstellen +tutorial.description: Erstellen Sie eine .NET-Konsolenanwendung, die ein Fenster öffnet und ein Dreieck mit einem weichen Farbverlauf zeichnet. Sie lernen, wie Scheitelpunktdaten, Shader und Pipeline-Zustände zusammenwirken, und zeichnen anschließend die Befehle auf und reichen sie ein, die das Bild erzeugen. +tutorial.details: Arbeiten Sie die Abschnitte der Reihe nach durch. Sie öffnen zuerst ein leeres Fenster, zeigen dann eine Hintergrundfarbe an und zeichnen schließlich das Dreieck. Jeder Kontrollpunkt bestätigt einen Teil der Anwendung, bevor Sie den nächsten hinzufügen. Die Initialisierung wird einmal ausgeführt; der Render-Callback zeichnet bei jedem Aufruf einen neuen Frame auf. +tutorial.draw.context: "Die Argumente für {draw} sind:" +tutorial.draw.description: "Ersetzen Sie im Callback {windowRender} den Platzhalter {addTheTriangleDrawCommandsHereLater} durch diese drei Befehle zwischen {beginRenderPass} und {endRenderPass}:" +tutorial.draw.details: "{setPipeline} wählt die soeben erstellten Shader und Zustände aus. Setzen Sie sie vor dem Binden von Scheitelpunktdaten: Das Backend verwendet das Eingabelayout der Pipeline, um die Bindung zu interpretieren." +tutorial.draw.guidance: "{setVertexBufferVertexBuffer} bindet den Puffer ab Byte-Offset 0 an Eingabeslot 0. Dieser Slot entspricht dem einzelnen Eintrag in {inputLayouts}. Die Daten werden dadurch nicht erneut kopiert oder hochgeladen." +tutorial.draw.notes: Die Befehle sind an dieser Stelle immer noch nur aufgezeichnet. Die Aufrufe von {submitWait} und {present}, die sich bereits am Ende des Render-Callbacks befinden, führen die Arbeit aus und zeigen ihr Ergebnis an. Das Löschen bleibt notwendig, da das Dreieck nur einen Teil des Bildes abdeckt; der Hintergrund muss ebenfalls in jedem Frame eine definierte Farbe erhalten. +tutorial.draw.table.firstInstance.meaning: Instanznummerierung bei null beginnen. +tutorial.draw.table.firstVertex.meaning: Mit dem ersten Scheitelpunkt im Puffer beginnen. +tutorial.draw.table.headings.argument: Argument +tutorial.draw.table.headings.description: Wert +tutorial.draw.table.headings.meaning: Bedeutung +tutorial.draw.table.instanceCount.meaning: Eine Kopie des Dreiecks zeichnen. +tutorial.draw.table.vertexCount.meaning: Drei Scheitelpunkte lesen. +tutorial.draw.title: Das Dreieck innerhalb des Passes zeichnen +tutorial.execution.description: "Erstellen Sie die Anwendung und führen Sie sie aus dem Verzeichnis {firstTriangle} aus:" +tutorial.execution.details: Das Fenster sollte ein Dreieck mit einer roten oberen Ecke, einer grünen unteren rechten Ecke und einer blauen unteren linken Ecke vor einem dunklen Hintergrund anzeigen. Das Innere sollte einen weichen Übergang zwischen diesen Farben aufweisen. +tutorial.execution.guidance: Ändern Sie die Fenstergröße. Der Resize-Callback aktualisiert die Framebuffer-Abmessungen und passt die Größe der Swapchain an. Der Renderpass richtet einen Viewport ein, der diesem Bild entspricht. Da die Scheitelpunktpositionen in normalisierten Koordinaten verbleiben, behält das Dreieck denselben Bruchteil der Fensterbreite und -höhe bei; eine Änderung des Seitenverhältnisses kann seine Form verzerren. Die Beibehaltung des Seitenverhältnisses eines Objekts erfordert eine Projektions- oder Viewport-Strategie, die über diesen ersten Zeichenvorgang hinausgeht. +tutorial.execution.title: Ausführen, Größe ändern und schließen +tutorial.frame.commands.context: Nach {endRenderPass} bereitet der zweite Übergang das Bild auf die Präsentation vor. {submit} beendet die Aufzeichnung und reicht den Befehlspuffer ein; {wait} wartet darauf, dass die GPU diese Übermittlung abschließt. {present} fordert dann die Anzeige des gerenderten Bildes an. +tutorial.frame.commands.description: Ein Renderpass gruppiert Zeichenoperationen, die dieselben Attachments verwenden. Hier ist das Farb-Attachment die Ausgabetextur der Swapchain, also das Bild, das unsere Zeichnung empfängt. {colorAttachmentClear} erstellt eine Beschreibung, die den Pass anweist, auf die angegebene RGBA-Farbe zu löschen und das Ergebnis nach Beendigung des Passes beizubehalten. {beginRenderPass} zeichnet diese Anweisungen auf; die GPU führt das Löschen aus, nachdem die Befehle eingereicht wurden. +tutorial.frame.commands.details: Die eckigen Klammern enthalten unser einzelnes Farb-Attachment. Das Argument {null} bedeutet, dass kein Tiefen-/Stencil-Attachment vorhanden ist, das Tiefenwerte und Stencil-Masken für Tiefen- und Stencil-Tests speichern würde. +tutorial.frame.commands.guidance: "{beginRenderPass} legt einen Viewport und einen Scissor fest, die das Attachment abdecken. Der Viewport bildet die gerenderten Koordinaten auf Pixel ab, und der Scissor schränkt ein, welche Pixel beschrieben werden dürfen. Diese Standardeinstellungen decken die gesamte Ausgabetextur ab, was für dieses Dreieck genau richtig ist." +tutorial.frame.commands.title: Löschen, einreichen und präsentieren +tutorial.frame.description: Füllen Sie das Bild zunächst mit einer einzigen Hintergrundfarbe. Dieser Vorgang wird als Löschen (Clear) bezeichnet. Wenn diese Farbe im Fenster erscheint, arbeiten die Oberfläche, das Einreichen von Befehlen und der Präsentationspfad zusammen. Mit diesem Kontrollpunkt können Sie die Frame-Schleife überprüfen, bevor Sie Geometrie und Shader hinzufügen. +tutorial.frame.details: "Ein Render-Callback ist Code, den Silk.NET aufruft, wenn ein Frame gezeichnet werden soll. Dieser Callback benötigt das Argument für die vergangene Zeit des Ereignisses nicht, daher wird es {value} genannt. Registrieren Sie ihn {emphasis}:" +tutorial.frame.details.emphasis: vor {windowRun} +tutorial.frame.target.description: "{graphicsQueueCommandBuffer} bezieht einen Befehlspuffer, dessen Aufzeichnung bereits begonnen hat. Das Aufzeichnen beschreibt Arbeit für die GPU; es führt diese Arbeit nicht sofort aus." +tutorial.frame.target.details: Der erste {transition}-Aufruf bereitet die Ausgabetextur für den Zugriff als Farb-Attachment vor. {default} wählt Mip-Level 0 und Array-Layer 0 aus. Wir verwenden {undefined} als vorheriges Layout, da wir das gesamte Bild löschen und seinen vorherigen Inhalt verwerfen. Ein Pass, der vorhandene Inhalte beibehalten muss, muss stattdessen sein tatsächliches vorheriges Layout verwenden. +tutorial.frame.target.guidance: Verwenden Sie in jedem Frame die aktuelle Ausgabetextur der Swapchain. Die Präsentation kann ändern, welches Bild verfügbar ist; daher ist eine aus einem früheren Frame gespeicherte Textur kein dauerhaftes Fenster-Renderziel. +tutorial.frame.target.title: Ausgabetextur vorbereiten +tutorial.frame.title: Eine Hintergrundfarbe anzeigen +tutorial.geometry.data.description: Fügen Sie dieses Array {emphasis} hinzu. Die folgenden Schritte zur Ressourcenerstellung gehören ebenfalls vor diesen Callback, in der gezeigten Reihenfolge. +tutorial.geometry.data.description.emphasis: vor {windowRender} +tutorial.geometry.data.details: "Jeder Array-Eintrag erstellt einen {vertex}. Die beiden inneren {new}-Ausdrücke erstellen seine {vector3}-Position und {vector4}-Farbe. Die Scheitelpunkte beschreiben die obere, untere rechte und untere linke Ecke. Der Vertex-Shader liefert eine vierte Positionskoordinate, {w}. Wenn w gleich 1 ist, beschreiben x und y direkt normalisierte Gerätekoordinaten: -1 und +1 sind die Bildränder und 0 ist das Zentrum. Diese Koordinaten hängen nicht von den Pixelabmessungen des Fensters ab." +tutorial.geometry.data.guidance: Jede Farbe enthält Rot-, Grün-, Blau- und Alpha-Komponenten. Alpha ist an allen drei Ecken 1. Alle drei Positionen haben z = 0 und liegen damit in derselben Ebene. Diese Positionen benötigen keine Kamera- oder Transformationsmatrix, da sie bereits die Koordinaten beschreiben, die wir rendern möchten. Für dieses einzelne flache Dreieck deaktivieren wir außerdem Blending und Tiefentests und verzichten auf einen Tiefenpuffer. +tutorial.geometry.data.title: Die Ecken auswählen +tutorial.geometry.description: Ein Scheitelpunkt (Vertex) ist ein Punkt zusammen mit den zu seinem Zeichnen verwendeten Daten. Unser Dreieck hat drei Scheitelpunkte, einen für jede Ecke. Jeder enthält eine Position und eine Farbe. Die GPU interpoliert die Farben und berechnet Zwischenwerte über das gesamte Dreieck hinweg. +tutorial.geometry.format.description: "Fügen Sie diese Deklaration {emphasis} an:" +tutorial.geometry.format.description.emphasis: am Ende von {programCs}, nach den Bereinigungsanweisungen +tutorial.geometry.format.details: "{file} beschränkt diesen Typ auf {programCs}, und der Konstruktor initialisiert seine Positions- und Farbfelder. {layoutKindSequential} behält die Deklarationsreihenfolge der Felder bei. {position} enthält drei 32-Bit-Gleitkommazahlen und {color} vier. In dieser Struktur beginnt die Position bei Byte 0, die Farbe bei Byte 12, und der gesamte Scheitelpunkt belegt 28 Bytes. Dasselbe Layout werden wir der Grafikpipeline beschreiben." +tutorial.geometry.format.title: Einen Scheitelpunkt definieren +tutorial.geometry.title: Der GPU drei Scheitelpunkte übergeben +tutorial.geometry.upload.context: "{fixed} verhindert, dass der Garbage Collector das Array verschiebt, während seine Adresse verwendet wird. Bei diesem CPU-beschreibbaren Puffer mappt {upload} den Speicher, kopiert die Daten und hebt das Mapping vor der Rückkehr auf. Das Array muss danach nicht fixiert bleiben. Der Puffer muss während des gesamten Renderings gültig bleiben. Da sich die Scheitelpunkte nicht ändern, genügt ein einmaliger Upload." +tutorial.geometry.upload.description: "Das verwaltete Array besteht aus CPU-Daten. Ein {buffer} stellt der GPU Speicherplatz zur Verfügung, aus dem sie die Scheitelpunkte lesen kann. Fügen Sie nach dem Array Folgendes hinzu:" +tutorial.geometry.upload.details: "Die Gesamtgröße beträgt {sizeofVertexVerticesLength}: 28 Bytes pro Scheitelpunkt, drei Scheitelpunkte, insgesamt 84 Bytes. {bufferUsagesVertex} erlaubt den Zugriff als Scheitelpunkteingabe. {cpuWriteOnly} ermöglicht es der CPU, diesen kleinen Puffer direkt zu initialisieren. Der Stride des Deskriptors erfasst die Elementgröße; das weiter unten erstellte Eingabelayout teilt dem Scheitelpunktabruf mit, wie die einzelnen Attribute zu lesen sind." +tutorial.geometry.upload.guidance: Das Erstellen eines Puffers befüllt ihn nicht. {upload} kopiert das Array ab dem Ziel-Byte-Offset 0 in diese Zuweisung. Seine Quellbeschreibung liefert einen Zeiger und die Anzahl der zu kopierenden Bytes. +tutorial.geometry.upload.notes: Fügen Sie {vertexBufferDispose} unmittelbar vor {swapChainDispose} in die Bereinigung am Ende von {programCs} ein. Für größere statische Geometrien erklärt {link}, wann stattdessen reiner GPU-Speicher und Transfer-Uploads gewählt werden sollten. +tutorial.geometry.upload.notes.link: Ressourcenverwaltung +tutorial.geometry.upload.title: Einen Puffer zuweisen und das Array hochladen +tutorial.input.description: "Die Scheitelpunkt-Bytes und Shader sind bereit. Beschreiben Sie als Nächstes, wie die GPU jeden Scheitelpunkt lesen soll. Ein Attribut ist ein einzelner Wert, wie etwa Position oder Farbe. Das Eingabelayout weist jedem Attribut ein Format und einen Byte-Offset zu; der Stride gibt den Abstand in Bytes von einem Scheitelpunkt zum nächsten an. Fügen Sie diesen Initialisierungsblock nach der Shader-Erstellung ein:" +tutorial.input.details: "{inputLayoutAdd} hängt ein Element am aktuellen Stride an und erhöht diesen Stride um die Größe des Elements. Es überprüft die C#-Struktur nicht. Hier erzeugt es die folgende Übereinstimmung zwischen CPU-Speicher und Shader-Eingaben:" +tutorial.input.guidance: "Eine Änderung der C#-Feldreihenfolge oder des Paddings ohne Anpassung dieser Beschreibung würde die GPU falsche Bytes lesen lassen. Der Standardwert von {semanticIndex} ist 0 und entspricht {pOSITION0} und {cOLOR0}. Beide Elemente gehören zum selben Puffer. Deshalb enthält die Pipeline ein Eingabelayout, und wir binden den Puffer an Slot 0." +tutorial.input.table.headings.byteOffset: Byte-Offset +tutorial.input.table.headings.cField: "C#-Feld" +tutorial.input.table.headings.format: Format +tutorial.input.table.headings.shaderInput: Shader-Eingabe +tutorial.input.table.nextVertex.cField: Nächster Scheitelpunkt +tutorial.input.table.nextVertex.format: "Gesamter Stride: 28 Bytes" +tutorial.input.table.nextVertex.shaderInput: Nächster Eingabedatensatz +tutorial.input.table.vertexColor.format: "{float4} (16 Bytes)" +tutorial.input.table.vertexPosition.format: "{float3} (12 Bytes)" +tutorial.input.title: Das Scheitelpunkteingabelayout beschreiben +tutorial.lifecycle.description: "Die fertige Anwendung wiederholt diese Abfolge:" +tutorial.lifecycle.details: "Das Schließen des Fensters beendet {run}. Jeder gerenderte Frame hat bereits darauf gewartet, dass seine GPU-Arbeit abgeschlossen ist, sodass wir nun die von ihm verwendeten Ressourcen freigeben können. Die Bereinigung nach {windowRun} sollte wie folgt aussehen:" +tutorial.lifecycle.guidance: "Geben Sie die Swapchain vor ihrem nativen Fenster und den Kontext nach all seinen Ressourcen frei. Die Warteschlange besitzt und recycelt eingereichte Befehlspuffer; die Swapchain besitzt ihre Ausgabetextur. Für diese Befehlspuffer und die Ausgabetextur ist in dieser Anwendung kein eigener {dispose}-Aufruf nötig." +tutorial.lifecycle.title: Den Lebenszyklus eines Frames verfolgen +tutorial.pipeline.behavior: "Fügen Sie nach dem Eingabelayout Folgendes hinzu:" +tutorial.pipeline.context: "{cullNone} füllt das Dreieck aus, ohne eine der beiden Flächenorientierungen zu verwerfen. Die Reihenfolge seiner Scheitelpunkte bestimmt die Flächenwindung; durch Deaktivieren des Cullings wird verhindert, dass diese Reihenfolge unser erstes Dreieck verbirgt." +tutorial.pipeline.description: Wir haben nun Scheitelpunktdaten, ein Eingabelayout und zwei Shader. Die {graphicsPipeline} verbindet sie und gibt an, wie die GPU Scheitelpunkte zu Primitiven zusammensetzt und das Ergebnis in ein Attachment schreibt. +tutorial.pipeline.details: "Eine Pipeline kombiniert programmierbare Shader-Stufen mit Festfunktionseinstellungen, die GPU-Operationen wie Dreieckszusammensetzung, Face-Culling und Blending steuern. Wählen Sie für dieses Dreieck die folgenden Einstellungen:" +tutorial.pipeline.guidance: Das Farbformat stammt aus {swapChainDescFormat}. Es muss mit dem vom Renderpass verwendeten Bild übereinstimmen. {count1} bedeutet ein Sample pro Pixel. +tutorial.pipeline.item: "{triangleList} setzt jeweils drei aufeinanderfolgende Scheitelpunkte zu einem Dreieck zusammen. Wir übergeben drei Scheitelpunkte und zeichnen einmal, sodass kein Indexpuffer benötigt wird." +tutorial.pipeline.notes: "{depthNone} deaktiviert Tiefentests und -schreiben, passend zum Pass ohne Tiefen-Attachment." +tutorial.pipeline.reference: "{opaque} deaktiviert das Blending, sodass die Farbe des Fragment-Shaders den Hintergrund innerhalb des Dreiecks ersetzt." +tutorial.pipeline.title: Shader und Scheitelpunktlayout verbinden +tutorial.pipeline.usage: Die Shader-Objekte können nach dem Erstellen der Pipeline freigegeben werden, wie im Beispiel-Renderer gezeigt. Halten Sie die Pipeline selbst für jeden Frame gültig, der mit ihr zeichnet. Fügen Sie {pipelineDispose} vor {vertexBufferDispose} in die Bereinigung ein. Die Pipeline-Erstellung ist der letzte Initialisierungsschritt vor dem Render-Callback. +tutorial.pipeline.validation: Die Pipeline-Beschreibung deklariert die Attachment-Konfiguration; sie erstellt kein weiteres Bild. {inputLayouts} enthält einen Eintrag, da Position und Farbe zusammen in einem Puffer gespeichert sind. +tutorial.presentation.title: Die GPU mit dem Fenster verbinden +tutorial.project.context: Aktivieren Sie {emphasis} ({allowUnsafeBlocks}) in den Buildeinstellungen des Projekts. Wir verwenden dies, um Scheitelpunktdaten an die GPU zu übergeben, sowie für die nativen Aufrufe des Fenster-Helpers. +tutorial.project.context.emphasis: Unsicheren Code zulassen +tutorial.project.description: "Erstellen Sie das Projekt und wechseln Sie in dessen Verzeichnis:" +tutorial.project.details: "Installieren Sie die Pakete:" +tutorial.project.guidance: "{zenithNET} stellt die gemeinsame Rendering-API bereit. Die drei Backend-Pakete ermöglichen es demselben Programm, die Implementierung für seine Plattform auszuwählen. {zenithNETCompiler} kompiliert Slang-Shader – die kleinen GPU-Programme, die wir später schreiben – für diese Implementierung. Silk.NET liefert das Fenster und die Ereignisschleife." +tutorial.project.title: Konsolenprojekt erstellen +tutorial.requirements.context: Sie können dieser Seite von einem leeren Projekt aus folgen. Das {link} und sein {detail} stehen als Referenz für die hier verwendeten Rendering- und Fenster-APIs zur Verfügung. +tutorial.requirements.context.detail: gemeinsamer Host +tutorial.requirements.context.link: Hallo-Dreieck-Beispiel +tutorial.requirements.description: "Sie benötigen das {emphasis}, einen Code-Editor oder eine IDE sowie einen Desktop-PC mit einer GPU und einem Treiber, die von einem Zenith.NET-Backend unterstützt werden. Grundlegende Vertrautheit mit C# genügt; die Grafikkonzepte werden bei ihrer ersten Verwendung eingeführt. Dies ist ein gewöhnliches {net10}-Konsolenprojekt. Ein Backend übersetzt Zenith.NET-Operationen in Aufrufe einer Grafik-API wie DirectX 12, Metal oder Vulkan. Die Anwendung wählt beim Start eines davon aus:" +tutorial.requirements.description.emphasis: .NET 10 SDK +tutorial.requirements.details: Linux benötigt eine X11-kompatible Fenstersitzung für den hier verwendeten Fensterpfad. Optionale Raytracing- und Mesh-Shading-Funktionen sind für dieses Dreieck nicht erforderlich. +tutorial.requirements.guidance: Zenith.NET rendert in eine von der Anwendung bereitgestellte Oberfläche. Silk.NET.Windowing erstellt das Desktop-Fenster und verarbeitet dessen Ereignisse. Unter macOS ist das Präsentationsziel ein Metal-Layer ({cAMetalLayerCs}); der Fenster-Helper des Tutorials bindet diesen Layer für uns ein. +tutorial.requirements.table.headings.graphicsBackend: Grafik-Backend +tutorial.requirements.table.headings.platform: Plattform +tutorial.requirements.table.headings.windowSurface: Fensteroberfläche +tutorial.requirements.table.linux.graphicsBackend: Vulkan 1.4 +tutorial.requirements.table.linux.platform: Linux +tutorial.requirements.table.linux.windowSurface: X11-Fenster und Display; XWayland ist ebenfalls geeignet +tutorial.requirements.table.macOS.graphicsBackend: Metal 4 +tutorial.requirements.table.macOS.platform: macOS +tutorial.requirements.table.macOS.windowSurface: An das Fenster angebundener Metal-Layer +tutorial.requirements.table.windows.graphicsBackend: DirectX 12 +tutorial.requirements.table.windows.platform: Windows +tutorial.requirements.table.windows.windowSurface: Win32-Fenster-Handle +tutorial.requirements.title: Bevor Sie beginnen +tutorial.resize.context: "Führen Sie {dotnetRun} erneut aus. Das Fenster sollte nun einen einheitlichen dunklen Hintergrund haben, der es auch nach einer Größenänderung weiterhin vollständig ausfüllt. Behalten Sie diesen Callback bei: Das Dreieck wird innerhalb seines bestehenden Renderpasses gezeichnet." +tutorial.resize.description: "Die Bilder der Swapchain müssen den Framebuffer-Abmessungen folgen. Verwenden Sie {framebufferResize}, um auf Änderungen der Pixelgröße zu reagieren, einschließlich Änderungen durch Anzeigeskalierung. Fügen Sie nach dem Render-Callback, weiterhin vor {windowRun}, Folgendes hinzu:" +tutorial.resize.details: Silk.NET unterscheidet Fenstergrößenänderungen von {link}. Wir benötigen Letzteres, da die Swapchain Pixel speichert. Ein minimiertes Fenster kann einen Framebuffer der Größe null haben. Beide Callbacks überspringen in diesem Fall ihre GPU-Arbeit. Nach einer Größenänderung verwendet der Renderpass die neuen Attachment-Abmessungen für seinen Viewport und Scissor. +tutorial.resize.details.link: Framebuffer-Größenänderungen +tutorial.resize.guidance: Wir warten nach jeder Übermittlung, sodass kein früherer Frame die Bilder mehr verwendet, wenn der Resize-Handler sie ersetzt. Die aktuelle Implementierung von {present} wartet ebenfalls auf der Grafikwarteschlange. Diese einfache Schleife stellt sicher, dass die Arbeit eines Frames abgeschlossen ist, bevor der nächste beginnt; {link} behandelt fortgeschrittenere Ablaufsteuerungen. +tutorial.resize.guidance.link: Synchronisation +tutorial.resize.title: Auf Größenänderungen reagieren +tutorial.shaders.compilation.context: Die Kompilierung erfolgt einmalig während der Initialisierung. {appContextBaseDirectory} findet den kopierten Shader neben der ausführbaren Datei, unabhängig vom aktuellen Arbeitsverzeichnis. Diese Shader verarbeiten nur Scheitelpunkteingaben, daher müssen noch keine Konstantenpuffer, Texturen oder Ressourcen-Handles gebunden werden. +tutorial.shaders.compilation.description: Legen Sie in den Dateieigenschaften für {triangleSlang} die Option {emphasis} auf {detail} fest. Dadurch wird der Shader neben der ausführbaren Datei verfügbar gemacht. +tutorial.shaders.compilation.description.detail: Kopieren, wenn neuer +tutorial.shaders.compilation.description.emphasis: In Ausgabeverzeichnis kopieren +tutorial.shaders.compilation.details: "Kehren Sie zu {programCs} zurück. Fügen Sie nach dem Scheitelpunkt-Upload diese Initialisierungsanweisungen vor dem Render-Callback ein:" +tutorial.shaders.compilation.guidance: "{zenithCompiler} gibt eine Shader-Beschreibung zurück, die Code für die angeforderte Grafik-API enthält. {createShader} erstellt das entsprechende Backend-Objekt. Sowohl die Grafik-API als auch die Namen der Einstiegspunkte sind wichtig: Verwenden Sie {contextGraphicsApi} und schreiben Sie {vSMain} und {fSMain} exakt so wie in der Slang-Datei." +tutorial.shaders.compilation.title: Für das ausgewählte Backend kompilieren +tutorial.shaders.context: "{fSInput} verbindet die Ausgabe des Vertex-Shaders mit der Eingabe des Fragment-Shaders. Wenn es vom Vertex-Shader geschrieben wird, liefert {sVPOSITION} eine Clip-Space-Position: die vier Koordinaten, anhand derer die GPU bestimmt, was innerhalb des sichtbaren Bildes liegt. {cOLOR0} überträgt die zwischen den Scheitelpunkten zu interpolierende Farbe. Beide Stufen müssen hinsichtlich Typ und Semantik übereinstimmen." +tutorial.shaders.description: Ein Shader ist ein von der GPU ausgeführtes Programm. Dieser Zeichenvorgang benötigt einen Vertex-Shader zur Positionierung der Scheitelpunkte und einen Fragment-Shader zur Erzeugung der Farben innerhalb des Dreiecks. Wir werden sie in Slang schreiben, einer Shader-Sprache, und zwei Einstiegspunkte aus derselben Datei kompilieren. Ein Einstiegspunkt ist die Funktion, an der die Ausführung einer Shader-Stufe beginnt. +tutorial.shaders.details: "Erstellen Sie {triangleSlang}, beginnend mit diesen beiden Strukturen:" +tutorial.shaders.fragment.description: "Fügen Sie den Fragment-Einstiegspunkt an dieselbe Datei an:" +tutorial.shaders.fragment.details: Die Rasterung bestimmt, welche Bildbereiche das Dreieck abdeckt. Sie erzeugt Fragmente – die vom Fragment-Shader verarbeiteten Daten – mit über den abgedeckten Bereich interpolierten Scheitelpunktfarben. {fSMain} gibt diese interpolierte Farbe über {sVTARGET} zurück, was das erste Farb-Attachment identifiziert. +tutorial.shaders.fragment.guidance: Die Interpolation der Scheitelpunktfarben ist getrennt vom Blending der Attachments zu betrachten. Blending kombiniert die Ausgabe eines Fragments mit der bereits im Attachment gespeicherten Farbe. Unser opaker Blend-Zustand deaktiviert diese Kombination, sodass die interpolierte Farbe den Hintergrund innerhalb des Dreiecks ersetzt. +tutorial.shaders.fragment.title: Die Fragmente einfärben +tutorial.shaders.guidance: "{vSInput} beschreibt, was der Vertex-Shader aus dem Scheitelpunktpuffer empfängt. Die Semantiken {pOSITION0} und {cOLOR0} identifizieren die Eingaben; C#-Feldnamen allein begründen diese Zuordnung nicht." +tutorial.shaders.title: Die beiden Shader-Stufen schreiben +tutorial.shaders.vertex.description: "Fügen Sie den Vertex-Einstiegspunkt an {triangleSlang} an:" +tutorial.shaders.vertex.details: Die GPU ruft diesen Einstiegspunkt für jeden Eingabescheitelpunkt auf. Er fügt der Position die homogene Koordinate {w} hinzu und leitet die Farbe weiter. Nach der Vertex-Stufe wird die Position durch w geteilt; hier lässt diese Division x, y und z unverändert. Aus diesem Grund können die oben gewählten Positionen direkt als normalisierte Gerätekoordinaten verstanden werden. +tutorial.shaders.vertex.title: Jeden Scheitelpunkt positionieren +tutorial.surface.description: "Der Kontext muss auch wissen, wo er seine Ausgabe anzeigen soll. Fügen Sie Folgendes {emphasis} hinzu:" +tutorial.surface.description.emphasis: nach {windowCenter} und vor {windowRun} +tutorial.surface.details: "{surface} beschreibt ein natives Präsentationsziel und seine Pixelabmessungen. Der Framebuffer ist das mit dem Fenster verknüpfte Pixelbild. {framebufferSize} gibt seine Abmessungen in Pixeln an; die logischen Abmessungen des Fensters können abweichen, wenn die Anzeigeskalierung aktiviert ist." +tutorial.surface.guidance: Die Oberfläche entspricht dem oben ausgewählten Backend. Windows liefert ein Fenster-Handle, Linux liefert ein X11-Display und -Fenster, und der macOS-Helper stellt den angebundenen Metal-Layer bereit. Dies ist der einzige plattformspezifische Teil der Verbindung unseres Fensters mit dem Rendering. +tutorial.surface.title: Die native Oberfläche beschreiben +tutorial.swapChain.context: "Die Swapchain verwendet sowohl den Kontext als auch das native Fenster. Ersetzen Sie die Zeile {windowDispose} am Ende von {programCs} durch diese Bereinigungsreihenfolge:" +tutorial.swapChain.description: "Verwenden Sie die Oberflächenbeschreibung, um die Bilder zu erstellen, die präsentiert werden sollen. Fügen Sie unmittelbar nach dem Oberflächenblock Folgendes hinzu:" +tutorial.swapChain.details: Die {swapChain} verwaltet die im Fenster angezeigten Bilder. In jedem Frame liefert uns {drawable} das aktuelle Bild als {texture}, den API-Typ für Bilddaten. Nach dem Zeichnen fordert {present} die Anzeige des Ergebnisses an und wechselt zum nächsten Drawable. +tutorial.swapChain.guidance: "{b8G8R8A8UNorm} speichert vier 8-Bit-Farbkanäle in der Reihenfolge Blau, Grün, Rot und Alpha. {uNorm} bedeutet, dass ganzzahlige Werte von 0 bis 255 Werte von 0 bis 1 darstellen. Der Shader gibt weiterhin einen logischen RGBA-Wert zurück; dieses Format bestimmt, wie diese Kanäle im Bild gespeichert werden. Später wird die Grafikpipeline {swapChainDescFormat} verwenden, um dieses Attachment abzugleichen." +tutorial.swapChain.title: Die Swapchain erstellen +tutorial.title: Erstes Dreieck +tutorial.troubleshooting.description: "Lesen Sie zuerst jeden Fehler in der Konsole und nutzen Sie dann die früheren Kontrollpunkte, um die fehlgeschlagene Stufe zu identifizieren:" +tutorial.troubleshooting.details: "Verwenden Sie den {link} und den {detail}, um Scheitelpunktdaten, Eingabelayout und Zeichenoperation zu vergleichen. Das Beispiel organisiert Fensterverwaltung und Einreichung in einem gemeinsamen Host; dieses Tutorial hält den Anwendungsablauf in {programCs}. Fahren Sie mit {context} fort, um indexiertes Zeichnen, Transformationen und Tiefentests kennenzulernen." +tutorial.troubleshooting.details.context: Rotierender Würfel +tutorial.troubleshooting.details.detail: Slang-Shader +tutorial.troubleshooting.details.link: Beispiel-Renderer +tutorial.troubleshooting.table.backend.check: Überprüfen Sie, ob das ausgewählte Backend vom Gerät und dem installierten Grafiktreiber unterstützt wird. +tutorial.troubleshooting.table.backend.symptom: Backend-Erstellung schlägt fehl +tutorial.troubleshooting.table.drawing.check: Überprüfen Sie die Upload-Größe, das Eingabelayout, die Pipeline-Auswahl und die Platzierung der Zeichenbefehle innerhalb des Renderpasses. +tutorial.troubleshooting.table.drawing.symptom: Der Hintergrund erscheint, aber das Dreieck nicht +tutorial.troubleshooting.table.headings.check: Prüfung +tutorial.troubleshooting.table.headings.symptom: Symptom +tutorial.troubleshooting.table.input.check: Überprüfen Sie den Stride von 28 Bytes und die Positions-/Farboffsets von 0 und 12. +tutorial.troubleshooting.table.input.symptom: Scheitelpunktpositionen oder -farben sind fehlerhaft +tutorial.troubleshooting.table.shaders.check: Überprüfen Sie die kopierte Datei {triangleSlang}, die Schreibweise des Einstiegspunkts und die vom Compiler gemeldete Diagnose. +tutorial.troubleshooting.table.shaders.symptom: Der Schritt mit der Hintergrundfarbe funktioniert, aber das Laden der Shader schlägt fehl +tutorial.troubleshooting.table.window.check: Bestätigen Sie, dass das .NET-Projekt kompiliert wird und der reine Fensterschritt in einer Desktop-Sitzung ausgeführt wird. Überprüfen Sie unter Linux, ob X11 oder XWayland verfügbar ist. +tutorial.troubleshooting.table.window.symptom: Es öffnet sich kein Fenster +tutorial.troubleshooting.title: Die fehlgeschlagene Stufe überprüfen +tutorial.window.context: "{usingZenithTutorials} importiert den Namespace des Helpers. Jede C#-Datei verwendet ihre eigenen gewöhnlichen using-Direktiven, sodass der Interop-Import in beiden Dateien benötigt wird. Der Alias {buffer} verweist auf den Zenith.NET-Puffertyp und unterscheidet ihn von {systemBuffer}." +tutorial.window.description: Fügen Sie dem Projekt {cocoaHelperCs} hinzu und behalten Sie dessen Namespace bei. Fügen Sie {interopUsing} ganz oben in dieser Datei vor der Namespace-Deklaration ein. Der Helper bindet unter macOS einen Metal-Layer an das Fenster an; die anderen Plattformzweige rufen ihn nicht auf. +tutorial.window.details: "Ersetzen Sie die generierte {programCs} durch den folgenden Code. Sie verwendet Top-Level-Anweisungen, die der Reihe nach ohne explizite {main}-Methode ausgeführt werden. Spätere Abschnitte erläutern, an welchen Stellen Sie dieser Datei weiteren Code hinzufügen:" +tutorial.window.guidance: "{graphicsAPINone} weist Silk.NET an, ein Fenster ohne eigenen Grafikkontext zu erstellen. Wir werden diesen Kontext mit Zenith.NET erstellen. {initialize} erstellt das native Fenster und macht dessen Handles verfügbar. Ein Handle ist ein vom Fenstersystem bereitgestellter Bezeichner. {center} zentriert das Fenster, und {run} verarbeitet Ereignisse, bis es geschlossen wird. Die Ausführung fährt dann mit {dispose} fort, wodurch das Fenster freigegeben wird." +tutorial.window.notes: Führen Sie {dotnetRun} aus. Ein leeres Fenster sollte sich öffnen und auf Verschieben, Größenänderungen und Schließen reagieren. Sein Inhalt ist noch nicht definiert, da wir noch keine Rendering-Befehle eingereicht haben. Schließen Sie es, bevor Sie fortfahren. +tutorial.window.title: Ein Fenster öffnen +ui.action.copy: Kopieren +ui.action.navigate: Navigieren +ui.action.open: Öffnen +ui.action.source: Quellcode anzeigen +ui.api.browse: Namespaces und Typen durchsuchen. +ui.api.clearTypeSearch: Typsuche löschen +ui.api.findType: Typ suchen +ui.api.loadError: Typen konnten nicht geladen werden. Laden Sie diese Seite neu, um es erneut zu versuchen. +ui.api.loadingNamespaces: Namespaces werden geladen… +ui.api.loadingTypes: Typen werden geladen… +ui.api.matchingTypes: Passende Typen +ui.api.namespace: Namespace +ui.api.namespaces: Namespaces +ui.api.noNamespaceTypes: Keine Typen in diesem Namespace. +ui.api.noTypes: Keine passenden Typen. +ui.api.types: Typen +ui.content.reference: Referenz +ui.content.source: Quellcode +ui.content.tutorial: Tutorial +ui.contents.close: Inhaltsverzeichnis schließen +ui.contents.open: Inhaltsverzeichnis öffnen +ui.contents.title: Inhalt +ui.footer.caption: Modernes RHI für .NET. +ui.footer.label: Fußzeile +ui.language.label: Sprache +ui.language.unavailable: Nicht übersetzt +ui.members.clear: Membersuche löschen +ui.members.close: Member-Suche schließen +ui.members.empty: Keine passenden Member. +ui.members.open: Zum Member wechseln +ui.members.placeholder: Name oder Signatur… +ui.members.search: Member suchen +ui.members.title: Member suchen +ui.members.undeclared: Dieser Typ hat keine deklarierten Member. +ui.navigation.api: API +ui.navigation.concepts: Konzepte +ui.navigation.home: Startseite +ui.navigation.label: Hauptnavigation +ui.navigation.toggle: Navigation umschalten +ui.outline.title: Auf dieser Seite +ui.reference.assembly: Assembly +ui.reference.classes: Klassen +ui.reference.constructors: Konstruktoren +ui.reference.declaration: "C#-Typdeklaration" +ui.reference.delegates: Delegaten +ui.reference.derived: Abgeleitete Typen +ui.reference.enums: Enumerationen +ui.reference.events: Ereignisse +ui.reference.examples: Beispiele +ui.reference.exceptions: Ausnahmen +ui.reference.extensionMethods: Erweiterungsmethoden +ui.reference.fields: Felder +ui.reference.implementations: Explizite Schnittstellenimplementierungen +ui.reference.implements: Implementiert +ui.reference.inheritance: Vererbung +ui.reference.inheritedMembers: Geerbte Member +ui.reference.interfaces: Schnittstellen +ui.reference.metadata: Typ-Metadaten +ui.reference.methods: Methoden +ui.reference.namespace: Namespace +ui.reference.open: Referenz für {name} öffnen +ui.reference.operators: Operatoren +ui.reference.parameters: Parameter +ui.reference.properties: Eigenschaften +ui.reference.related: Siehe auch +ui.reference.relationships: Vererbung und Metadaten +ui.reference.remarks: Hinweise +ui.reference.returns: Rückgabe +ui.reference.structs: Strukturen +ui.reference.typeParameters: Typparameter +ui.reference.value: Wert +ui.reference.values: Werte +ui.search.close: Suche schließen +ui.search.empty: Keine Ergebnisse für „{query}“. +ui.search.hint: Tutorials, Konzepte, Beispiele und die API-Referenz durchsuchen. +ui.search.loading: Suche wird geladen… +ui.search.more: Weitere Ergebnisse anzeigen +ui.search.pending: Suche läuft… +ui.search.placeholder: Wonach suchen Sie? +ui.search.resultCount: "Ergebnisse: {count}" +ui.search.title: Dokumentation durchsuchen +ui.search.unavailable: Die Suche ist nicht verfügbar. Sie können weiterhin die folgenden Seiten aufrufen. diff --git a/documents/locales/es-ES/strings.yml b/documents/locales/es-ES/strings.yml new file mode 100644 index 00000000..f06c8ab7 --- /dev/null +++ b/documents/locales/es-ES/strings.yml @@ -0,0 +1,604 @@ +### YamlMime:Resources +concepts.execution.context.description: Un {graphicsContext} representa un dispositivo de backend y proporciona sus colas de gráficos, cálculo y transferencia. Cree los búferes, texturas, sombreadores y canalizaciones para una carga de trabajo a través del mismo contexto. Un recurso o identificador creado por otro contexto no se puede vincular simplemente a los búferes de comandos de este. +concepts.execution.context.details: Elija el backend para la plataforma y la superficie de presentación. La API sigue siendo compartida, pero la compatibilidad del dispositivo sigue siendo importante. {capabilities} expone el nombre del dispositivo y los indicadores {rayTracingSupported} y {meshShadingSupported}. Compruebe el indicador correspondiente antes de crear una carga de trabajo opcional, como hacen los ejemplos {link} y {detail}. Estos indicadores no son una lista completa de restricciones de formato, memoria o plataforma. +concepts.execution.context.details.detail: sombreado de mallas +concepts.execution.context.details.link: trazado de rayos +concepts.execution.context.title: El contexto conecta recursos y colas +concepts.execution.description: Una aplicación de Zenith.NET crea recursos de GPU, graba comandos que los utilizan y envía esos comandos a una cola. La CPU puede continuar mientras la GPU ejecuta el envío. Mantenga los recursos válidos hasta que finalice ese trabajo, incluso después de que las llamadas de grabación hayan regresado. +concepts.execution.ownership.description: "Aquí, la propiedad significa responsabilidad de liberación. Una referencia de C# mantiene accesible un objeto administrado; no evita que un {dispose} explícito destruya el recurso nativo. Del mismo modo, enviar un comando que utiliza un búfer no transfiere la propiedad de ese búfer a la cola." +concepts.execution.ownership.details: Al apagar, deje de enviar nuevo trabajo, espere los últimos usos en cada cola involucrada, libere los recursos de la aplicación y luego libere el contexto. La liberación del contexto libera sus propias colas y asistentes internos; no espera todo el trabajo de la aplicación ni libera cada recurso que la aplicación creó. +concepts.execution.ownership.guidance: Aplique las mismas reglas de tiempo de vida durante el renderizado. Conserve el valor de finalización del último uso de un recurso para saber cuándo se pueden sobrescribir sus bytes o reemplazar el recurso. Consulte {link} para obtener información sobre vistas y tiempos de vida de recursos de respaldo. +concepts.execution.ownership.guidance.link: Administración de recursos +concepts.execution.ownership.table.applicationResources.object: Recursos creados por la aplicación +concepts.execution.ownership.table.applicationResources.ownership: La aplicación los libera después de su último uso en la GPU. +concepts.execution.ownership.table.commandBuffers.object: Búferes de comandos prestados +concepts.execution.ownership.table.commandBuffers.ownership: La cola los gestiona y los recicla. +concepts.execution.ownership.table.headings.object: Objeto +concepts.execution.ownership.table.headings.ownership: ¿Quién lo libera? +concepts.execution.ownership.table.queues.object: Colas de contexto y sus líneas de tiempo +concepts.execution.ownership.table.queues.ownership: El contexto y las colas los gestionan. +concepts.execution.ownership.table.swapChainDrawable.ownership: La cadena de intercambio lo gestiona. +concepts.execution.ownership.title: Mantener la propiedad separada de la finalización en la GPU +concepts.execution.pipelines.description: "Una canalización de gráficos combina sombreadores, el diseño de entrada de vértices, la regla para ensamblar vértices en primitivas, formatos de adjuntos y estado de renderizado. Establézcala antes de enlazar datos de vértices, índices o constantes y de emitir comandos de dibujo. Sus formatos de adjuntos y recuento de muestras deben coincidir con los adjuntos de la pasada de renderizado." +concepts.execution.pipelines.details: Una canalización de cálculo proporciona el punto de entrada del sombreador para un dispatch, que inicia grupos de subprocesos de GPU. Establézcala y configure sus constantes antes del dispatching. Los dispatches de cálculo pertenecen a fuera de las pasadas de renderizado gráfico. Cambiar la canalización es un cambio en la forma en que los comandos posteriores interpretan sus entradas; enlace los datos requeridos por la canalización seleccionada antes de usarla. +concepts.execution.pipelines.guidance: "La {link} muestra la secuencia gráfica completa. El {detail} graba un dispatch seguido de una pasada gráfica que muestra el resultado." +concepts.execution.pipelines.guidance.detail: ejemplo de cálculo +concepts.execution.pipelines.guidance.link: devolución de llamada de renderizado del triángulo +concepts.execution.pipelines.title: Una canalización determina cómo interpretan los datos los comandos +concepts.execution.queues.description: Comience con {graphicsQueue} cuando un fotograma combine dibujo, cálculo y copias. Mantener el trabajo dependiente en una cola facilita seguir su ordenación. +concepts.execution.queues.details: Una cola acepta lotes de comandos para su ejecución. Las colas separadas no corresponden necesariamente a motores de hardware independientes, por lo que su trabajo podría no ejecutarse simultáneamente. Utilice otra cola cuando la carga de trabajo pueda beneficiarse de la superposición y agregue una dependencia explícita cuando una cola consuma los resultados de otra cola. +concepts.execution.queues.guidance: Cuando los comandos posteriores dependen de escrituras anteriores, la aplicación también debe asegurarse de que esas escrituras estén disponibles para los comandos posteriores. Enviar ambos búferes de comandos a la misma cola no establece automáticamente cada dependencia de este tipo. Los comandos pueden usar diferentes etapas de GPU, y los accesos posteriores pueden necesitar una barrera o una transición de textura. {link} explica la distinción entre el orden de envío y la visibilidad de los recursos. +concepts.execution.queues.guidance.link: Sincronización +concepts.execution.queues.table.computeQueue.workToRecord: Dispatches de cálculo y trabajo de transferencia compatible, sin pasadas de renderizado gráfico. +concepts.execution.queues.table.graphicsQueue.workToRecord: Pasadas de renderizado y dibujo, más operaciones de cálculo y transferencia utilizadas por el fotograma. +concepts.execution.queues.table.headings.queue: Cola +concepts.execution.queues.table.headings.workToRecord: Trabajo a grabar +concepts.execution.queues.table.transferQueue.workToRecord: Trabajo de carga, descarga y copia, sin dibujo ni dispatches de cálculo. +concepts.execution.queues.title: Elegir una cola para el trabajo que ejecutará +concepts.execution.recording.context: La cola sondea la finalización y recicla los búferes de comandos terminados. Llame a {queueCommandBuffer} para cada nueva grabación; puede devolver una instancia reciclada. No libere un búfer de comandos prestado, no lo envíe dos veces ni continúe grabando en él después del envío. Grabe un búfer de comandos determinado desde un solo subproceso a la vez; el bloqueo interno de la cola no protege contra modificaciones simultáneas en un búfer de comandos. +concepts.execution.recording.description: "{queueCommandBuffer} devuelve un {commandBuffer} con la grabación ya iniciada. Grabe los comandos y sus dependencias, luego llame a {submit} una vez. El envío finaliza la grabación y devuelve un {timelineValue} que identifica un punto de finalización en esa cola." +concepts.execution.recording.details: "Por ejemplo, después de grabar un fotograma en {commandBuffer}, el triángulo lo envía y espera a que se complete con:" +concepts.execution.recording.guidance: "{submit} programa el trabajo; {wait} evita que la CPU continúe hasta que se haya completado ese envío. Grabar un dibujo, finalizar una pasada de renderizado y enviar un búfer de comandos son operaciones independientes. Ni grabar el dibujo ni finalizar la pasada esperan a la GPU." +concepts.execution.recording.title: La grabación no ejecuta comandos +concepts.execution.title: Modelo de ejecución +concepts.platforms.description: Elija si su aplicación posee la ventana nativa y el bucle de fotogramas o si utiliza un control de renderizado de interfaz de usuario. Esa elección determina quién obtiene la textura de salida, envía comandos y presenta el resultado. La textura de salida es la textura utilizada como salida del fotograma actual. El trabajo de gráficos y cálculo fuera de pantalla no necesita una ventana ni una cadena de intercambio. +concepts.platforms.frame.context: Agregue sus enlaces de canalización y comandos de dibujo dentro de esa pasada. Finalice la pasada antes de regresar. No envíe el búfer de comandos suministrado ni presente de forma independiente, y no libere el búfer de comandos ni la textura de salida. Si su controlador utiliza la textura de salida en otro layout, devuélvala a {colorAttachment} para la transición final del control. +concepts.platforms.frame.description: Las integraciones implementan {iZenithView}. La aplicación suministra su {graphicsContext}, actualiza datos de escena en {updateRequested} y graba el renderizado en {renderRequested} mediante {renderEventArgs}. +concepts.platforms.frame.details: "El control gestiona el ciclo completo de cada fotograma. Obtiene la textura de salida y el búfer de comandos, cambia la textura a {colorAttachment}, invoca los controladores de eventos y realiza el envío y la presentación que requiere el framework." +concepts.platforms.frame.guidance: "Para un {iZenithView} inicializado llamado {view}, con un contexto asignado, este controlador graba una pasada de borrado completa. Requiere {usingZenithNET}:" +concepts.platforms.frame.notes: Los controles pasan de {undefined} al inicio de cada fotograma, por lo que las aplicaciones no pueden depender de que se conserve el contenido anterior de la textura de salida. Borre o renderice la imagen requerida en cada fotograma. Mantenga la acumulación persistente o el renderizado almacenado en caché en una textura propiedad de la aplicación y luego muestre esa textura a través de la vista. +concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat} suministra el formato de color predeterminado de las integraciones. Compruebe la textura de salida real del evento al hacer coincidir los formatos de adjuntos, los recuentos de muestras y las dimensiones." +concepts.platforms.frame.title: Grabar en el fotograma suministrado por un control de interfaz de usuario +concepts.platforms.integration.context: WinForms, WPF y la ruta de WinUI de Windows requieren Windows. Las aplicaciones MAUI necesitan la carga de trabajo de su plataforma de destino y deben registrar el controlador del control con {useZenithView}; consulte {extensionsCs}. Se deben cumplir tanto la compatibilidad del marco como la del backend. +concepts.platforms.integration.description: "Los controles comparten la interfaz de eventos, pero no todos presentan de la misma manera:" +concepts.platforms.integration.details: La lectura de mapas de bits (bitmap readback) copia los píxeles renderizados en la memoria de la CPU antes de que la interfaz de usuario los muestre. La interoperabilidad de texturas compartidas evita esa lectura, pero aún puede requerir copias y sincronización de GPU. Por lo tanto, la interfaz {renderRequested} compartida no implica costos de presentación idénticos o requisitos de interoperabilidad nativa iguales. +concepts.platforms.integration.guidance: "Utilice el paquete para el marco de la aplicación; por ejemplo:" +concepts.platforms.integration.table.avalonia.integration: Avalonia +concepts.platforms.integration.table.avalonia.presentation: Renderiza en una textura y descarga píxeles en un {writeableBitmap}. Consulte {zenithViewCs} y {surfaceCs}. +concepts.platforms.integration.table.headings.integration: Integración +concepts.platforms.integration.table.headings.presentation: Cómo llega su imagen a la interfaz de usuario +concepts.platforms.integration.table.maui.integration: .NET MAUI +concepts.platforms.integration.table.maui.presentation: Utiliza superficies nativas en Android, iOS y Mac Catalyst, y composición de texturas compartidas en Windows. Consulte las {link}. +concepts.platforms.integration.table.maui.presentation.link: implementaciones de plataforma +concepts.platforms.integration.table.uno.integration: Ruta de Uno +concepts.platforms.integration.table.uno.presentation: Descarga píxeles en un {writeableBitmap}. Consulte {zenithViewUnoCs}. +concepts.platforms.integration.table.winForms.integration: WinForms +concepts.platforms.integration.table.winForms.presentation: Crea una cadena de intercambio de Zenith.NET para el {hWND} del control. Consulte {zenithViewCs}. +concepts.platforms.integration.table.winUI.integration: WinUI en Windows +concepts.platforms.integration.table.winUI.presentation: Renderiza en una textura compartida de Direct3D 11 importada y luego copia a una cadena de intercambio de composición conectada a {swapChainPanel}. Consulte {zenithViewWinUICs}. +concepts.platforms.integration.table.wpf.integration: WPF +concepts.platforms.integration.table.wpf.presentation: Importa una textura compartida de Direct3D 11 y luego copia a través de interoperabilidad Direct3D a una superficie mostrada por {d3DImage}. Consulte {surfaceCs}. +concepts.platforms.integration.title: Elegir la ruta de presentación así como el marco de trabajo +concepts.platforms.lifecycle.context: Para una vista de interfaz de usuario, utilice {descWidth}, {descHeight}, {descFormat} y {descSampleCount} de la textura de salida del evento al crear recursos de renderizado coincidentes. El control determina la resolución de esa textura de salida; no asuma que sus dimensiones lógicas o escala de pantalla siempre son iguales a las dimensiones de la textura. +concepts.platforms.lifecycle.description: Para una cadena de intercambio nativa, pase las dimensiones del búfer de fotogramas en píxeles. Los tamaños de ventana expresados en unidades lógicas pueden diferir cuando la escala de pantalla está activada. Omita los búferes de fotogramas de tamaño cero, cambie el tamaño de la cadena de intercambio cuando cambie su tamaño de píxeles y obtenga {swapChainDrawable} para cada fotograma. La textura de salida es propiedad de la cadena de intercambio y puede cambiar después de la presentación o del cambio de tamaño. +concepts.platforms.lifecycle.details: "{swapChainResize} cambia las dimensiones de la superficie existente. {swapChainRefresh} reemplaza la descripción de la superficie, incluidos sus identificadores nativos. Antes de cualquiera de las operaciones, complete los usos pendientes de los recursos afectados. Libere la cadena de intercambio antes de destruir su destino de presentación nativo." +concepts.platforms.lifecycle.guidance: "Vuelva a crear texturas fuera de pantalla o de profundidad propiedad de la aplicación cuyo tamaño siga a la ventana y actualice las constantes que contengan sus identificadores. Una canalización puede seguir en uso a través de un cambio de tamaño cuando sus formatos de adjuntos y recuento de muestras siguen siendo compatibles. El {link} mantiene su canalización mientras reemplaza su textura de profundidad." +concepts.platforms.lifecycle.guidance.link: renderizador de cubo giratorio +concepts.platforms.lifecycle.title: Mantener el tamaño y el tiempo de vida de la textura de salida con su host +concepts.platforms.ownership.description: "La aplicación es propietaria del contexto que asigna y de los recursos que crea para renderizar. El control posee sus propios recursos de presentación. Cambiar la propiedad {graphicsContext} de la vista hace que el planificador recree los recursos del control; no recrea las canalizaciones, los búferes ni las texturas de la aplicación para el nuevo contexto." +concepts.platforms.ownership.details: Coordine el reemplazo de recursos con el ciclo de vida de los fotogramas de la vista. Detenga la actividad de fotogramas de la vista y finalice los usos pendientes de la GPU antes de liberar los recursos de la aplicación o el contexto asignado. Quitar una vista no transfiere la propiedad del contexto al control. +concepts.platforms.ownership.guidance: El archivo compartido {frameSchedulerCs} despacha el trabajo del fotograma a través del despachador de interfaz de usuario de la vista. Mantenga los controladores de fotogramas enfocados en actualizar y grabar el fotograma; el trabajo prolongado de la CPU allí también retrasa la interfaz de usuario. +concepts.platforms.ownership.title: Mantener los recursos de la aplicación fuera de la propiedad del control +concepts.platforms.surface.context: Que una biblioteca de ventanas o un marco de interfaz de usuario sea compatible con un sistema operativo no garantiza que el backend de GPU seleccionado esté disponible allí. Las funciones del dispositivo, los controladores y la compatibilidad con superficies nativas aún deben coincidir. Compruebe el trazado de rayos y el sombreado de mallas opcionales a través de {contextCapabilities} antes de crear esas cargas de trabajo. +concepts.platforms.surface.description: El {link} utiliza Silk.NET para crear una ventana y procesar eventos. Zenith.NET se conecta a esa ventana a través de una descripción de {surface} y una {swapChain}. Una superficie contiene identificadores y dimensiones nativas; construir la descripción no crea ni posee la ventana del sistema operativo. +concepts.platforms.surface.description.link: triángulo +concepts.platforms.surface.details: "El identificador debe coincidir con el backend seleccionado:" +concepts.platforms.surface.guidance: El archivo {appCs} del tutorial muestra las opciones de Windows, macOS y X11. Su host de Linux suministra identificadores Xlib; usarlo en una sesión Wayland requiere XWayland. Una aplicación nativa de Wayland suministraría diferentes identificadores a través de {surfaceWayland}. +concepts.platforms.surface.table.android.backend: Vulkan en Android. +concepts.platforms.surface.table.apple.backend: Metal en plataformas Apple. +concepts.platforms.surface.table.headings.backend: Ruta de backend +concepts.platforms.surface.table.headings.factory: Fábrica de superficies +concepts.platforms.surface.table.headings.handles: Identificadores suministrados por el host +concepts.platforms.surface.table.wayland.backend: Vulkan con un host Wayland nativo. +concepts.platforms.surface.table.wayland.handles: Pantalla y superficie Wayland +concepts.platforms.surface.table.win32.backend: DirectX 12 o Vulkan en Windows. +concepts.platforms.surface.table.xlib.backend: Vulkan en Linux con X11 o XWayland. +concepts.platforms.surface.table.xlib.handles: Pantalla y ventana X11 +concepts.platforms.surface.title: Suministrar una superficie nativa cuando la aplicación posee la presentación +concepts.platforms.title: Integración de plataforma +concepts.resources.allocation.context: "Empiece con recursos creados por el contexto, salvo que necesite su propio asignador de memoria. Al usar un montículo, espere a que termine todo el trabajo de GPU que utiliza sus recursos; después libere los recursos ubicados y, por último, el propio montículo." +concepts.resources.allocation.description: "Un {heap} proporciona memoria en la que se ubican recursos en desplazamientos explícitos en bytes. La aplicación elige esos desplazamientos y lleva el control de las regiones en uso." +concepts.resources.allocation.details: "Antes de ubicar un recurso, utilice {contextGetSizeAndAlignment} con su descripción exacta de búfer o textura. Elija un desplazamiento múltiplo de la alineación devuelta, reserve el tamaño devuelto y mantenga el recurso dentro del tamaño total del montículo. Las asignaciones en uso no deben solaparse. El almacenamiento de texturas puede incluir relleno y alineación específicos del backend; multiplicar el número de píxeles por los bytes por píxel no permite calcular el tamaño de la asignación." +concepts.resources.allocation.guidance: "Para los búferes ubicados, mantenga la residencia del búfer coherente con la del montículo. Utilice montículos exclusivos de GPU para las texturas de GPU ordinarias descritas aquí. El tamaño y la alineación son requisitos de ubicación, no una garantía de que cualquier recurso pueda ubicarse en cualquier montículo en todos los backends." +concepts.resources.allocation.title: Ubicar recursos en un montículo cuando se necesita control de asignación +concepts.resources.bufferUsages.table.constant.role: Parámetros de sombreador leídos a través de un enlace de búfer de constantes. +concepts.resources.bufferUsages.table.headings.role: "Rol" +concepts.resources.bufferUsages.table.headings.usage: Uso +concepts.resources.bufferUsages.table.index.role: Índices utilizados por el dibujo indexado. +concepts.resources.bufferUsages.table.indirect.role: "Argumentos leídos por comandos de dibujo o dispatch indirectos." +concepts.resources.bufferUsages.table.none.role: "No se declaran indicadores de uso del búfer." +concepts.resources.bufferUsages.table.storageReadOnly.role: "Datos de búfer accedidos mediante un enlace de sombreador de solo lectura." +concepts.resources.bufferUsages.table.storageReadWrite.role: "Datos de búfer accedidos mediante un enlace de sombreador de lectura y escritura." +concepts.resources.bufferUsages.table.transferDst.role: "Almacenamiento de destino para una copia de GPU." +concepts.resources.bufferUsages.table.transferSrc.role: "Datos de origen para una copia de GPU." +concepts.resources.bufferUsages.table.vertex.role: Atributos de vértice capturados para dibujar. +concepts.resources.bufferUsages.title: Usos de búfer +concepts.resources.description: "Elija la descripción de un recurso según las operaciones que lo utilizarán. Una textura que recibe renderizado, se muestrea en un sombreador y se descarga a la CPU necesita declarar esos tres usos y sincronizar los accesos entre ellos. La ubicación de memoria y el tiempo de vida del recurso son decisiones adicionales." +concepts.resources.memory.context: Para un búfer accesible por la CPU, {map} proporciona a la CPU una dirección. No espera a que la GPU deje de acceder a los mismos bytes. {unmap} igualmente no envía trabajo ni espera a que se complete. Antes de sobrescribir datos editables por la CPU, finalice las lecturas de GPU que aún necesiten su contenido anterior. +concepts.resources.memory.description: "Un {bufferDesc} tiene un campo {residency}. Elíjalo según cómo accederán a los datos la CPU y la GPU:" +concepts.resources.memory.details: La residencia describe el acceso previsto de la CPU a la asignación. No implica que cada dispositivo tenga memoria física de CPU y GPU separada. El triángulo utiliza {cpuWriteOnly} para inicializar un pequeño búfer de vértices directamente. Una malla estática grande puede beneficiarse en cambio del almacenamiento exclusivo de GPU con una carga única. +concepts.resources.memory.guidance: "{textureDesc} no tiene campo de residencia. Las texturas ordinarias creadas por el contexto utilizan almacenamiento de GPU. Su API pública proporciona operaciones de carga y descarga para transferir datos de CPU, sin exponer un método de mapeo directo. Los montículos explícitos permiten controlar la ubicación, como se explica más abajo." +concepts.resources.memory.table.cpuReadOnly.cPUAccess: "Leer la memoria mapeada después de que termine la copia de GPU." +concepts.resources.memory.table.cpuReadOnly.typicalRole: "Datos producidos por la GPU para su lectura en la CPU" +concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "Escribir la memoria mapeada cuando hayan terminado los lectores anteriores de GPU." +concepts.resources.memory.table.cpuWriteOnly.typicalRole: "Datos proporcionados o actualizados por la CPU" +concepts.resources.memory.table.gpuOnly.cPUAccess: "Transferir bytes mediante un búfer de carga o de lectura desde la GPU." +concepts.resources.memory.table.gpuOnly.typicalRole: "Geometría estática y datos de trabajo de la GPU" +concepts.resources.memory.table.headings.cPUAccess: Acceso de CPU +concepts.resources.memory.table.headings.residency: Residencia +concepts.resources.memory.table.headings.typicalRole: Rol típico +concepts.resources.memory.title: "Elegir memoria según el acceso de CPU necesario" +concepts.resources.textureUsages.description: "Los indicadores de uso para transferencias describen la dirección de las copias de GPU. El acceso de CPU es una decisión independiente de ubicación de memoria, descrita más abajo." +concepts.resources.textureUsages.details: "Combinar indicadores de uso declara varios roles; no ejecuta las operaciones ni ordena sus accesos. Las texturas siguen necesitando {link} adecuados, y sus formatos deben admitir los usos solicitados en el dispositivo seleccionado." +concepts.resources.textureUsages.details.link: "layout y sincronización" +concepts.resources.textureUsages.table.colorAttachment.role: "Un adjunto de color en una pasada de renderizado." +concepts.resources.textureUsages.table.depthStencilAttachment.role: "Un adjunto de profundidad y plantilla en una pasada de renderizado." +concepts.resources.textureUsages.table.headings.role: "Rol" +concepts.resources.textureUsages.table.headings.usage: Uso +concepts.resources.textureUsages.table.none.role: "No se declaran indicadores de uso de la textura." +concepts.resources.textureUsages.table.sampled.role: "Datos de textura leídos mediante un enlace de textura muestreada." +concepts.resources.textureUsages.table.storage.role: "Datos de textura accedidos mediante un enlace de textura de almacenamiento para lecturas o escrituras del sombreador." +concepts.resources.textureUsages.table.transferDst.role: "Almacenamiento de imagen de destino para una copia de GPU." +concepts.resources.textureUsages.table.transferSrc.role: "Datos de imagen de origen para una copia de GPU." +concepts.resources.textureUsages.title: Usos de textura +concepts.resources.title: Administración de recursos +concepts.resources.transfers.context: Una descarga graba una copia de GPU en el almacenamiento interno de lectura. La biblioteca copia esos bytes en el destino de CPU suministrado cuando restablece el búfer de comandos completado para su reutilización. Mantenga el destino asignado y mantenga la memoria administrada anclada hasta que regrese el {wait} del valor de envío. +concepts.resources.transfers.description: "Una carga copia datos de CPU a un recurso de GPU; una descarga copia datos del recurso a la memoria de CPU. Los métodos del propio recurso completan esa transferencia antes de devolver el control:" +concepts.resources.transfers.details: "Estas esperas cubren la transferencia que envían esos métodos. No descubren dependencias con otra cola que ya estuviera leyendo o escribiendo el recurso. Establezca esas dependencias antes de llamar al método del recurso. Una copia directa mediante memoria mapeada también exige que quien llama garantice la finalización del trabajo de GPU correspondiente." +concepts.resources.transfers.guidance: "Utilice {commandBufferUpload} o {commandBufferDownload} cuando las copias deban grabarse con otro trabajo. Los tiempos de vida de sus punteros difieren:" +concepts.resources.transfers.item: "Durante la llamada, una carga copia los datos de origen de CPU en un búfer de carga interno, también llamado memoria provisional o staging. El puntero de origen solo debe permanecer válido durante esa llamada." +concepts.resources.transfers.notes: "Para una textura, el paso de fila es la distancia en bytes entre filas consecutivas de datos de CPU, y el paso de corte es la distancia en bytes entre cortes de profundidad consecutivos. No describen la distribución interna de la textura en memoria de GPU. Consulte {link} para distinguir la finalización de GPU de la disponibilidad de los datos leídos." +concepts.resources.transfers.notes.link: Sincronización +concepts.resources.transfers.table.bufferDownload.transfer: Copia directa de CPU para {cpuReadOnly}; de lo contrario, envía una descarga en la cola de transferencia y espera. +concepts.resources.transfers.table.bufferUpload.transfer: Copia directa de CPU para {cpuWriteOnly}; de lo contrario, envía una carga en la cola de transferencia y espera. +concepts.resources.transfers.table.headings.method: Método +concepts.resources.transfers.table.headings.transfer: "Cómo transfiere los datos" +concepts.resources.transfers.table.textureTransfers.method: "{textureUpload} / {textureDownload}" +concepts.resources.transfers.table.textureTransfers.transfer: "Utiliza la cola gráfica, cambia el layout del subrecurso seleccionado para realizar la copia, lo cambia al layout final solicitado y espera a que termine la transferencia." +concepts.resources.transfers.title: "Elegir entre transferencias inmediatas y transferencias grabadas" +concepts.resources.usages.description: "{bufferUsages} y {textureUsages} son enumeraciones de indicadores que declaran los roles previstos de un recurso. Se asignan a {bufferDescUsages} y {textureDescUsages}, respectivamente. Una enumeración de indicadores permite combinar varios miembros con {value} cuando un recurso tiene más de un rol." +concepts.resources.usages.title: Declarar los usos requeridos antes de crear un recurso +concepts.resources.views.description: Una {bufferView} describe una región de búfer y su interpretación. Una {textureView} selecciona un tipo de textura compatible, un formato y un rango de subrecursos. Una vista comparte el almacenamiento de respaldo; no copia los datos ni añade usos que faltaban cuando se creó el recurso. Su rango tampoco es una garantía portátil de comprobación de límites en el sombreador. +concepts.resources.views.details: "Utilice el handle del propio recurso para su vista predeterminada, o cree una vista cuando necesite otra región o una interpretación compatible distinta. Mantenga referencias de C# a la vista y al recurso subyacente mientras el trabajo de GPU pueda utilizarlos; un handle de recurso por sí solo no mantiene vivo ninguno de los dos objetos. Libérelos únicamente tras su último uso en la GPU. Después de reemplazar cualquiera de ellos, actualice las constantes que contengan su antiguo {link}." +concepts.resources.views.details.link: "handle de recurso" +concepts.resources.views.guidance: El {link} muestra una textura de profundidad reemplazada al cambiar el tamaño. El {detail} muestra una textura de entrada que se mantiene separada de su salida editable. Ambos hacen que el tiempo de vida del recurso siga al trabajo que realmente lo utiliza. +concepts.resources.views.guidance.detail: ejemplo de cálculo +concepts.resources.views.guidance.link: renderizador de cubo giratorio +concepts.resources.views.title: "Mantener disponibles las vistas y sus recursos subyacentes durante su uso" +concepts.shaders.binding.context: "En el ejemplo de cálculo, {input} se llena con {inputTextureSampledHandle} y {output} con {outputTextureStorageHandle}. El {descriptorHandle} con tipo de Slang indica al sombreador cómo acceder a cada recurso:" +concepts.shaders.binding.description: "{setConstantBuffer} enlaza un búfer y un desplazamiento de bytes para los datos de constantes de la canalización actual. Enlaza el almacenamiento visible por GPU existente; no carga un valor de C#. Llene el búfer primero y asegúrese de que los lectores de GPU anteriores hayan finalizado antes de sobrescribir sus bytes." +concepts.shaders.binding.details: "Establezca la canalización antes de su búfer de constantes. Para una carga de trabajo de cálculo con recursos ya creados y cargados, la grabación utiliza este orden:" +concepts.shaders.binding.guidance: Este fragmento asume un {commandBuffer} de grabación, una {computePipeline}, un {constantBuffer} cargado con uso {bufferUsagesConstant} y los recuentos de grupos de subprocesos para la carga de trabajo. El desplazamiento 0 enlaza el inicio del búfer. Si varios registros de datos de constantes comparten un búfer, el desplazamiento inicial de cada registro debe cumplir con la alineación de enlace del backend. Ese requisito es independiente del diseño de campos dentro del registro. +concepts.shaders.binding.notes: "{resourceHandle} almacena dos campos de 32 bits, pero su interpretación pertenece al backend. No lo trate como un índice de descriptor universal, dirección o valor que se pueda transferir entre contextos. Un identificador no crea un recurso, no añade un uso faltante ni realiza sincronización." +concepts.shaders.binding.reference: Conserve referencias al recurso y a cualquier vista utilizada para obtener su identificador, y libérelos solo después de que se complete el último uso del sombreador. Al reemplazar una textura o vista, actualice las constantes que contengan su identificador anterior. {link} explica esa relación de tiempo de vida. +concepts.shaders.binding.reference.link: Administración de recursos +concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: Leer elementos estructurados del tipo de sombreador {t}. +concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: Leer o escribir elementos estructurados del tipo de sombreador {t}. +concepts.shaders.binding.table.headings.access: Acceso previsto +concepts.shaders.binding.table.headings.cHandle: "Identificador de C#" +concepts.shaders.binding.table.headings.slangFieldType: Tipo de campo Slang +concepts.shaders.binding.table.samplerHandle.access: Suministrar estado de muestreo de textura. +concepts.shaders.binding.table.textureSampledHandle.access: Leer una textura. +concepts.shaders.binding.table.textureStorageHandle.access: Leer o escribir una textura de almacenamiento. +concepts.shaders.binding.title: Enlazar el búfer de constantes y los recursos que describe +concepts.shaders.compilation.description: "{zenithCompiler} compila un punto de entrada de Slang con nombre y devuelve un {shaderDesc}. Utilice el {graphicsApi} del contexto para que el resultado se dirija al backend que creará el sombreador: DXIL para DirectX 12, una biblioteca Metal para Metal o SPIR-V para Vulkan." +concepts.shaders.compilation.details: "Por ejemplo, con un {context} existente y el sombreador del triángulo copiado junto al ejecutable:" +concepts.shaders.compilation.guidance: "{vSMain} debe coincidir exactamente con el nombre del punto de entrada en el archivo del sombreador. Mantenga válidos los objetos de sombreador mientras crea la canalización, luego libérelos después de la creación de la canalización, como se muestra en {link}. Realice esta inicialización una vez en lugar de recompilar en cada fotograma." +concepts.shaders.compilation.guidance.link: Primer triángulo +concepts.shaders.compilation.title: Compilar un punto de entrada para el contexto seleccionado +concepts.shaders.description: "Un sombreador recibe datos suministrados por la aplicación. Los atributos de vértice describen vértices individuales; los búferes contienen parámetros o matrices; los identificadores de recursos identifican otros recursos a los que accederá el sombreador. Las declaraciones de C# y las declaraciones de Slang deben coincidir en lo que significan esos valores. Hacer coincidir un nombre de campo no es suficiente: el diseño, el acceso a recursos y el enlace deben coincidir." +concepts.shaders.dispatch.description: "{dispatch} toma el número de grupos de subprocesos. El punto de entrada {numthreads} del ejemplo de cálculo ejecuta 16 × 16 subprocesos por grupo. Divida las dimensiones de la imagen entre 16 y redondee hacia arriba para encontrar los recuentos de grupos. Por ejemplo, una imagen de 17 × 19 necesita 2 × 2 grupos. El sombreador comprueba sus coordenadas de píxeles con las dimensiones de la imagen porque los últimos grupos pueden contener subprocesos fuera de la imagen." +concepts.shaders.dispatch.details: El compilador almacena el tamaño de grupo declarado del punto de entrada en {shaderDescThreadGroupSize}; no convierte las dimensiones en píxeles suministradas a {dispatch} en recuentos de grupos. Utilice {computeShaderRendererCs} con su sombreador para el ejemplo completo de enlace y dispatch, y {link} antes de que otra pasada consuma la salida. +concepts.shaders.dispatch.details.link: Sincronización +concepts.shaders.dispatch.title: Despachar grupos de subprocesos, no píxeles +concepts.shaders.layout.context: "Las {link} hacen explícitos sus desplazamientos. Esta declaración necesita {systemRuntimeInteropServices} y {zenithNET} en el ámbito:" +concepts.shaders.layout.context.link: "constantes de C# del ejemplo de cálculo" +concepts.shaders.layout.description: "Para la entrada de vértices, el {inputLayout} de la canalización describe formatos, desplazamientos, stride y semánticas. La posición {float3} del triángulo seguida de un color {float4} ocupa 28 bytes, con el color en el byte 12. {inputLayoutAdd} calcula este diseño empaquetado; no inspecciona la estructura de C#. Si los campos de C# contienen relleno, proporcione un diseño coincidente en lugar de asumir que los campos están empaquetados." +concepts.shaders.layout.details: "Los búferes de constantes contienen parámetros de sombreador, mientras que los búferes estructurados contienen matrices de elementos de un tipo declarado. Ambos se leen de acuerdo con sus declaraciones de Slang. No utilizan {inputLayout}. Verifique los desplazamientos de campos y los tamaños de elementos para la representación de sombreador compilada, incluido el relleno. Un tipo de C# no administrado es adecuado para copiarlo como bytes, pero eso por sí solo no demuestra que coincida con un tipo de sombreador. En particular, no aplique el diseño {float3} estrechamente empaquetado de un vértice a cada búfer de sombreador." +concepts.shaders.layout.guidance: Un identificador de recurso es un valor pequeño que hace referencia a un recurso existente. Copiar el identificador en un búfer de constantes no copia el contenido del recurso. +concepts.shaders.layout.notes: "La declaración correspondiente en {computeShaderSlang} es:" +concepts.shaders.layout.reference: "Las dimensiones ocupan los primeros ocho bytes, seguidas de dos identificadores de recursos de ocho bytes. El ejemplo de C# reserva 256 bytes en total. Ese tamaño es el tamaño de almacenamiento elegido por el ejemplo, no una regla de que todas las estructuras de Slang o cargas útiles de constantes deban ocupar 256 bytes. Rellenar el tamaño total tampoco corrige un campo en el desplazamiento incorrecto." +concepts.shaders.layout.title: La entrada de vértices y los datos de sombreadores tienen reglas de diseño diferentes +concepts.shaders.matrices.description: El compilador solicita almacenamiento de matrices en orden principal de filas (row-major), que almacena juntos los elementos de cada fila. El {link} coloca tres valores {matrix4x4} en los desplazamientos 0, 64 y 128. Su {detail} utiliza {mulVectorMatrix} en orden de modelo, vista y proyección. +concepts.shaders.matrices.description.detail: sombreador +concepts.shaders.matrices.description.link: renderizador de cubo giratorio +concepts.shaders.matrices.details: El orden de almacenamiento determina cómo ocupan memoria los elementos de la matriz; el orden de multiplicación determina la transformación. Mantenga ambos lados coherentes. Agregar una transposición sin verificar esas dos opciones puede ocultar una falta de coincidencia mientras introduce otra. +concepts.shaders.matrices.title: Mantener coherentes el almacenamiento y la multiplicación de matrices +concepts.shaders.title: Datos de sombreadores y enlace +concepts.synchronization.backends.description: DirectX 12 y Vulkan codifican transiciones de textura con información de layout y acceso. Metal no tiene ninguna operación en la implementación de {transition} de Zenith.NET. Metal agrupa el trabajo grabado en codificadores de renderizado y cálculo. El backend inserta barreras de visibilidad cuando finaliza estos grupos, haciendo que las escrituras anteriores estén disponibles para el trabajo posterior. Las llamadas explícitas a {barrier} manejan dependencias como dispatches de cálculo sucesivos dentro del mismo codificador. +concepts.synchronization.backends.details: Esta distinción es importante al cambiar una carga de trabajo. En el {link}, el dispatch va seguido de una pasada de renderizado gráfico, que también crea un límite de codificador en Metal. Dos dispatches de cálculo dependientes no crean ese límite simplemente cambiando el layout declarado de la textura. Conserve las transiciones requeridas por la API compartida e identifique por separado la dependencia entre los comandos reales de producción y consumo. +concepts.synchronization.backends.details.link: ejemplo de cálculo +concepts.synchronization.backends.title: Una transición no es idéntica en todos los backends +concepts.synchronization.barriers.context: "{barrierStagesAll} es un ámbito más amplio, no un detector automático de dependencias. Seleccione etapas que realmente cubran el trabajo y utilícelas solo en una cola que admita esas operaciones." +concepts.synchronization.barriers.description: "Considere dos dispatches de cálculo: el primero escribe datos de simulación y el segundo lee esos datos para realizar el siguiente paso. Ambos usan búferes de almacenamiento, por lo que no hay un layout de textura que cambiar. Inserte esto entre los dispatches en su búfer de comandos:" +concepts.synchronization.barriers.details: El primer argumento identifica la etapa productora y el segundo la etapa consumidora. La barrera establece la dependencia de ejecución y memoria correspondiente en la GPU. El backend traduce esas etapas a sus reglas de ejecución y acceso a memoria. Esta barrera no cambia el layout de una textura ni espera todo el trabajo en el dispositivo. +concepts.synchronization.barriers.guidance: "La {link} utiliza este patrón entre dispatches dependientes. Coloque la barrera donde se produce la dependencia. Una barrera grabada después del consumidor no puede ordenar ese consumidor después de un productor anterior." +concepts.synchronization.barriers.guidance.link: simulación FluidTank +concepts.synchronization.barriers.title: Ordenar comandos dependientes con una barrera +concepts.synchronization.dependencies.description: Para cada recurso compartido, identifique la operación que accede a él primero, la operación que le sigue y si alguno de los accesos escribe. Leer los mismos datos dos veces no requiere ordenación para proteger su contenido, aunque los cambios de layout o la presentación pueden imponer otros requisitos. Una escritura seguida de una lectura, una lectura seguida de una sobrescritura o dos escrituras pueden requerir una dependencia. +concepts.synchronization.dependencies.details: "Luego elija el mecanismo según dónde se ejecuten esas operaciones:" +concepts.synchronization.dependencies.guidance: Estos mecanismos están relacionados, pero no son intercambiables. Enviar comandos en orden no reemplaza cada dependencia de memoria. Una espera de cola no declara un nuevo layout de textura, y una barrera de comandos no espera en el subproceso de CPU que llama. +concepts.synchronization.dependencies.table.cpuAccess.mechanism: Llamar a {wait} en el valor de finalización correspondiente. +concepts.synchronization.dependencies.table.cpuAccess.situation: La CPU debe esperar antes de acceder a los datos o liberarlos +concepts.synchronization.dependencies.table.crossQueue.mechanism: Pasar su {timelineValue} al {submit} del búfer de comandos consumidor. +concepts.synchronization.dependencies.table.crossQueue.situation: Un envío en otra cola produce los datos +concepts.synchronization.dependencies.table.headings.mechanism: Mecanismo +concepts.synchronization.dependencies.table.headings.situation: Situación +concepts.synchronization.dependencies.table.layoutChange.mechanism: "{commandBufferTransition} con sus layouts anterior y siguiente." +concepts.synchronization.dependencies.table.layoutChange.situation: Un subrecurso de textura cambia cómo se utiliza +concepts.synchronization.dependencies.table.pipelineStages.mechanism: "{commandBufferBarrier} con las etapas productora y consumidora." +concepts.synchronization.dependencies.table.pipelineStages.situation: Etapas de GPU dependientes en un flujo de comandos +concepts.synchronization.dependencies.title: Comenzar con el productor y el consumidor +concepts.synchronization.description: Un comando que lee datos escritos por un comando anterior depende de que esas escrituras estén finalizadas y sean visibles para él. El escritor es el productor; el lector es el consumidor. La CPU también necesita un punto de finalización antes de leer, sobrescribir o liberar datos compartidos. Zenith.NET proporciona barreras, transiciones de textura y líneas de tiempo para estas diferentes dependencias. +concepts.synchronization.layouts.context: "{undefined} significa que no es necesario conservar el contenido anterior. Es adecuado para una nueva imagen o un adjunto que se borrará por completo. No es una forma de evitar rastrear el layout de una imagen cuyo contenido se cargará, muestreará o acumulará." +concepts.synchronization.layouts.description: "Los indicadores de uso describen qué roles admite una textura. {textureLayout} describe cómo se accederá a un subrecurso determinado para una operación. Un subrecurso es un nivel mip y una capa de matriz seleccionados. Cambiar su layout prepara ese acceso; no convierte la textura a un formato de píxeles diferente. Por ejemplo, el ejemplo de cálculo escribe una textura de salida en el layout {storage} y luego la muestrea en una pasada gráfica. Entre esos usos graba:" +concepts.synchronization.layouts.details: "Este fragmento supone que {outputTexture} se creó con el uso {sampledStorage} y que el subrecurso seleccionado está en el layout {storage}. {default} selecciona el nivel mip 0 y la capa de matriz 0. La operación no cambia el layout de todos los niveles mip ni de todas las capas de una textura." +concepts.synchronization.layouts.guidance: La aplicación proporciona el layout anterior. {transition} no mantiene un rastreador de layouts visible para la aplicación ni infiere ese valor a partir de comandos anteriores. Rastree el layout dondequiera que un recurso pase entre etapas de renderizado. +concepts.synchronization.layouts.title: Rastrear el layout de cada subrecurso de textura +concepts.synchronization.readback.description: "{isCompleted} solo consulta si la línea de tiempo de la GPU ha alcanzado un valor. No reclama por sí mismo los búferes de comandos ni copia descargas intermedias en el puntero de destino de la aplicación." +concepts.synchronization.readback.details: "{commandBufferDownload} graba primero una copia en el almacenamiento interno de lectura. Al restablecer el búfer de comandos completado para reutilizarlo, la CPU copia los datos al puntero suministrado. Mantenga ese destino válido y la memoria administrada anclada hasta que retorne {wait} para el envío de descarga. Solo entonces lea los datos o libere la memoria. Esperar a un envío posterior de otra cola no sondea la cola que gestiona la descarga." +concepts.synchronization.readback.guidance: "Por eso no basta con sondear {isCompleted} y leer inmediatamente el destino de una descarga asíncrona. En {link} se explican la copia directa y las transferencias mediante almacenamiento provisional." +concepts.synchronization.readback.guidance.link: Administración de recursos +concepts.synchronization.readback.title: La finalización en la GPU y los datos descargados en la CPU son pasos independientes +concepts.synchronization.reuse.description: Para un primer renderizador, una espera inmediata después de cada fotograma es sencilla. Para superponer trabajo, proporcione a los fotogramas pendientes datos mutables separados y conserve el valor de finalización del uso final de cada fotograma. Antes de actualizar un búfer de constantes, reemplazar una textura o liberar una canalización, finalice cada acceso pendiente al recurso afectado. +concepts.synchronization.reuse.details: Al cambiar el tamaño o apagar, detenga los nuevos usos antes de esperar los antiguos. {swapChainResize}, la liberación de recursos y la liberación del contexto no sirven como esperas generales para el trabajo de la aplicación. El triángulo puede cambiar de tamaño de forma segura entre devoluciones de llamada porque cada fotograma anterior ya ha completado su envío. +concepts.synchronization.reuse.guidance: El {swapChainPresent} actual también envía señales y espera en la cola de gráficos después de su operación de presentación. Por lo tanto, quitar la espera de envío explícita del triángulo no establece por sí sola un bucle de presentación superpuesto. Una espera en la cola de gráficos tampoco dice nada sobre el trabajo independiente que aún se está ejecutando en otra cola. +concepts.synchronization.reuse.title: Reutilizar datos solo después de su acceso final +concepts.synchronization.timelines.context: "Antes de que la CPU lea, sobrescriba o libere esos recursos, espere su uso final:" +concepts.synchronization.timelines.description: Una línea de tiempo realiza un seguimiento de la finalización en una cola mediante valores crecientes. {submit} devuelve un {timelineValue} que contiene esa línea de tiempo y el valor asociado con el envío. Los valores de finalización de diferentes líneas de tiempo no son comparables únicamente por sus campos numéricos {value}. +concepts.synchronization.timelines.details: "Supongamos que {producer} y {consumer} son búferes de comandos ya grabados de dos colas del mismo contexto. El productor escribe datos que utiliza el consumidor. Envíelos de esta manera:" +concepts.synchronization.timelines.guidance: Pasar el valor producido hace que la cola consumidora espere por él en la GPU. La CPU no llama a {producedWait} aquí. Mantenga válidos los recursos compartidos hasta que se complete {consumed} y grabe cualquier cambio de layout de textura requerido por el consumidor. +concepts.synchronization.timelines.notes: "{wait} espera ese valor de línea de tiempo y luego comprueba la cola propietaria en busca de envíos completados. Los búferes de comandos terminados se restablecen para su reutilización y sus descargas intermedias se copian en los destinos de CPU suministrados. {queueTimelineSignal} también puede poner en cola un punto de finalización después del trabajo ya enviado a esa cola. Llamar a {signal} no significa que la GPU ya haya alcanzado el punto." +concepts.synchronization.timelines.title: Usar una línea de tiempo para la finalización y transferencias de colas +concepts.synchronization.title: Sincronización +home.actions.reference: Explorar API +home.actions.tutorial: Comenzar con un triángulo +home.entries.description: Un primer fotograma. Un ejemplo enfocado. Una mirada detallada a la API. +home.entries.label: Explorar la documentación +home.entries.reference.action: Explorar la API +home.entries.reference.category: Referencia +home.entries.reference.description: Encuentre los tipos, firmas y miembros que respaldan su aplicación. +home.entries.reference.title: Referencia de la API +home.entries.samples.action: Examinar ejemplos +home.entries.samples.category: Ejemplos +home.entries.samples.description: Explore técnicas enfocadas de renderizado y cálculo a través de su código fuente. +home.entries.samples.title: Ejemplos +home.entries.title: "Empiece a crear." +home.entries.tutorial.action: Iniciar tutorial +home.entries.tutorial.category: Tutorial +home.entries.tutorial.description: Cree una aplicación de renderizado completa, desde la configuración hasta el primer fotograma. +home.entries.tutorial.title: Primer triángulo +home.introduction.accent: "En C#." +home.introduction.description: Cree recursos, grabe comandos y envíe trabajo de gráficos o cálculo a través de una única API de .NET. +home.introduction.title: Cree su propio renderizador. +home.meta.description: "Una API coherente de C# para gráficos y cálculo en DirectX, Metal y Vulkan." +home.scene.description: Estudio de geometría rotatoria. Arrastre o use las teclas de dirección para ajustar la vista. +home.scene.label: Visualización geométrica +home.scene.surface: Superficie +home.scene.wireframe: Estructura alámbrica +home.title: RHI moderno para .NET +learning.concepts.description: Comprenda cómo encajan los comandos, los recursos, los datos de sombreadores y la sincronización antes de combinar pasadas de renderizado. +learning.concepts.execution.description: Grabe trabajo de GPU, envíelo y mantenga vivos sus recursos. +learning.concepts.platforms.description: Conecte una ventana nativa o un control de renderizado de interfaz de usuario. +learning.concepts.resources.description: Elija usos de recursos, ubicación de memoria y vistas. +learning.concepts.shaders.description: "Haga coincidir diseños de C# e identificadores de recursos con Slang." +learning.concepts.synchronization.description: Ordene accesos dependientes y sepa cuándo finaliza el trabajo. +learning.concepts.title: Conceptos básicos +learning.description: Comience con un tutorial completo sobre un triángulo. Luego use los ejemplos enfocados y las guías conceptuales para comprender los recursos, los datos y las dependencias detrás de un renderizador más grande. +learning.entries.samples.action: Examinar ejemplos +learning.entries.samples.description: "Encuentre ejemplos de C# y Slang para geometría, cálculo, consultas de rayos y sombreado de mallas." +learning.entries.tutorial.action: Abrir tutorial +learning.entries.tutorial.description: Cree una aplicación de consola, abra una ventana y dibuje un triángulo. +learning.meta.description: Comience con Zenith.NET y explore su modelo de programación. +learning.title: Aprender +reference.description: Consulte tipos de recursos, firmas de comandos e integraciones de plataforma. +reference.entries.commands.description: Grabe comandos de gráficos, cálculo y transferencia. +reference.entries.commands.label: Grabar trabajo +reference.entries.context.description: Cree recursos de GPU para el backend seleccionado. +reference.entries.context.label: Comience aquí +reference.meta.description: Explore los tipos y miembros en Zenith.NET. +reference.navigation.core: Examinar la API principal. +reference.title: Referencia de la API +samples.computeShader.description: Convierte una imagen a escala de grises con un dispatch de cálculo y muestra la textura resultante. Muestra identificadores de recursos para una textura de entrada muestreada y una textura de salida editable, recuentos de grupos de subprocesos redondeados hacia arriba y una comprobación de límites en el sombreador. Conserve el recurso {assetsTexturesShokoPng} incluido; el renderizador lo procesa una vez y presenta el resultado en los fotogramas subsiguientes. +samples.computeShader.details: "{computeShaderRendererCs} · {computeShaderSlang}" +samples.computeShader.title: Sombreador de cálculo +samples.cube.description: "Agrega dibujo indexado, matrices de modelo, vista y proyección en un búfer de constantes y prueba de profundidad. La textura de profundidad se vuelve a crear al cambiar el tamaño. Úselo al pasar de geometría en espacio de recorte a un objeto transformado; el renderizador utiliza un adjunto de profundidad/plantilla {d32FloatS8UInt}." +samples.cube.details: "{spinningCubeRendererCs} · {spinningCubeSlang}" +samples.cube.title: Cubo giratorio +samples.description: "Elija un ejemplo enfocado para la característica que desea estudiar. Cada ejemplo se vincula al renderizador de C# y a su sombreador Slang. Comience con {link} si desea una aplicación completa explicada desde un proyecto vacío." +samples.description.link: Primer triángulo +samples.execution.description: "{link} contiene seis renderizadores independientes en una aplicación de escritorio. Utilice el SDK de .NET 10 y un backend de escritorio compatible, como se describe a continuación. Compile y ejecute la aplicación, luego elija un ejemplo del menú de la consola:" +samples.execution.description.link: ZenithTutorials +samples.execution.details: El host selecciona DirectX 12 en Windows, Metal en macOS y Vulkan en Linux. Utilice un entorno de dispositivo, controlador y compilador de sombreadores compatible con el backend seleccionado. La ruta de ventana de Linux requiere X11 o XWayland. El {link} declara las dependencias de paquetes y copia los recursos de sombreador y textura necesarios en tiempo de ejecución. +samples.execution.details.link: archivo de proyecto +samples.execution.guidance: Los ejemplos comparten código de ventanas y presentación. Puede elegir cualquier ejemplo de forma independiente según la característica que desee estudiar. +samples.execution.title: Ejecutar los ejemplos del tutorial +samples.host.description: "{appCs} crea el contexto, la ventana y la cadena de intercambio. Obtiene un búfer de comandos, llama al renderizador seleccionado, envía el fotograma y lo presenta. {iRendererCs} define los métodos de actualización, renderizado, cambio de tamaño y liberación del renderizador." +samples.host.details: El cálculo y el trazado de rayos producen texturas fuera de pantalla. {texturePresenterCs} y {presentTextureSlang} dibujan esas texturas en la textura de salida del fotograma actual de la ventana. El host sigue siendo el propietario del envío y de la presentación de la cadena de intercambio. +samples.host.title: Host y presentación compartidos +samples.indirectDrawing.description: Dibuja varias copias de un cubo utilizando un búfer de argumentos indirectos indexados y datos por instancia en un búfer estructurado. La CPU suministra los argumentos de dibujo y actualiza las transformaciones. Úselo para comprender el diseño de argumentos indirectos y el acceso de sombreadores a datos de instancia antes de agregar argumentos generados por GPU. +samples.indirectDrawing.details: "{indirectDrawingRendererCs} · {indirectDrawingSlang}" +samples.indirectDrawing.title: Dibujo indirecto +samples.meshShading.description: Utiliza un sombreador de tareas para descartar instancias de esferas y pasar sus índices a un sombreador de mallas que emite geometría. El renderizador comprueba {contextCapabilitiesMeshShadingSupported} antes de crear su canalización. Úselo para seguir los identificadores de recursos y los datos de carga útil a través de las etapas de tarea y malla. +samples.meshShading.details: "{meshShadingRendererCs} · {meshShadingSlang}" +samples.meshShading.title: Sombreado de mallas +samples.rayTracing.description: Crea estructuras de aceleración de nivel inferior y superior para un suelo y esferas procedimentales, y luego traza consultas de rayos en línea en un sombreador de cálculo. El renderizador comprueba {contextCapabilitiesRayTracingSupported} antes de construir la carga de trabajo. Utilice este ejemplo para entradas de estructuras de aceleración y recorrido de rayos del lado del sombreador. +samples.rayTracing.details: "{rayTracingRendererCs} · {rayTracingSlang}" +samples.rayTracing.title: Trazado de rayos +samples.title: Ejemplos +samples.triangle.description: Crea un búfer de vértices y un diseño de entrada coincidente, y luego dibuja tres vértices a través de una canalización de gráficos. Úselo para conectar la creación de recursos con los comandos en una pasada de renderizado. +samples.triangle.details: "{helloTriangleRendererCs} · {helloTriangleSlang} · {link}" +samples.triangle.details.link: Tutorial completo +samples.triangle.title: Hola triángulo +samples.workloads.description: "El {link} del repositorio principal contiene aplicaciones que combinan varias características. Sus proyectos hacen referencia al código fuente de la biblioteca. Desde una copia de Zenith.NET, ejecute el proyecto elegido, por ejemplo:" +samples.workloads.description.link: directorio Experiments +samples.workloads.details: Los experimentos con ventanas utilizan las mismas opciones de host para Windows, macOS y Linux/X11. Para dibujar dentro de Avalonia, WinForms, WPF, WinUI/Uno o MAUI, consulte {link} para obtener información sobre el ciclo de vida de los fotogramas del control y los vínculos de implementación. +samples.workloads.details.link: Integración de plataforma +samples.workloads.table.cornellBox.example: "{link}" +samples.workloads.table.cornellBox.example.link: CornellBox +samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: "Trazado de caminos, reducción de ruido, asignación de tonos, aumento de resolución y controles ImGui. Requiere compatibilidad con trazado de rayos y el entorno de compilación de sombreadores para su backend de escritorio." +samples.workloads.table.fluidTank.example: "{link}" +samples.workloads.table.fluidTank.example.link: FluidTank +samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: Simulación de fluidos por cálculo, dependencias entre etapas de simulación y renderizado de superficies multipasada. Requiere su backend de escritorio y el entorno de compilación de sombreadores. +samples.workloads.table.headings.example: Ejemplo +samples.workloads.table.headings.whatItDemonstratesAndRequires: Qué demuestra y qué requiere +samples.workloads.table.inkCanvas.example: "{link}" +samples.workloads.table.inkCanvas.example.link: InkCanvas +samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: Dibujo con Skia y control de entrada en una ventana nativa. Requiere el backend y la biblioteca nativa de Skia para la plataforma de destino. +samples.workloads.table.platformDetection.example: "{link}" +samples.workloads.table.platformDetection.example.link: PlatformDetection +samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: Intenta la creación de contexto para cada backend e informa de las funcionalidades del dispositivo. Si la creación del contexto falla, se informa como no compatible; ese resultado también puede indicar la falta de un controlador o una dependencia en tiempo de ejecución. +samples.workloads.title: Explorar cargas de trabajo más amplias +tutorial.context.description: La ventana ahora puede abrirse, pero aún no hemos creado los objetos de GPU que renderizarán en ella. Un {graphicsContext} proporciona acceso al backend gráfico seleccionado y a sus colas de comandos. +tutorial.context.details: "Inserte este bloque {emphasis}:" +tutorial.context.details.emphasis: después de las directivas using, antes de {iWindowWindow} +tutorial.context.guidance: Las ramas seleccionan DirectX 12 en Windows, Metal en macOS y Vulkan en Linux. El código de renderizado que sigue utiliza la API compartida de Zenith.NET. Solicitamos validación durante el desarrollo e imprimimos los mensajes notificados a través de {validationMessage}. Los diagnósticos dependen del backend y de los componentes de validación disponibles en el equipo. +tutorial.context.title: Crear el contexto gráfico +tutorial.description: Cree una aplicación de consola .NET que abra una ventana y dibuje un triángulo con un degradado de color suave. Aprenderá cómo interactúan los datos de vértices, los sombreadores y el estado de la canalización, y luego grabará y enviará los comandos que producen la imagen. +tutorial.details: Siga las secciones en orden. Primero abrirá una ventana vacía, luego mostrará un color de fondo y finalmente dibujará el triángulo. Cada punto de comprobación confirma una parte de la aplicación antes de agregar la siguiente. La inicialización se ejecuta una vez; la devolución de llamada de renderizado graba un nuevo fotograma cada vez que se invoca. +tutorial.draw.context: "Los argumentos para {draw} son:" +tutorial.draw.description: "En la devolución de llamada {windowRender}, reemplace {addTheTriangleDrawCommandsHereLater} por estos tres comandos, entre {beginRenderPass} y {endRenderPass}:" +tutorial.draw.details: "{setPipeline} selecciona los sombreadores y el estado que acabamos de crear. Establézcalo antes de enlazar datos de vértices: el backend utiliza el diseño de entrada de la canalización para interpretar el enlace." +tutorial.draw.guidance: "{setVertexBufferVertexBuffer} enlaza el búfer comenzando en el desplazamiento de bytes 0 a la ranura de entrada 0. Esa ranura corresponde a la única entrada en {inputLayouts}. No vuelve a copiar ni a cargar los datos." +tutorial.draw.notes: Los comandos aún solo están grabados en este punto. Las llamadas a {submitWait} y {present} que ya están al final de la devolución de llamada de renderizado ejecutan el trabajo y muestran su resultado. El borrado sigue siendo necesario porque el triángulo cubre solo una parte de la imagen; el fondo también debe recibir un color definido en cada fotograma. +tutorial.draw.table.firstInstance.meaning: Comenzar la numeración de instancias en cero. +tutorial.draw.table.firstVertex.meaning: Comenzar con el primer vértice en el búfer. +tutorial.draw.table.headings.argument: Argumento +tutorial.draw.table.headings.description: Valor +tutorial.draw.table.headings.meaning: Significado +tutorial.draw.table.instanceCount.meaning: Dibujar una copia del triángulo. +tutorial.draw.table.vertexCount.meaning: Leer tres vértices. +tutorial.draw.title: Dibujar el triángulo dentro de la pasada +tutorial.execution.description: "Compile y ejecute desde el directorio {firstTriangle}:" +tutorial.execution.details: La ventana debería mostrar un triángulo con una esquina superior roja, una esquina inferior derecha verde y una esquina inferior izquierda azul contra un fondo oscuro. El interior debe mostrar un degradado suave entre esos colores. +tutorial.execution.guidance: Cambie el tamaño de la ventana. La devolución de llamada de cambio de tamaño actualiza las dimensiones del búfer de fotogramas y cambia el tamaño de la cadena de intercambio. La pasada de renderizado establece una ventana gráfica que coincide con esa imagen. Debido a que las posiciones de los vértices permanecen en coordenadas normalizadas, el triángulo conserva la misma fracción del ancho y alto de la ventana; cambiar la relación de aspecto puede estirar su forma. Conservar la relación de aspecto de un objeto requiere una directiva de proyección o ventana gráfica, lo cual va más allá de este primer dibujo. +tutorial.execution.title: Ejecutar, cambiar tamaño y cerrar +tutorial.frame.commands.context: Después de {endRenderPass}, la segunda transición prepara la imagen para su presentación. {submit} finaliza la grabación y envía el búfer de comandos; {wait} espera a que la GPU complete ese envío. Luego, {present} solicita la visualización de la imagen renderizada. +tutorial.frame.commands.description: "Una pasada de renderizado agrupa operaciones de dibujo que utilizan los mismos adjuntos. Aquí, el adjunto de color es la textura de salida de la cadena de intercambio, la imagen que recibe nuestro dibujo. {colorAttachmentClear} crea una descripción que indica a la pasada que borre al color RGBA indicado y conserve el resultado cuando termine la pasada. {beginRenderPass} graba esas instrucciones; la GPU realiza el borrado después de que se envían los comandos." +tutorial.frame.commands.details: "Los corchetes contienen nuestro único adjunto de color. El argumento {null} significa que no hay un adjunto de profundidad/plantilla, que almacenaría valores de profundidad y máscaras de plantilla para pruebas de profundidad y plantilla." +tutorial.frame.commands.guidance: "{beginRenderPass} establece una ventana gráfica (viewport) y un recorte (scissor) que cubren el adjunto. La ventana gráfica asigna las coordenadas renderizadas a píxeles, y el recorte limita qué píxeles se pueden escribir. Estos valores predeterminados cubren toda la textura de salida, que es lo que necesita este triángulo." +tutorial.frame.commands.title: Borrar, enviar y presentar +tutorial.frame.description: Primero llene la imagen con un único color de fondo. Esta operación se denomina borrado (clear). Si ese color aparece en la ventana, la superficie, el envío de comandos y la ruta de presentación están funcionando juntos. Este punto de comprobación le permite verificar el bucle de fotogramas antes de agregar geometría y sombreadores. +tutorial.frame.details: "Una devolución de llamada de renderizado es código que Silk.NET llama cuando es hora de dibujar un fotograma. Esta devolución de llamada no necesita el argumento de tiempo transcurrido del evento, por lo que se denomina {value}. Regístrela {emphasis}:" +tutorial.frame.details.emphasis: antes de {windowRun} +tutorial.frame.target.description: "{graphicsQueueCommandBuffer} obtiene un búfer de comandos con la grabación ya iniciada. La grabación describe trabajo para la GPU; no ejecuta ese trabajo de inmediato." +tutorial.frame.target.details: "La primera {transition} prepara la textura de salida para el acceso como adjunto de color. {default} selecciona el nivel mip 0 y la capa de matriz 0. Usamos {undefined} como layout anterior porque borraremos toda la imagen y descartaremos su contenido anterior. Una pasada que deba conservar el contenido existente debe usar su layout anterior real en su lugar." +tutorial.frame.target.guidance: Utilice la textura de salida actual de la cadena de intercambio en cada fotograma. La presentación puede cambiar qué imagen está disponible, por lo que una textura guardada de un fotograma anterior no es un destino de renderizado de ventana permanente. +tutorial.frame.target.title: Preparar la textura de salida +tutorial.frame.title: Mostrar un color de fondo +tutorial.geometry.data.description: Agregue esta matriz {emphasis}. Los siguientes pasos de creación de recursos también pertenecen a antes de esa devolución de llamada, en el orden mostrado. +tutorial.geometry.data.description.emphasis: antes de {windowRender} +tutorial.geometry.data.details: "Cada entrada de la matriz crea un {vertex}. Las dos expresiones {new} internas crean su posición {vector3} y su color {vector4}. Los vértices describen las esquinas superior, inferior derecha e inferior izquierda. El sombreador de vértices suministrará una cuarta coordenada de posición, {w}. Con w igual a 1, x e y describen directamente coordenadas de dispositivo normalizadas: -1 y +1 son los bordes de la imagen y 0 es el centro. Estas coordenadas no dependen de las dimensiones en píxeles de la ventana." +tutorial.geometry.data.guidance: Cada color contiene componentes rojo, verde, azul y alfa. Alfa es 1 en las tres esquinas. Las tres posiciones tienen z = 0, situándolas en el mismo plano. Estas posiciones no necesitan cámara ni matriz de transformación porque ya describen las coordenadas que queremos renderizar. Para este triángulo plano único, también desactivaremos la mezcla y la prueba de profundidad y omitiremos un búfer de profundidad. +tutorial.geometry.data.title: Elegir las esquinas +tutorial.geometry.description: Un vértice es un punto junto con los datos utilizados para dibujarlo. Nuestro triángulo tiene tres vértices, uno para cada esquina. Cada uno contiene una posición y un color. La GPU interpolará los colores calculando valores intermedios a través del triángulo. +tutorial.geometry.format.description: "Agregue esta declaración {emphasis}:" +tutorial.geometry.format.description.emphasis: al final de {programCs}, después de las instrucciones de limpieza +tutorial.geometry.format.details: "{file} limita este tipo a {programCs}, y el constructor inicializa sus campos de posición y color. {layoutKindSequential} mantiene los campos en el orden de declaración. {position} contiene tres flotantes de 32 bits y {color} contiene cuatro. En esta estructura, la posición comienza en el byte 0, el color comienza en el byte 12 y el vértice completo ocupa 28 bytes. Describiremos ese mismo diseño a la canalización de gráficos." +tutorial.geometry.format.title: Definir un vértice +tutorial.geometry.title: Dar a la GPU tres vértices +tutorial.geometry.upload.context: "{fixed} evita que el recolector de elementos no utilizados mueva la matriz mientras se usa su dirección. Para este búfer al que puede escribir la CPU, {upload} mapea la memoria, copia los datos y deshace el mapeo antes de devolver el control. Por tanto, la matriz no necesita seguir anclada después. El búfer debe permanecer vivo durante todo el renderizado, y basta con cargar los datos una vez porque los vértices no cambian." +tutorial.geometry.upload.description: "La matriz administrada son datos de CPU. Un {buffer} proporciona a la GPU almacenamiento desde el que puede leer los vértices. Después de la matriz, agregue:" +tutorial.geometry.upload.details: "El tamaño total es {sizeofVertexVerticesLength}: 28 bytes por vértice, tres vértices, 84 bytes en total. {bufferUsagesVertex} permite el acceso de entrada de vértices. {cpuWriteOnly} permite a la CPU inicializar este pequeño búfer directamente. El stride del descriptor registra el tamaño del elemento; el diseño de entrada que crearemos a continuación indicará a la captura de vértices cómo leer los atributos individuales." +tutorial.geometry.upload.guidance: Crear un búfer no lo rellena. {upload} copia la matriz en esa asignación comenzando en el desplazamiento de byte de destino 0. Su descripción de origen proporciona un puntero y el número de bytes que se van a copiar. +tutorial.geometry.upload.notes: Agregue {vertexBufferDispose} inmediatamente antes de {swapChainDispose} en la limpieza al final de {programCs}. Para geometrías estáticas más grandes, {link} explica cuándo elegir almacenamiento exclusivo de GPU y transferencias de carga en su lugar. +tutorial.geometry.upload.notes.link: Administración de recursos +tutorial.geometry.upload.title: Asignar un búfer y cargar la matriz +tutorial.input.description: "Los bytes de vértices y los sombreadores están listos. A continuación, describa cómo debe leer la GPU cada vértice. Un atributo es un valor único, como posición o color. El diseño de entrada proporciona a cada atributo un formato y un desplazamiento de bytes; el stride proporciona la distancia en bytes de un vértice al siguiente. Agregue este bloque de inicialización después de la creación del sombreador:" +tutorial.input.details: "{inputLayoutAdd} agrega un elemento en el stride actual y aumenta ese stride en el tamaño del elemento. No inspecciona la estructura de C#. Aquí produce la siguiente concordancia entre la memoria de la CPU y las entradas del sombreador:" +tutorial.input.guidance: "Cambiar el orden de los campos de C# o el relleno sin actualizar esta descripción haría que la GPU leyera los bytes incorrectos. El {semanticIndex} predeterminado es cero, coincidiendo con {pOSITION0} y {cOLOR0}. Ambos elementos pertenecen al mismo búfer, por lo que la canalización contendrá un diseño de entrada y enlazaremos ese búfer a la ranura 0." +tutorial.input.table.headings.byteOffset: Desplazamiento de bytes +tutorial.input.table.headings.cField: "Campo de C#" +tutorial.input.table.headings.format: Formato +tutorial.input.table.headings.shaderInput: Entrada del sombreador +tutorial.input.table.nextVertex.cField: Siguiente vértice +tutorial.input.table.nextVertex.format: "Stride total: 28 bytes" +tutorial.input.table.nextVertex.shaderInput: Siguiente registro de entrada +tutorial.input.table.vertexColor.format: "{float4} (16 bytes)" +tutorial.input.table.vertexPosition.format: "{float3} (12 bytes)" +tutorial.input.title: Describir el diseño de entrada de vértices +tutorial.lifecycle.description: "La aplicación terminada repite esta secuencia:" +tutorial.lifecycle.details: "Cerrar la ventana regresa de {run}. Cada fotograma renderizado ya ha esperado a que se complete su trabajo de GPU, por lo que ahora podemos liberar los recursos que utilizó. La limpieza después de {windowRun} debe ser:" +tutorial.lifecycle.guidance: "Libere la cadena de intercambio antes que su ventana nativa, y el contexto después de todos sus recursos. La cola posee y recicla los búferes de comandos enviados; la cadena de intercambio posee su textura de salida. Esos búferes de comandos y esa textura no necesitan una llamada {dispose} independiente en esta aplicación." +tutorial.lifecycle.title: Seguir el ciclo de vida de un fotograma +tutorial.pipeline.behavior: "Después del diseño de entrada, agregue:" +tutorial.pipeline.context: "{cullNone} rellena el triángulo sin descartarlo por la orientación de sus caras. El orden de los vértices determina esa orientación; desactivar el descarte evita que dicho orden oculte nuestro primer triángulo." +tutorial.pipeline.description: "Ahora tenemos datos de vértices, un diseño de entrada y dos sombreadores. La {graphicsPipeline} los conecta y especifica cómo la GPU ensambla los vértices en primitivas y escribe el resultado en un adjunto." +tutorial.pipeline.details: "Una canalización combina etapas de sombreador programables con configuraciones de función fija, que controlan operaciones de GPU como ensamblado de triángulos, descarte de caras y mezcla. Para este triángulo, elija estas configuraciones:" +tutorial.pipeline.guidance: El formato de color proviene de {swapChainDescFormat}. Debe coincidir con la imagen utilizada por la pasada de renderizado. {count1} significa una muestra por píxel. +tutorial.pipeline.item: "{triangleList} ensambla cada grupo consecutivo de tres vértices en un triángulo. Suministraremos tres vértices y dibujaremos una vez, por lo que no se necesita un búfer de índices." +tutorial.pipeline.notes: "{depthNone} deshabilita la prueba y la escritura de profundidad, coincidiendo con la pasada sin adjunto de profundidad." +tutorial.pipeline.reference: "{opaque} deshabilita la mezcla, por lo que el color del sombreador de fragmentos reemplaza el fondo dentro del triángulo." +tutorial.pipeline.title: Conectar los sombreadores y el diseño de vértices +tutorial.pipeline.usage: Los objetos de sombreador se pueden liberar después de crear la canalización, como se hace en el renderizador de ejemplo. Mantenga viva la canalización en sí para cada fotograma que dibuje con ella. Agregue {pipelineDispose} antes de {vertexBufferDispose} en la limpieza. La creación de la canalización es el paso final de inicialización antes de la devolución de llamada de renderizado. +tutorial.pipeline.validation: "La descripción de la canalización declara la configuración del adjunto; no crea otra imagen. {inputLayouts} tiene una entrada porque la posición y el color se almacenan juntos en un solo búfer." +tutorial.presentation.title: Conectar la GPU a la ventana +tutorial.project.context: Habilite {emphasis} ({allowUnsafeBlocks}) en la configuración de compilación del proyecto. Lo utilizaremos para pasar datos de vértices a la GPU y para las llamadas nativas del asistente de ventanas. +tutorial.project.context.emphasis: Permitir código no seguro +tutorial.project.description: "Cree el proyecto y entre en su directorio:" +tutorial.project.details: "Instale los paquetes:" +tutorial.project.guidance: "{zenithNET} proporciona la API de renderizado compartida. Los tres paquetes de backend permiten que el mismo programa seleccione la implementación para su plataforma. {zenithNETCompiler} compila sombreadores Slang, los pequeños programas de GPU que escribiremos más adelante, para esa implementación. Silk.NET suministra la ventana y el bucle de eventos." +tutorial.project.title: Crear un proyecto de consola +tutorial.requirements.context: Puede seguir esta página desde un proyecto vacío. El {link} y su {detail} están disponibles como referencia para las API de renderizado y ventanas utilizadas aquí. +tutorial.requirements.context.detail: host compartido +tutorial.requirements.context.link: ejemplo Hola triángulo +tutorial.requirements.description: "Necesita el {emphasis}, un editor de código o IDE y un equipo de escritorio con una GPU y un controlador compatibles con un backend de Zenith.NET. Basta con tener conocimientos básicos de C#; los conceptos gráficos se introducen a medida que se utilizan. Este es un proyecto de consola {net10} ordinario. Un backend traduce las operaciones de Zenith.NET en llamadas a una API gráfica, como DirectX 12, Metal o Vulkan. La aplicación elige una al inicio:" +tutorial.requirements.description.emphasis: SDK de .NET 10 +tutorial.requirements.details: Linux necesita una sesión de ventanas compatible con X11 para la ruta de ventanas utilizada aquí. Las funciones opcionales de trazado de rayos y sombreado de mallas no son necesarias para este triángulo. +tutorial.requirements.guidance: Zenith.NET renderiza en una superficie suministrada por la aplicación. Silk.NET.Windowing creará la ventana de escritorio y procesará sus eventos. En macOS, el destino de presentación es una capa Metal ({cAMetalLayerCs}); el asistente de ventana del tutorial conecta esa capa por nosotros. +tutorial.requirements.table.headings.graphicsBackend: Backend gráfico +tutorial.requirements.table.headings.platform: Plataforma +tutorial.requirements.table.headings.windowSurface: Superficie de ventana +tutorial.requirements.table.linux.graphicsBackend: Vulkan 1.4 +tutorial.requirements.table.linux.platform: Linux +tutorial.requirements.table.linux.windowSurface: Ventana y pantalla X11; XWayland también es adecuado +tutorial.requirements.table.macOS.graphicsBackend: Metal 4 +tutorial.requirements.table.macOS.platform: macOS +tutorial.requirements.table.macOS.windowSurface: Capa Metal conectada a la ventana +tutorial.requirements.table.windows.graphicsBackend: DirectX 12 +tutorial.requirements.table.windows.platform: Windows +tutorial.requirements.table.windows.windowSurface: Identificador de ventana Win32 +tutorial.requirements.title: Antes de comenzar +tutorial.resize.context: "Ejecute {dotnetRun} nuevamente. La ventana ahora debería tener un fondo oscuro uniforme que continúe llenándola después de cambiar el tamaño. Conserve esta devolución de llamada: el triángulo se dibujará dentro de su pasada de renderizado existente." +tutorial.resize.description: "Las imágenes de la cadena de intercambio deben seguir las dimensiones del búfer de fotogramas. Utilice {framebufferResize} para responder a los cambios en el tamaño de píxeles, incluidos los cambios causados por la escala de pantalla. Después de la devolución de llamada de renderizado, aún antes de {windowRun}, agregue:" +tutorial.resize.details: "Silk.NET distingue los cambios de tamaño de ventana de los {link}. Necesitamos estos últimos porque la cadena de intercambio almacena píxeles. Una ventana minimizada puede tener un búfer de fotogramas de tamaño cero. En ese caso, ambas devoluciones de llamada omiten su trabajo de GPU. Después de cambiar el tamaño, la pasada de renderizado utilizará las nuevas dimensiones del adjunto para su ventana gráfica y recorte." +tutorial.resize.details.link: cambios de tamaño del búfer de fotogramas +tutorial.resize.guidance: Esperamos después de cada envío, por lo que ningún fotograma anterior sigue utilizando las imágenes cuando el controlador de cambio de tamaño las reemplaza. La implementación actual de {present} también espera en la cola de gráficos. Este bucle simple mantiene completo el trabajo de un fotograma antes de que comience el siguiente; {link} cubre una programación más avanzada. +tutorial.resize.guidance.link: Sincronización +tutorial.resize.title: Responder al cambio de tamaño +tutorial.shaders.compilation.context: La compilación se realiza una vez durante la inicialización. {appContextBaseDirectory} localiza el sombreador copiado junto al ejecutable, independientemente del directorio de trabajo actual. Estos sombreadores solo consumen entrada de vértices, por lo que aún no hay búferes de constantes, texturas ni identificadores de recursos para enlazar. +tutorial.shaders.compilation.description: En las propiedades del archivo para {triangleSlang}, establezca {emphasis} en {detail}. Esto hace que el sombreador esté disponible junto al ejecutable. +tutorial.shaders.compilation.description.detail: Copiar si es posterior +tutorial.shaders.compilation.description.emphasis: Copiar en el directorio de salida +tutorial.shaders.compilation.details: "Regrese a {programCs}. Después de la carga de vértices, agregue estas instrucciones de inicialización antes de la devolución de llamada de renderizado:" +tutorial.shaders.compilation.guidance: "{zenithCompiler} devuelve una descripción de sombreador que contiene código para la API gráfica solicitada. {createShader} crea el objeto de backend correspondiente. Tanto la API gráfica como los nombres de los puntos de entrada son importantes: use {contextGraphicsApi} y escriba {vSMain} y {fSMain} exactamente como en el archivo Slang." +tutorial.shaders.compilation.title: Compilar para el backend seleccionado +tutorial.shaders.context: "{fSInput} conecta la salida del sombreador de vértices con la entrada del sombreador de fragmentos. Cuando lo escribe el sombreador de vértices, {sVPOSITION} suministra una posición en espacio de recorte: las cuatro coordenadas que utiliza la GPU para determinar qué queda dentro de la imagen visible. {cOLOR0} transporta el color para interpolar entre vértices. Las dos etapas deben coincidir en su tipo y semántica." +tutorial.shaders.description: Un sombreador es un programa ejecutado por la GPU. Este dibujo necesita un sombreador de vértices para posicionar los vértices y un sombreador de fragmentos para producir los colores dentro del triángulo. Los escribiremos en Slang, un lenguaje de sombreadores, y compilaremos dos puntos de entrada desde el mismo archivo. Un punto de entrada es la función donde comienza a ejecutarse una etapa de sombreador. +tutorial.shaders.details: "Cree {triangleSlang}, comenzando con estas dos estructuras:" +tutorial.shaders.fragment.description: "Agregue el punto de entrada de fragmentos al mismo archivo:" +tutorial.shaders.fragment.details: "La rasterización determina qué ubicaciones de imagen cubre el triángulo. Produce fragmentos (los datos procesados por el sombreador de fragmentos) con los colores de los vértices interpolados en el área cubierta. {fSMain} devuelve este color interpolado a través de {sVTARGET}, que identifica el primer adjunto de color." +tutorial.shaders.fragment.guidance: "La interpolación del color de los vértices es independiente de la mezcla del adjunto. La mezcla combina la salida de un fragmento con el color ya almacenado en el adjunto. Nuestro estado de mezcla opaco desactiva esa combinación, por lo que el color interpolado reemplaza el fondo dentro del triángulo." +tutorial.shaders.fragment.title: Colorear los fragmentos +tutorial.shaders.guidance: "{vSInput} describe lo que recibe el sombreador de vértices desde el búfer de vértices. Las semánticas {pOSITION0} y {cOLOR0} identifican las entradas; los nombres de campos de C# por sí solos no establecen esa asignación." +tutorial.shaders.title: Escribir las dos etapas del sombreador +tutorial.shaders.vertex.description: "Agregue el punto de entrada de vértices a {triangleSlang}:" +tutorial.shaders.vertex.details: La GPU invoca este punto de entrada para cada vértice de entrada. Agrega la coordenada homogénea {w} a la posición y reenvía el color. Después de la etapa de vértices, la posición se divide por w; aquí esa división deja x, y y z sin cambios. Es por eso que las posiciones elegidas anteriormente se pueden entender directamente en coordenadas de dispositivo normalizadas. +tutorial.shaders.vertex.title: Posicionar cada vértice +tutorial.surface.description: "El contexto también necesita saber dónde mostrar su salida. Agregue lo siguiente {emphasis}:" +tutorial.surface.description.emphasis: después de {windowCenter} y antes de {windowRun} +tutorial.surface.details: "{surface} describe un destino de presentación nativo y sus dimensiones en píxeles. El búfer de fotogramas es la imagen de píxeles asociada a la ventana. {framebufferSize} proporciona sus dimensiones en píxeles; las dimensiones lógicas de la ventana pueden diferir cuando la escala de pantalla está activada." +tutorial.surface.guidance: La superficie coincide con el backend seleccionado anteriormente. Windows suministra un identificador de ventana, Linux suministra una pantalla y ventana X11, y el asistente de macOS suministra la capa Metal conectada. Esta es la única parte específica de la plataforma para conectar nuestra ventana al renderizado. +tutorial.surface.title: Describir la superficie nativa +tutorial.swapChain.context: "La cadena de intercambio utiliza tanto el contexto como la ventana nativa. Reemplace la línea {windowDispose} al final de {programCs} por este orden de limpieza:" +tutorial.swapChain.description: "Utilice la descripción de la superficie para crear las imágenes que se presentarán. Inmediatamente después del bloque de superficie, agregue:" +tutorial.swapChain.details: La {swapChain} gestiona las imágenes mostradas en la ventana. En cada fotograma, {drawable} nos proporciona la imagen actual como una {texture}, el tipo de API para datos de imagen. Después de dibujar, {present} solicita mostrar el resultado y avanza al siguiente drawable. +tutorial.swapChain.guidance: "{b8G8R8A8UNorm} almacena cuatro canales de color de 8 bits en orden azul, verde, rojo y alfa. {uNorm} significa que los valores enteros de 0 a 255 representan valores de 0 a 1. El sombreador seguirá devolviendo un valor RGBA lógico; este formato determina cómo se almacenan esos canales en la imagen. Más adelante, la canalización de gráficos utilizará {swapChainDescFormat} para coincidir con este adjunto." +tutorial.swapChain.title: Crear la cadena de intercambio +tutorial.title: Primer triángulo +tutorial.troubleshooting.description: "Lea primero cualquier error en la consola y luego use los puntos de comprobación anteriores para identificar la etapa que falló:" +tutorial.troubleshooting.details: Utilice el {link} y el {detail} para comparar los datos de vértices, el diseño de entrada y la operación de dibujo. Ese ejemplo coloca las ventanas y el envío en un host compartido; este tutorial mantiene el flujo de la aplicación en {programCs}. Continúe con {context} para aprender dibujo indexado, transformaciones y pruebas de profundidad. +tutorial.troubleshooting.details.context: Cubo giratorio +tutorial.troubleshooting.details.detail: sombreador Slang +tutorial.troubleshooting.details.link: renderizador de ejemplo +tutorial.troubleshooting.table.backend.check: Compruebe que el backend seleccionado sea compatible con el dispositivo y el controlador de gráficos instalado. +tutorial.troubleshooting.table.backend.symptom: Falla la creación del backend +tutorial.troubleshooting.table.drawing.check: Compruebe el tamaño de carga, el diseño de entrada, la selección de canalización y la ubicación de los comandos de dibujo dentro de la pasada de renderizado. +tutorial.troubleshooting.table.drawing.symptom: Aparece el fondo pero no el triángulo +tutorial.troubleshooting.table.headings.check: Comprobación +tutorial.troubleshooting.table.headings.symptom: Síntoma +tutorial.troubleshooting.table.input.check: Compruebe el stride de 28 bytes y los desplazamientos de posición/color de 0 y 12. +tutorial.troubleshooting.table.input.symptom: Las posiciones o colores de los vértices están dañados +tutorial.troubleshooting.table.shaders.check: Compruebe el archivo {triangleSlang} copiado, la ortografía del punto de entrada y el diagnóstico notificado por el compilador. +tutorial.troubleshooting.table.shaders.symptom: El paso del color de borrado funciona, pero la carga del sombreador falla +tutorial.troubleshooting.table.window.check: Confirme que el proyecto .NET se compila y que el paso de solo ventana se ejecuta en una sesión de escritorio. En Linux, compruebe que X11 o XWayland estén disponibles. +tutorial.troubleshooting.table.window.symptom: No se abre ninguna ventana +tutorial.troubleshooting.title: Comprobar la etapa que falló +tutorial.window.context: "{usingZenithTutorials} importa el espacio de nombres del asistente. Cada archivo de C# usa sus propias directivas using habituales, por lo que la importación de interoperabilidad es necesaria en ambos archivos. El alias {buffer} se refiere al tipo de búfer de Zenith.NET y lo distingue de {systemBuffer}." +tutorial.window.description: Agregue {cocoaHelperCs} al proyecto, conservando su espacio de nombres. Agregue {interopUsing} en la parte superior de ese archivo, antes de su declaración de espacio de nombres. El asistente conecta una capa Metal a la ventana en macOS; las ramas de otras plataformas no lo llaman. +tutorial.window.details: "Reemplace el archivo {programCs} generado por el siguiente código. Utiliza instrucciones de nivel superior, que se ejecutan en orden sin un método {main} explícito. Las secciones posteriores le indicarán dónde agregar código a este mismo archivo:" +tutorial.window.guidance: "{graphicsAPINone} solicita a Silk.NET que cree una ventana sin su propio contexto gráfico. Crearemos ese contexto con Zenith.NET. {initialize} crea la ventana nativa y pone a disposición sus identificadores. Un identificador es proporcionado por el sistema de ventanas. {center} centra la ventana y {run} procesa eventos hasta que se cierra. La ejecución continúa luego hacia {dispose}, que libera la ventana." +tutorial.window.notes: Ejecute {dotnetRun}. Debería abrirse una ventana vacía y responder a mover, cambiar de tamaño y cerrar. Su contenido aún no está definido porque no hemos enviado ningún comando de renderizado. Ciérrela antes de continuar. +tutorial.window.title: Abrir una ventana +ui.action.copy: Copiar +ui.action.navigate: Navegar +ui.action.open: Abrir +ui.action.source: Ver código fuente +ui.api.browse: Examinar espacios de nombres y tipos. +ui.api.clearTypeSearch: Borrar búsqueda de tipos +ui.api.findType: Buscar un tipo +ui.api.loadError: No se pudieron cargar los tipos. Recargue esta página para intentarlo de nuevo. +ui.api.loadingNamespaces: Cargando espacios de nombres… +ui.api.loadingTypes: Cargando tipos… +ui.api.matchingTypes: Tipos coincidentes +ui.api.namespace: Espacio de nombres +ui.api.namespaces: Espacios de nombres +ui.api.noNamespaceTypes: No hay tipos en este espacio de nombres. +ui.api.noTypes: No hay tipos coincidentes. +ui.api.types: Tipos +ui.content.reference: Referencia +ui.content.source: Código fuente +ui.content.tutorial: Tutorial +ui.contents.close: Cerrar contenido +ui.contents.open: Abrir contenido +ui.contents.title: Contenido +ui.footer.caption: RHI moderno para .NET. +ui.footer.label: Pie de página +ui.language.label: Idioma +ui.language.unavailable: No traducido +ui.members.clear: Borrar búsqueda de miembros +ui.members.close: Cerrar buscador de miembros +ui.members.empty: No hay miembros coincidentes. +ui.members.open: Ir al miembro +ui.members.placeholder: Nombre o firma… +ui.members.search: Buscar miembros +ui.members.title: Buscar un miembro +ui.members.undeclared: Este tipo no tiene miembros declarados. +ui.navigation.api: API +ui.navigation.concepts: Conceptos +ui.navigation.home: Inicio +ui.navigation.label: Navegación principal +ui.navigation.toggle: Alternar navegación +ui.outline.title: En esta página +ui.reference.assembly: Ensamblado +ui.reference.classes: Clases +ui.reference.constructors: Constructores +ui.reference.declaration: "Declaración de tipo C#" +ui.reference.delegates: Delegados +ui.reference.derived: Tipos derivados +ui.reference.enums: Enumeraciones +ui.reference.events: Eventos +ui.reference.examples: Ejemplos +ui.reference.exceptions: Excepciones +ui.reference.extensionMethods: Métodos de extensión +ui.reference.fields: Campos +ui.reference.implementations: Implementaciones explícitas de interfaz +ui.reference.implements: Implementa +ui.reference.inheritance: Herencia +ui.reference.inheritedMembers: Miembros heredados +ui.reference.interfaces: Interfaces +ui.reference.metadata: Metadatos de tipo +ui.reference.methods: Métodos +ui.reference.namespace: Espacio de nombres +ui.reference.open: Abrir referencia de {name} +ui.reference.operators: Operadores +ui.reference.parameters: Parámetros +ui.reference.properties: Propiedades +ui.reference.related: Vea también +ui.reference.relationships: Herencia y metadatos +ui.reference.remarks: Comentarios +ui.reference.returns: Devuelve +ui.reference.structs: Estructuras +ui.reference.typeParameters: Parámetros de tipo +ui.reference.value: Valor +ui.reference.values: Valores +ui.search.close: Cerrar búsqueda +ui.search.empty: No hay resultados para «{query}». +ui.search.hint: Busque en tutoriales, conceptos, ejemplos y en la referencia de la API. +ui.search.loading: Cargando búsqueda… +ui.search.more: Mostrar más resultados +ui.search.pending: Buscando… +ui.search.placeholder: ¿Qué está buscando? +ui.search.resultCount: "Resultados: {count}" +ui.search.title: Buscar en la documentación +ui.search.unavailable: La búsqueda no está disponible. Aún puede abrir las páginas siguientes. diff --git a/documents/locales/fr-FR/strings.yml b/documents/locales/fr-FR/strings.yml new file mode 100644 index 00000000..fefe795e --- /dev/null +++ b/documents/locales/fr-FR/strings.yml @@ -0,0 +1,604 @@ +### YamlMime:Resources +concepts.execution.context.description: Un {graphicsContext} représente un périphérique backend et fournit ses files de graphisme, de calcul et de transfert. Créez les tampons, textures, shaders et pipelines pour une charge de travail via le même contexte. Une ressource ou un handle créé par un autre contexte ne peut pas simplement être lié aux tampons de commandes de celui-ci. +concepts.execution.context.details: Choisissez le backend pour la plateforme et la surface de présentation. L’API reste partagée, mais la prise en charge des périphériques compte toujours. {capabilities} expose le nom du périphérique et les indicateurs {rayTracingSupported} et {meshShadingSupported}. Vérifiez l’indicateur correspondant avant de créer une charge de travail optionnelle, comme le font les exemples {link} et {detail}. Ces indicateurs ne constituent pas une liste exhaustive des restrictions de format, de mémoire ou de plateforme. +concepts.execution.context.details.detail: mesh shading +concepts.execution.context.details.link: lancer de rayons +concepts.execution.context.title: Le contexte relie les ressources et les files +concepts.execution.description: Une application Zenith.NET crée des ressources GPU, enregistre des commandes qui les utilisent et soumet ces commandes à une file. Le CPU peut continuer pendant que le GPU exécute la soumission. Gardez les ressources valides jusqu’à ce que ce travail soit terminé, même après le retour des appels d’enregistrement. +concepts.execution.ownership.description: "Ici, la propriété signifie la responsabilité de la libération. Une référence C# maintient un objet managé accessible ; elle n’empêche pas un {dispose} explicite de détruire la ressource native. De même, la soumission d’une commande qui utilise un tampon ne transfère pas la propriété de ce tampon à la file." +concepts.execution.ownership.details: Lors de l’arrêt, cessez de soumettre de nouveaux travaux, attendez les dernières utilisations sur chaque file impliquée, libérez les ressources de l’application, puis libérez le contexte. La libération du contexte libère ses propres files et assistants internes ; elle n’attend pas tous les travaux de l’application et ne libère pas chaque ressource créée par l’application. +concepts.execution.ownership.guidance: Appliquez les mêmes règles de durée de vie pendant le rendu. Conservez la valeur d’achèvement pour la dernière utilisation d’une ressource afin de savoir quand ses octets peuvent être écrasés ou quand la ressource peut être remplacée. Consultez {link} pour les vues et les durées de vie des ressources sous-jacentes. +concepts.execution.ownership.guidance.link: Gestion des ressources +concepts.execution.ownership.table.applicationResources.object: Ressources créées par l’application +concepts.execution.ownership.table.applicationResources.ownership: L’application les libère après leur dernière utilisation par le GPU. +concepts.execution.ownership.table.commandBuffers.object: Tampons de commandes empruntés +concepts.execution.ownership.table.commandBuffers.ownership: La file les gère et les recycle. +concepts.execution.ownership.table.headings.object: Objet +concepts.execution.ownership.table.headings.ownership: Qui le libère ? +concepts.execution.ownership.table.queues.object: Files de contexte et leurs lignes de temps +concepts.execution.ownership.table.queues.ownership: Le contexte et les files les gèrent. +concepts.execution.ownership.table.swapChainDrawable.ownership: La chaîne d’échange la gère. +concepts.execution.ownership.title: Séparer la propriété de l’achèvement GPU +concepts.execution.pipelines.description: Un pipeline graphique combine les shaders, l’agencement d’entrée des sommets, la règle d’assemblage des sommets en primitives, les formats d’attachement et l’état de rendu. Définissez-le avant de lier les données de sommets, d’indices ou de constantes et d’émettre des commandes de dessin. Ses formats d’attachement et son nombre d’échantillons doivent correspondre aux attachements de la passe de rendu. +concepts.execution.pipelines.details: Un pipeline de calcul fournit le point d’entrée de shader pour un dispatch, qui lance des groupes de threads GPU. Définissez-le ainsi que ses constantes avant le dispatch. Les dispatches de calcul appartiennent à l’extérieur des passes de rendu graphique. Changer de pipeline modifie la façon dont les commandes ultérieures interprètent leurs entrées ; liez les données requises par le pipeline sélectionné avant de l’utiliser. +concepts.execution.pipelines.guidance: Le {link} montre la séquence graphique complète. L’{detail} enregistre un dispatch suivi d’une passe graphique qui affiche le résultat. +concepts.execution.pipelines.guidance.detail: exemple de calcul +concepts.execution.pipelines.guidance.link: rappel de rendu du triangle +concepts.execution.pipelines.title: Un pipeline détermine comment les commandes interprètent les données +concepts.execution.queues.description: Commencez avec {graphicsQueue} lorsqu’une image combine dessin, calcul et copies. Conserver le travail dépendant sur une seule file rend son ordonnancement plus facile à suivre. +concepts.execution.queues.details: Une file accepte des lots de commandes pour exécution. Des files distinctes ne correspondent pas nécessairement à des moteurs matériels distincts, de sorte que leur travail peut ne pas s’exécuter simultanément. Utilisez une autre file lorsque la charge de travail peut bénéficier d’un chevauchement, et ajoutez une dépendance explicite lorsqu’une file consomme les résultats d’une autre file. +concepts.execution.queues.guidance: Lorsque des commandes ultérieures dépendent d’écritures antérieures, l’application doit également s’assurer que ces écritures sont disponibles pour les commandes ultérieures. La soumission des deux tampons de commandes à la même file n’établit pas automatiquement chaque dépendance de ce type. Les commandes peuvent utiliser différentes étapes de GPU, et les accès ultérieurs peuvent nécessiter une barrière ou une transition de texture. {link} explique la distinction entre ordre de soumission et visibilité des ressources. +concepts.execution.queues.guidance.link: Synchronisation +concepts.execution.queues.table.computeQueue.workToRecord: Dispatches de calcul et travail de transfert compatible, sans passes de rendu graphique. +concepts.execution.queues.table.graphicsQueue.workToRecord: Passes de rendu et dessin, plus opérations de calcul et de transfert utilisées par l’image. +concepts.execution.queues.table.headings.queue: File +concepts.execution.queues.table.headings.workToRecord: Travail à enregistrer +concepts.execution.queues.table.transferQueue.workToRecord: Travail de chargement, téléchargement et copie, sans dessin ni dispatches de calcul. +concepts.execution.queues.title: Choisir une file pour le travail qu’elle exécutera +concepts.execution.recording.context: La file interroge l’achèvement et recycle les tampons de commandes terminés. Appelez {queueCommandBuffer} pour chaque nouvel enregistrement ; il peut renvoyer une instance recyclée. Ne libérez pas un tampon de commandes emprunté, ne le soumettez pas deux fois et ne continuez pas à y enregistrer après soumission. Enregistrez un tampon de commandes donné depuis un seul thread à la fois ; le verrouillage interne de la file ne protège pas contre les modifications simultanées d’un tampon de commandes. +concepts.execution.recording.description: "{queueCommandBuffer} renvoie un {commandBuffer} dont l’enregistrement a déjà commencé. Enregistrez les commandes et leurs dépendances, puis appelez {submit} une fois. La soumission met fin à l’enregistrement et renvoie une {timelineValue} identifiant un point d’achèvement sur cette file." +concepts.execution.recording.details: "Par exemple, après avoir enregistré une image dans {commandBuffer}, le tutoriel du triangle soumet ce tampon et attend son achèvement ainsi :" +concepts.execution.recording.guidance: "{submit} planifie le travail ; {wait} empêche le CPU de continuer jusqu’à ce que cette soumission soit terminée. L’enregistrement d’un dessin, la fin d’une passe de rendu et la soumission d’un tampon de commandes sont des opérations distinctes. Ni l’enregistrement du dessin ni la fin de la passe n’attendent le GPU." +concepts.execution.recording.title: L’enregistrement n’exécute pas les commandes +concepts.execution.title: Modèle d’exécution +concepts.platforms.description: Choisissez si votre application possède la fenêtre native et la boucle de trame ou si elle utilise un contrôle de rendu d’interface utilisateur. Ce choix détermine qui obtient la texture de sortie, soumet les commandes et présente le résultat. La texture de sortie est la texture utilisée comme sortie de l’image actuelle. Les travaux graphiques et de calcul hors écran ne nécessitent ni fenêtre ni chaîne d’échange. +concepts.platforms.frame.context: Ajoutez vos liaisons de pipeline et vos commandes de dessin à l’intérieur de cette passe. Terminez la passe avant de revenir. Ne soumettez pas le tampon de commandes fourni et ne présentez pas de manière indépendante, et ne libérez ni le tampon de commandes ni la texture de sortie. Si votre gestionnaire utilise la texture de sortie dans un autre layout, remettez-la en {colorAttachment} pour la transition finale du contrôle. +concepts.platforms.frame.description: Les intégrations implémentent {iZenithView}. L’application fournit son {graphicsContext}, met à jour les données de scène dans {updateRequested} et enregistre le rendu dans {renderRequested} à l’aide de {renderEventArgs}. +concepts.platforms.frame.details: "Le contrôle gère le déroulement complet de chaque image. Il obtient la texture de sortie et le tampon de commandes, fait passer la texture à {colorAttachment}, appelle les gestionnaires, puis effectue la soumission et la présentation requises par le framework." +concepts.platforms.frame.guidance: "Pour une {iZenithView} initialisée nommée {view}, avec un contexte attribué, ce gestionnaire enregistre une passe d’effacement complète. Il nécessite {usingZenithNET} :" +concepts.platforms.frame.notes: Les contrôles effectuent une transition depuis {undefined} au début de chaque image, de sorte que les applications ne peuvent pas compter sur la préservation du contenu précédent de la texture de sortie. Effacez ou rendez l’image requise à chaque image. Conservez l’accumulation persistante ou le rendu mis en cache dans une texture appartenant à l’application, puis affichez cette texture via la vue. +concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat} fournit le format de couleur par défaut des intégrations. Vérifiez la texture de sortie réelle de l’événement lors de la mise en correspondance des formats d’attachement, des nombres d’échantillons et des dimensions." +concepts.platforms.frame.title: Enregistrer dans l’image fournie par un contrôle d’interface utilisateur +concepts.platforms.integration.context: WinForms, WPF et la voie WinUI sous Windows nécessitent Windows. Les applications MAUI ont besoin de la charge de travail de leur plateforme cible et doivent enregistrer le gestionnaire de contrôle avec {useZenithView} ; voir {extensionsCs}. La prise en charge du framework et celle du backend doivent toutes deux être satisfaites. +concepts.platforms.integration.description: "Les contrôles partagent l’interface d’événements, mais ils ne présentent pas tous de la même manière :" +concepts.platforms.integration.details: La lecture de bitmap (bitmap readback) copie les pixels rendus dans la mémoire CPU avant que l’interface utilisateur ne les affiche. L’interopérabilité par texture partagée évite cette lecture, mais peut toujours nécessiter des copies et une synchronisation GPU. L’interface partagée {renderRequested} n’implique donc pas des coûts de présentation identiques ou des exigences d’interopérabilité native identiques. +concepts.platforms.integration.guidance: "Utilisez le paquet adapté au framework de l’application ; par exemple :" +concepts.platforms.integration.table.avalonia.integration: Avalonia +concepts.platforms.integration.table.avalonia.presentation: Effectue le rendu dans une texture et télécharge les pixels dans un {writeableBitmap}. Voir {zenithViewCs} et {surfaceCs}. +concepts.platforms.integration.table.headings.integration: Intégration +concepts.platforms.integration.table.headings.presentation: Comment son image parvient à l’interface +concepts.platforms.integration.table.maui.integration: .NET MAUI +concepts.platforms.integration.table.maui.presentation: Utilise des surfaces natives sur Android, iOS et Mac Catalyst, et la composition par texture partagée sous Windows. Voir les {link}. +concepts.platforms.integration.table.maui.presentation.link: implémentations de plateforme +concepts.platforms.integration.table.uno.integration: Voie Uno +concepts.platforms.integration.table.uno.presentation: Télécharge les pixels dans un {writeableBitmap}. Voir {zenithViewUnoCs}. +concepts.platforms.integration.table.winForms.integration: WinForms +concepts.platforms.integration.table.winForms.presentation: Crée une chaîne d’échange Zenith.NET pour le {hWND} du contrôle. Voir {zenithViewCs}. +concepts.platforms.integration.table.winUI.integration: WinUI sous Windows +concepts.platforms.integration.table.winUI.presentation: Effectue le rendu dans une texture partagée Direct3D 11 importée, puis copie vers une chaîne d’échange de composition attachée à {swapChainPanel}. Voir {zenithViewWinUICs}. +concepts.platforms.integration.table.wpf.integration: WPF +concepts.platforms.integration.table.wpf.presentation: Importe une texture partagée Direct3D 11, puis copie via l’interopérabilité Direct3D vers une surface affichée par {d3DImage}. Voir {surfaceCs}. +concepts.platforms.integration.title: Choisir la voie de présentation ainsi que le framework +concepts.platforms.lifecycle.context: Pour une vue d’interface utilisateur, utilisez les propriétés {descWidth}, {descHeight}, {descFormat} et {descSampleCount} de la texture de sortie de l’événement lors de la création de ressources de rendu correspondantes. Le contrôle détermine la résolution de cette texture de sortie ; ne supposez pas que ses dimensions logiques ou son échelle d’affichage sont toujours égales aux dimensions de la texture. +concepts.platforms.lifecycle.description: Pour une chaîne d’échange native, transmettez les dimensions du tampon de trame en pixels. Les tailles de fenêtre exprimées en unités logiques peuvent différer lorsque la mise à l’échelle de l’affichage est activée. Ignorez les tampons de trame de taille zéro, redimensionnez la chaîne d’échange lorsque sa taille de pixel change et obtenez {swapChainDrawable} pour chaque image. La texture de sortie appartient à la chaîne d’échange et peut changer après la présentation ou le redimensionnement. +concepts.platforms.lifecycle.details: "{swapChainResize} modifie les dimensions de la surface existante. {swapChainRefresh} remplace la description de la surface, y compris ses handles natifs. Avant l’une ou l’autre opération, terminez les utilisations en cours des ressources affectées. Libérez la chaîne d’échange avant de détruire sa cible de présentation native." +concepts.platforms.lifecycle.guidance: Recréez les textures de profondeur ou hors écran appartenant à l’application dont la taille suit la fenêtre, et mettez à jour les constantes contenant leurs handles. Un pipeline peut rester utilisé à travers un changement de taille lorsque ses formats d’attachement et son nombre d’échantillons restent compatibles. Le {link} conserve son pipeline tout en remplaçant sa texture de profondeur. +concepts.platforms.lifecycle.guidance.link: moteur de rendu du cube en rotation +concepts.platforms.lifecycle.title: Conserver la taille et la durée de vie de la texture de sortie avec son hôte +concepts.platforms.ownership.description: L’application possède le contexte qu’elle assigne et les ressources qu’elle crée pour le rendu. Le contrôle possède ses propres ressources de présentation. La modification de la propriété {graphicsContext} de la vue amène le planificateur à recréer les ressources du contrôle ; cela ne recrée pas les pipelines, tampons ou textures de l’application pour le nouveau contexte. +concepts.platforms.ownership.details: Coordonnez le remplacement des ressources avec le cycle de vie de l’image de la vue. Arrêtez l’activité de trame de la vue et terminez les utilisations GPU en attente avant de libérer les ressources de l’application ou le contexte assigné. La suppression d’une vue ne transfère pas la propriété du contexte au contrôle. +concepts.platforms.ownership.guidance: Le fichier partagé {frameSchedulerCs} distribue le travail de trame via le dispatcher UI de la vue. Gardez les gestionnaires de trame concentrés sur la mise à jour et l’enregistrement de l’image ; un travail CPU prolongé à cet endroit retarde également l’interface utilisateur. +concepts.platforms.ownership.title: Conserver les ressources de l’application en dehors de la propriété du contrôle +concepts.platforms.surface.context: Une bibliothèque de fenêtrage ou un framework d’interface utilisateur prenant en charge un système d’exploitation ne garantit pas que le backend GPU sélectionné y soit disponible. Les fonctionnalités matérielles, les pilotes et la prise en charge des surfaces natives doivent toujours concorder. Vérifiez le lancer de rayons et le mesh shading optionnels via {contextCapabilities} avant de créer ces charges de travail. +concepts.platforms.surface.description: Le {link} utilise Silk.NET pour créer une fenêtre et traiter les événements. Zenith.NET se connecte à cette fenêtre via une description de {surface} et une {swapChain}. Une surface contient des handles et des dimensions natifs ; la construction de la description ne crée ni ne possède la fenêtre du système d’exploitation. +concepts.platforms.surface.description.link: triangle +concepts.platforms.surface.details: "Le handle doit correspondre au backend sélectionné :" +concepts.platforms.surface.guidance: Le fichier {appCs} du tutoriel montre les choix pour Windows, macOS et X11. Son hôte Linux fournit des handles Xlib ; l’utiliser dans une session Wayland nécessite XWayland. Une application Wayland native fournirait des handles différents via {surfaceWayland}. +concepts.platforms.surface.table.android.backend: Vulkan sous Android. +concepts.platforms.surface.table.apple.backend: Metal sur les plateformes Apple. +concepts.platforms.surface.table.headings.backend: Chemin de backend +concepts.platforms.surface.table.headings.factory: Fabrique de surface +concepts.platforms.surface.table.headings.handles: Handles fournis par l’hôte +concepts.platforms.surface.table.wayland.backend: Vulkan avec un hôte Wayland natif. +concepts.platforms.surface.table.wayland.handles: Affichage et surface Wayland +concepts.platforms.surface.table.win32.backend: DirectX 12 ou Vulkan sous Windows. +concepts.platforms.surface.table.xlib.backend: Vulkan sous Linux avec X11 ou XWayland. +concepts.platforms.surface.table.xlib.handles: Affichage et fenêtre X11 +concepts.platforms.surface.title: Fournir une surface native lorsque l’application possède la présentation +concepts.platforms.title: Intégration de plateforme +concepts.resources.allocation.context: "Commencez par des ressources créées via le contexte, sauf si vous avez besoin de votre propre allocateur. Avec un tas, attendez la fin de tous les travaux GPU utilisant ses ressources, puis libérez les ressources placées avant de libérer le tas lui-même." +concepts.resources.allocation.description: "Un {heap} fournit de la mémoire dans laquelle vous placez les ressources à des décalages explicites en octets. L’application choisit ces décalages et suit les régions utilisées." +concepts.resources.allocation.details: "Avant de placer une ressource, utilisez {contextGetSizeAndAlignment} avec sa description exacte de tampon ou de texture. Choisissez un décalage multiple de l’alignement renvoyé, réservez la taille renvoyée et gardez la ressource dans les limites de la taille totale du tas. Les allocations encore utilisées ne doivent pas se chevaucher. Le stockage d’une texture peut inclure du remplissage et un alignement propres au backend ; multiplier le nombre de pixels par le nombre d’octets par pixel ne donne donc pas la taille de l’allocation." +concepts.resources.allocation.guidance: "Pour les tampons placés, faites correspondre la résidence du tampon à celle du tas. Utilisez des tas réservés au GPU pour les textures GPU ordinaires décrites ici. La taille et l’alignement sont des exigences de placement ; ils ne garantissent pas que toute ressource puisse être placée dans n’importe quel tas sur tous les backends." +concepts.resources.allocation.title: Placer des ressources dans un tas lorsqu’un contrôle d’allocation est requis +concepts.resources.bufferUsages.table.constant.role: Paramètres de shader lus via une liaison de tampon de constantes. +concepts.resources.bufferUsages.table.headings.role: "Rôle" +concepts.resources.bufferUsages.table.headings.usage: Usage +concepts.resources.bufferUsages.table.index.role: Indices utilisés par le dessin indexé. +concepts.resources.bufferUsages.table.indirect.role: "Arguments lus par les commandes de dessin ou de dispatch indirects." +concepts.resources.bufferUsages.table.none.role: "Aucun indicateur d’usage du tampon n’est déclaré." +concepts.resources.bufferUsages.table.storageReadOnly.role: "Données de tampon accessibles via une liaison de shader en lecture seule." +concepts.resources.bufferUsages.table.storageReadWrite.role: "Données de tampon accessibles via une liaison de shader en lecture et écriture." +concepts.resources.bufferUsages.table.transferDst.role: "Stockage de destination d’une copie GPU." +concepts.resources.bufferUsages.table.transferSrc.role: "Données sources d’une copie GPU." +concepts.resources.bufferUsages.table.vertex.role: Attributs de sommets récupérés pour le dessin. +concepts.resources.bufferUsages.title: Usages de tampon +concepts.resources.description: "Choisissez la description d’une ressource selon les opérations qui l’utiliseront. Une texture qui reçoit un rendu, est échantillonnée par un shader et est relue par le CPU doit déclarer ces trois usages et assurer leur synchronisation. Le placement mémoire et la durée de vie de la ressource sont des décisions supplémentaires." +concepts.resources.memory.context: Pour un tampon accessible par le CPU, {map} fournit une adresse au CPU. Il n’attend pas que le GPU cesse d’accéder aux mêmes octets. {unmap} de même ne soumet aucun travail et n’attend pas l’achèvement. Avant d’écraser des données accessibles en écriture par le CPU, terminez les lectures GPU qui ont encore besoin de leur ancien contenu. +concepts.resources.memory.description: "Un {bufferDesc} possède un champ {residency}. Choisissez-le selon la manière dont le CPU et le GPU accèdent aux données :" +concepts.resources.memory.details: La résidence décrit l’accès CPU prévu à l’allocation. Elle n’implique pas que chaque périphérique dispose d’une mémoire physique CPU et GPU séparée. Le triangle utilise {cpuWriteOnly} pour initialiser directement un petit tampon de sommets. Un grand maillage statique peut plutôt bénéficier d’un stockage réservé au GPU avec un transfert unique. +concepts.resources.memory.guidance: "{textureDesc} ne possède aucun champ de résidence. Les textures ordinaires créées par le contexte utilisent un stockage GPU. Leur API publique fournit des opérations de transfert et de lecture pour les transferts de données CPU, sans exposer de méthode de mappage direct. Les tas explicites fournissent un contrôle de placement, décrit ci-dessous." +concepts.resources.memory.table.cpuReadOnly.cPUAccess: "Lire la mémoire mappée après la fin de la copie GPU." +concepts.resources.memory.table.cpuReadOnly.typicalRole: "Données produites par le GPU pour être relues par le CPU" +concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "Écrire dans la mémoire mappée après la fin des lectures GPU précédentes." +concepts.resources.memory.table.cpuWriteOnly.typicalRole: "Données fournies ou mises à jour par le CPU" +concepts.resources.memory.table.gpuOnly.cPUAccess: "Transférer les octets via un tampon de transfert vers le GPU ou de lecture depuis le GPU." +concepts.resources.memory.table.gpuOnly.typicalRole: "Géométrie statique et données de travail du GPU" +concepts.resources.memory.table.headings.cPUAccess: Accès CPU +concepts.resources.memory.table.headings.residency: Résidence +concepts.resources.memory.table.headings.typicalRole: Rôle typique +concepts.resources.memory.title: "Choisir la mémoire selon l’accès CPU nécessaire" +concepts.resources.textureUsages.description: "Les indicateurs d’usage de transfert décrivent le sens des copies GPU. L’accès CPU relève d’un choix distinct de placement mémoire, décrit plus bas." +concepts.resources.textureUsages.details: "Combiner des indicateurs d’usage déclare plusieurs rôles ; cela n’exécute pas les opérations et n’ordonne pas leurs accès. Les textures nécessitent toujours des choix adaptés de {link}, et leurs formats doivent prendre en charge les usages demandés sur le périphérique choisi." +concepts.resources.textureUsages.details.link: "layout et de synchronisation" +concepts.resources.textureUsages.table.colorAttachment.role: "Un attachement de couleur dans une passe de rendu." +concepts.resources.textureUsages.table.depthStencilAttachment.role: "Un attachement de profondeur et de stencil dans une passe de rendu." +concepts.resources.textureUsages.table.headings.role: "Rôle" +concepts.resources.textureUsages.table.headings.usage: Usage +concepts.resources.textureUsages.table.none.role: "Aucun indicateur d’usage de la texture n’est déclaré." +concepts.resources.textureUsages.table.sampled.role: "Données de texture lues via une liaison de texture échantillonnée." +concepts.resources.textureUsages.table.storage.role: "Données de texture accessibles via une liaison de texture de stockage pour les lectures ou écritures des shaders." +concepts.resources.textureUsages.table.transferDst.role: "Stockage de l’image de destination d’une copie GPU." +concepts.resources.textureUsages.table.transferSrc.role: "Données de l’image source d’une copie GPU." +concepts.resources.textureUsages.title: Usages de texture +concepts.resources.title: Gestion des ressources +concepts.resources.transfers.context: Un téléchargement enregistre une copie GPU dans un stockage interne de lecture. La bibliothèque copie ces octets dans la destination CPU fournie lorsqu’elle réinitialise le tampon de commandes terminé pour le réutiliser. Gardez la destination allouée, et gardez la mémoire managée épinglée, jusqu’à ce que le {wait} de la valeur de soumission revienne. +concepts.resources.transfers.description: "Un transfert vers le GPU copie les données CPU dans une ressource GPU ; une lecture depuis le GPU ramène les données de la ressource en mémoire CPU. Les méthodes de la ressource terminent ce transfert avant de rendre la main :" +concepts.resources.transfers.details: "Ces attentes couvrent uniquement le transfert soumis par ces méthodes. Elles ne détectent pas les dépendances envers une autre file qui lisait ou écrivait déjà la ressource. Établissez ces dépendances avant d’appeler la méthode de la ressource. Une copie directe via la mémoire mappée exige elle aussi que l’appelant s’assure de l’achèvement du travail GPU concerné." +concepts.resources.transfers.guidance: "Utilisez {commandBufferUpload} ou {commandBufferDownload} lorsque les copies doivent être enregistrées avec d’autres travaux. Les durées de vie de leurs pointeurs diffèrent :" +concepts.resources.transfers.item: "Un transfert vers le GPU copie les données sources du CPU dans un tampon interne de transfert, également appelé mémoire intermédiaire ou staging, pendant l’appel. Le pointeur source doit rester valide uniquement pendant cet appel." +concepts.resources.transfers.notes: "Pour une texture, le pas de ligne est la distance en octets entre deux lignes successives de données CPU ; le pas de tranche est la distance en octets entre deux tranches de profondeur successives. Ils ne décrivent pas l’organisation interne de la texture en mémoire GPU. Consultez {link} pour distinguer l’achèvement GPU de la disponibilité des données relues." +concepts.resources.transfers.notes.link: Synchronisation +concepts.resources.transfers.table.bufferDownload.transfer: Copie directe du CPU pour {cpuReadOnly} ; sinon, soumet un téléchargement sur la file de transfert et attend. +concepts.resources.transfers.table.bufferUpload.transfer: Copie directe du CPU pour {cpuWriteOnly} ; sinon, soumet un transfert sur la file de transfert et attend. +concepts.resources.transfers.table.headings.method: Méthode +concepts.resources.transfers.table.headings.transfer: "Mode de transfert des données" +concepts.resources.transfers.table.textureTransfers.method: "{textureUpload} / {textureDownload}" +concepts.resources.transfers.table.textureTransfers.transfer: "Utilise la file graphique, fait passer la sous-ressource sélectionnée au layout nécessaire à la copie, puis au layout final demandé, et attend la fin du transfert." +concepts.resources.transfers.title: "Choisir entre transferts immédiats et transferts enregistrés" +concepts.resources.usages.description: "{bufferUsages} et {textureUsages} sont des énumérations d’indicateurs qui déclarent les rôles prévus d’une ressource. Ils sont affectés respectivement à {bufferDescUsages} et {textureDescUsages}. Une énumération d’indicateurs permet de combiner plusieurs membres avec {value} lorsqu’une ressource a plus d’un rôle." +concepts.resources.usages.title: Déclarer les usages requis avant de créer une ressource +concepts.resources.views.description: Une {bufferView} décrit une région de tampon et son interprétation. Une {textureView} sélectionne un type de texture compatible, un format et une plage de sous-ressources. Une vue partage le stockage sous-jacent ; elle ne copie pas les données et n’ajoute pas d’usages qui manquaient lors de la création de la ressource. Sa plage n’est pas non plus une garantie portable de vérification des limites dans le shader. +concepts.resources.views.details: "Utilisez le handle de la ressource pour sa vue par défaut, ou créez une vue si une autre région ou une interprétation compatible différente est nécessaire. Conservez les références C# vers la vue et sa ressource sous-jacente tant que des travaux GPU peuvent les utiliser ; un handle de ressource seul ne maintient aucun des deux objets en vie. Libérez-les uniquement après leur dernière utilisation GPU. Après avoir remplacé l’un des objets, mettez à jour les constantes contenant son ancien {link}." +concepts.resources.views.details.link: "handle de ressource" +concepts.resources.views.guidance: Le {link} montre une texture de profondeur remplacée lors du redimensionnement. L’{detail} montre une texture d’entrée maintenue séparée de sa sortie accessible en écriture. Les deux font suivre la durée de vie de la ressource au travail qui l’utilise réellement. +concepts.resources.views.guidance.detail: exemple de calcul +concepts.resources.views.guidance.link: moteur de rendu du cube en rotation +concepts.resources.views.title: "Garder les vues et leurs ressources sous-jacentes utilisables ensemble" +concepts.shaders.binding.context: "Dans l’exemple de calcul, {input} est rempli avec {inputTextureSampledHandle} et {output} avec {outputTextureStorageHandle}. Le {descriptorHandle} typé de Slang indique au shader comment accéder à chaque ressource :" +concepts.shaders.binding.description: "{setConstantBuffer} lie un tampon et un décalage d’octets pour les données de constantes du pipeline actuel. Il lie un stockage existant visible par le GPU ; il ne transfère pas de valeur C#. Remplissez d’abord le tampon et assurez-vous que les lecteurs GPU antérieurs ont terminé avant d’écraser ses octets." +concepts.shaders.binding.details: "Définissez le pipeline avant son tampon de constantes. Pour une charge de travail de calcul avec des ressources déjà créées et transférées, l’enregistrement utilise cet ordre :" +concepts.shaders.binding.guidance: Ce fragment suppose un {commandBuffer} en cours d’enregistrement, un {computePipeline}, un {constantBuffer} transféré avec l’usage {bufferUsagesConstant} et les nombres de groupes de threads pour la charge de travail. Le décalage 0 lie le début du tampon. Si plusieurs enregistrements de données de constantes partagent un même tampon, le décalage de départ de chaque enregistrement doit respecter l’alignement de liaison du backend. Cette exigence est distincte de l’agencement des champs à l’intérieur de l’enregistrement. +concepts.shaders.binding.notes: "{resourceHandle} stocke deux champs de 32 bits, mais son interprétation appartient au backend. Ne le traitez pas comme un index de descripteur universel, une adresse ou une valeur pouvant être transférée entre contextes. Un handle ne crée pas de ressource, n’ajoute pas d’usage manquant et n’effectue aucune synchronisation." +concepts.shaders.binding.reference: Conservez des références à la ressource et à toute vue utilisée pour obtenir son handle, et libérez-les uniquement après la fin de la dernière utilisation par le shader. Lors du remplacement d’une texture ou d’une vue, mettez à jour les constantes qui contiennent son ancien handle. {link} explique cette relation de durée de vie. +concepts.shaders.binding.reference.link: Gestion des ressources +concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: Lire des éléments structurés du type de shader {t}. +concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: Lire ou écrire des éléments structurés du type de shader {t}. +concepts.shaders.binding.table.headings.access: Accès prévu +concepts.shaders.binding.table.headings.cHandle: "Handle C#" +concepts.shaders.binding.table.headings.slangFieldType: Type de champ Slang +concepts.shaders.binding.table.samplerHandle.access: Fournir l’état d’échantillonnage de texture. +concepts.shaders.binding.table.textureSampledHandle.access: Lire une texture. +concepts.shaders.binding.table.textureStorageHandle.access: Lire ou écrire une texture de stockage. +concepts.shaders.binding.title: Lier le tampon de constantes et les ressources qu’il décrit +concepts.shaders.compilation.description: "{zenithCompiler} compile un point d’entrée Slang nommé et renvoie un {shaderDesc}. Utilisez le {graphicsApi} du contexte afin que le résultat cible le backend qui créera le shader : DXIL pour DirectX 12, une bibliothèque Metal pour Metal ou SPIR-V pour Vulkan." +concepts.shaders.compilation.details: "Par exemple, avec un {context} existant et le shader du triangle copié à côté de l’exécutable :" +concepts.shaders.compilation.guidance: "{vSMain} doit correspondre exactement au nom du point d’entrée dans le fichier de shader. Gardez les objets de shader valides lors de la création du pipeline, puis libérez-les après la création du pipeline, comme indiqué dans {link}. Effectuez cette initialisation une seule fois plutôt que de recompiler à chaque image." +concepts.shaders.compilation.guidance.link: Premier triangle +concepts.shaders.compilation.title: Compiler un point d’entrée pour le contexte sélectionné +concepts.shaders.description: "Un shader reçoit des données fournies par l’application. Les attributs de sommets décrivent des sommets individuels ; les tampons contiennent des paramètres ou des tableaux ; les handles de ressources identifient d’autres ressources auxquelles le shader accédera. Les déclarations C# et les déclarations Slang doivent s’accorder sur la signification de ces valeurs. Faire correspondre un nom de champ ne suffit pas : l’agencement, l’accès aux ressources et la liaison doivent tous concorder." +concepts.shaders.dispatch.description: "{dispatch} prend le nombre de groupes de threads. Le point d’entrée {numthreads} de l’exemple de calcul exécute 16 × 16 threads par groupe. Divisez les dimensions de l’image par 16 et arrondissez au supérieur pour trouver le nombre de groupes. Par exemple, une image de 17 × 19 nécessite 2 × 2 groupes. Le shader vérifie ses coordonnées de pixel par rapport aux dimensions de l’image car les derniers groupes peuvent contenir des threads en dehors de l’image." +concepts.shaders.dispatch.details: Le compilateur stocke la taille de groupe déclarée du point d’entrée dans {shaderDescThreadGroupSize} ; il ne convertit pas les dimensions en pixels fournies à {dispatch} en nombres de groupes. Utilisez {computeShaderRendererCs} avec son shader pour l’exemple complet de liaison et de dispatch, et {link} avant qu’une autre passe ne consomme la sortie. +concepts.shaders.dispatch.details.link: Synchronisation +concepts.shaders.dispatch.title: Dispatcher des groupes de threads, pas des pixels +concepts.shaders.layout.context: "Les {link} rendent leurs décalages explicites. Cette déclaration nécessite {systemRuntimeInteropServices} et {zenithNET} dans la portée :" +concepts.shaders.layout.context.link: "constantes C# de l’exemple de calcul" +concepts.shaders.layout.description: "Pour l’entrée de sommets, l’{inputLayout} du pipeline décrit les formats, décalages, le stride et les sémantiques. La position {float3} du triangle suivie d’une couleur {float4} occupe 28 octets, la couleur étant à l’octet 12. {inputLayoutAdd} calcule cet agencement compacté ; il n’inspecte pas la structure C#. Si les champs C# contiennent du remplissage, fournissez un agencement correspondant au lieu de supposer que les champs sont compactés." +concepts.shaders.layout.details: "Les tampons de constantes contiennent des paramètres de shader, tandis que les tampons structurés contiennent des tableaux d’éléments d’un type déclaré. Tous deux sont lus conformément à leurs déclarations Slang. Ils n’utilisent pas {inputLayout}. Vérifiez les décalages de champs et les tailles d’éléments pour la représentation compilée du shader, y compris le remplissage. Un type C# non managé est adapté pour être copié en tant qu’octets, mais cela ne prouve pas à lui seul qu’il correspond à un type de shader. En particulier, n’appliquez pas l’agencement {float3} étroitement compacté d’un sommet à chaque tampon de shader." +concepts.shaders.layout.guidance: Un handle de ressource est une petite valeur qui fait référence à une ressource existante. Copier le handle dans un tampon de constantes ne copie pas le contenu de la ressource. +concepts.shaders.layout.notes: "La déclaration correspondante dans {computeShaderSlang} est :" +concepts.shaders.layout.reference: "Les dimensions occupent les huit premiers octets, suivies de deux handles de ressources de huit octets. L’exemple C# réserve 256 octets au total. Cette taille est la taille de stockage choisie par l’exemple, et non une règle selon laquelle toutes les structures Slang ou charges utiles de constantes occuperaient 256 octets. Remplir la taille totale ne corrige pas non plus un champ au mauvais décalage." +concepts.shaders.layout.title: L’entrée de sommets et les données de shaders ont des règles d’agencement différentes +concepts.shaders.matrices.description: "Le compilateur demande un stockage des matrices par lignes (row-major), où les éléments de chaque ligne sont contigus. Le {link} place trois valeurs {matrix4x4} aux décalages 0, 64 et 128. Son {detail} utilise {mulVectorMatrix} dans l’ordre modèle, vue et projection." +concepts.shaders.matrices.description.detail: shader +concepts.shaders.matrices.description.link: moteur de rendu du cube en rotation +concepts.shaders.matrices.details: L’ordre de stockage détermine la façon dont les éléments de la matrice occupent la mémoire ; l’ordre de multiplication détermine la transformation. Maintenez les deux côtés cohérents. Ajouter une transposition sans vérifier ces deux choix peut masquer une incohérence tout en en introduisant une autre. +concepts.shaders.matrices.title: Maintenir cohérents le stockage et la multiplication des matrices +concepts.shaders.title: Données de shaders et liaison +concepts.synchronization.backends.description: DirectX 12 et Vulkan encodent les transitions de texture avec des informations de layout et d’accès. Metal n’a aucune opération dans l’implémentation de {transition} de Zenith.NET. Metal regroupe le travail enregistré dans des encodeurs de rendu et de calcul. Le backend insère des barrières de visibilité lorsqu’il termine ces groupes, rendant les écritures antérieures disponibles pour le travail ultérieur. Des appels explicites à {barrier} gèrent des dépendances telles que des dispatches de calcul successifs au sein du même encodeur. +concepts.synchronization.backends.details: Cette distinction est importante lors de la modification d’une charge de travail. Dans l’{link}, le dispatch est suivi d’une passe de rendu graphique, ce qui crée également une limite d’encodeur sur Metal. Deux dispatches de calcul dépendants ne créent pas cette limite simplement en modifiant le layout déclaré de la texture. Conservez les transitions requises par l’API partagée et identifiez séparément la dépendance entre les commandes réelles de production et de consommation. +concepts.synchronization.backends.details.link: exemple de calcul +concepts.synchronization.backends.title: Une transition n’est pas identique sur chaque backend +concepts.synchronization.barriers.context: "{barrierStagesAll} est une portée plus large, pas un détecteur automatique de dépendances. Sélectionnez des étapes qui couvrent réellement le travail et utilisez-les uniquement sur une file qui prend en charge ces opérations." +concepts.synchronization.barriers.description: "Considérez deux dispatches de calcul : le premier écrit des données de simulation et le second lit ces données pour effectuer l’étape suivante. Les deux utilisent des tampons de stockage, il n’y a donc pas de layout de texture à modifier. Insérez ceci entre les dispatches sur leur tampon de commandes :" +concepts.synchronization.barriers.details: Le premier argument identifie l’étape productrice et le second l’étape consommatrice. La barrière établit la dépendance d’exécution et de mémoire correspondante sur le GPU. Le backend traduit ces étapes en ses règles d’exécution et d’accès mémoire. Cette barrière ne change pas le layout d’une texture et n’attend pas tout le travail sur le périphérique. +concepts.synchronization.barriers.guidance: "La {link} utilise ce modèle entre des dispatches dépendants. Placez la barrière là où se trouve la dépendance. Une barrière enregistrée après le consommateur ne peut pas ordonner ce consommateur après un producteur antérieur." +concepts.synchronization.barriers.guidance.link: simulation FluidTank +concepts.synchronization.barriers.title: Ordonner les commandes dépendantes avec une barrière +concepts.synchronization.dependencies.description: Pour chaque ressource partagée, identifiez l’opération qui y accède en premier, l’opération qui suit et si l’un des accès effectue une écriture. Lire les mêmes données deux fois ne nécessite aucun ordonnancement pour protéger leur contenu, bien que les changements de layout ou la présentation puissent imposer d’autres exigences. Une écriture suivie d’une lecture, une lecture suivie d’un écrasement ou deux écritures peuvent nécessiter une dépendance. +concepts.synchronization.dependencies.details: "Choisissez ensuite le mécanisme selon l’endroit où ces opérations s’exécutent :" +concepts.synchronization.dependencies.guidance: Ces mécanismes sont liés, mais ne sont pas interchangeables. La soumission de commandes dans l’ordre ne remplace pas chaque dépendance mémoire. Une attente de file ne déclare pas un nouveau layout de texture, et une barrière de commandes n’attend pas sur le thread CPU appelant. +concepts.synchronization.dependencies.table.cpuAccess.mechanism: Appeler {wait} sur la valeur d’achèvement pertinente. +concepts.synchronization.dependencies.table.cpuAccess.situation: Le CPU doit attendre avant d’accéder aux données ou de les libérer +concepts.synchronization.dependencies.table.crossQueue.mechanism: Passer sa {timelineValue} au {submit} du tampon de commandes consommateur. +concepts.synchronization.dependencies.table.crossQueue.situation: Une soumission sur une autre file produit les données +concepts.synchronization.dependencies.table.headings.mechanism: Mécanisme +concepts.synchronization.dependencies.table.headings.situation: Situation +concepts.synchronization.dependencies.table.layoutChange.mechanism: "{commandBufferTransition} avec ses layouts précédent et suivant." +concepts.synchronization.dependencies.table.layoutChange.situation: Une sous-ressource de texture modifie sa façon d’être utilisée +concepts.synchronization.dependencies.table.pipelineStages.mechanism: "{commandBufferBarrier} avec les étapes productrice et consommatrice." +concepts.synchronization.dependencies.table.pipelineStages.situation: Étapes GPU dépendantes dans un flux de commandes +concepts.synchronization.dependencies.title: Commencer par le producteur et le consommateur +concepts.synchronization.description: "Une commande qui lit des données écrites par une commande antérieure dépend de l’achèvement et de la visibilité de ces écritures. L’opération qui écrit est le producteur ; celle qui lit est le consommateur. Le CPU a aussi besoin d’un point d’achèvement avant de lire, d’écraser ou de libérer des données partagées. Zenith.NET fournit des barrières, des transitions de texture et des lignes de temps pour ces différentes dépendances." +concepts.synchronization.layouts.context: "{undefined} signifie que le contenu précédent n’a pas besoin d’être préservé. Il convient pour une nouvelle image ou un attachement qui sera entièrement effacé. Ce n’est pas un moyen d’éviter de suivre le layout d’une image dont le contenu sera chargé, échantillonné ou accumulé." +concepts.synchronization.layouts.description: "Les indicateurs d’usage décrivent les rôles pris en charge par une texture. {textureLayout} décrit comment une sous-ressource particulière sera accessible pour une opération. Une sous-ressource est un niveau mip et une couche de tableau sélectionnés. Changer son layout prépare cet accès ; cela ne convertit pas la texture en un format de pixel différent. Par exemple, l’exemple de calcul écrit une texture de sortie au layout {storage}, puis l’échantillonne dans une passe graphique. Entre ces usages, il enregistre :" +concepts.synchronization.layouts.details: Ce fragment suppose que {outputTexture} a été créée avec l’usage {sampledStorage} et que sa sous-ressource sélectionnée est au layout {storage}. {default} sélectionne le niveau mip 0 et la couche de tableau 0. L’opération ne fait pas la transition de chaque mip ou couche d’une texture. +concepts.synchronization.layouts.guidance: L’application fournit le layout précédent. {transition} ne maintient pas de suivi de layout visible par l’application et ne déduit pas cette valeur à partir de commandes antérieures. Suivez le layout partout où une ressource passe entre des étapes de rendu. +concepts.synchronization.layouts.title: Suivre le layout de chaque sous-ressource de texture +concepts.synchronization.readback.description: "{isCompleted} interroge uniquement si la ligne de temps du GPU a atteint une valeur. Il ne récupère pas lui-même les tampons de commandes et ne copie pas les téléchargements intermédiaires dans le pointeur de destination de l’application." +concepts.synchronization.readback.details: "{commandBufferDownload} enregistre d’abord une copie dans le stockage interne de lecture. Lorsque le tampon de commandes terminé est réinitialisé pour être réutilisé, le CPU copie les données vers le pointeur fourni. Gardez la destination valide et la mémoire managée épinglée jusqu’au retour de {wait} pour cette soumission de lecture. Lisez les données ou libérez la mémoire seulement ensuite. Attendre une soumission ultérieure d’une autre file n’interroge pas la file qui gère la lecture." +concepts.synchronization.readback.guidance: "Interroger {isCompleted} puis lire immédiatement la destination d’une lecture asynchrone ne suffit donc pas. Consultez {link} pour les chemins de copie directe et de transfert intermédiaire." +concepts.synchronization.readback.guidance.link: Gestion des ressources +concepts.synchronization.readback.title: L’achèvement GPU et les données CPU téléchargées sont des étapes distinctes +concepts.synchronization.reuse.description: Pour un premier moteur de rendu, une attente immédiate après chaque image est simple. Pour faire chevaucher le travail, donnez aux images en cours des données modifiables distinctes et conservez la valeur d’achèvement de l’utilisation finale de chaque image. Avant de mettre à jour un tampon de constantes, de remplacer une texture ou de libérer un pipeline, terminez chaque accès en attente à la ressource affectée. +concepts.synchronization.reuse.details: Lors d’un redimensionnement ou d’un arrêt, arrêtez les nouvelles utilisations avant d’attendre les anciennes. {swapChainResize}, la libération de ressources et la libération du contexte ne servent pas d’attentes générales pour le travail de l’application. Le triangle peut redimensionner en toute sécurité entre les rappels car chaque image précédente a déjà terminé sa soumission. +concepts.synchronization.reuse.guidance: Le {swapChainPresent} actuel signale et attend également sur la file graphique après son opération de présentation. La suppression de l’attente de soumission explicite du triangle n’établit donc pas à elle seule une boucle de présentation avec chevauchement. Une attente sur la file graphique ne dit rien non plus sur le travail indépendant qui s’exécute encore sur une autre file. +concepts.synchronization.reuse.title: Ne réutiliser les données qu’après leur accès final +concepts.synchronization.timelines.context: "Avant que le CPU ne lise, n’écrase ou ne libère ces ressources, attendez leur utilisation finale :" +concepts.synchronization.timelines.description: Une ligne de temps suit l’achèvement sur une file à l’aide de valeurs croissantes. {submit} renvoie une {timelineValue} contenant cette ligne de temps et la valeur associée à la soumission. Les valeurs d’achèvement de différentes lignes de temps ne sont pas comparables uniquement par leurs champs numériques {value}. +concepts.synchronization.timelines.details: "Supposons que {producer} et {consumer} sont des tampons de commandes déjà enregistrés provenant de deux files du même contexte. Le producteur écrit des données que le consommateur utilise. Soumettez-les comme ceci :" +concepts.synchronization.timelines.guidance: Passer la valeur produite amène la file consommatrice à l’attendre sur le GPU. Le CPU n’appelle pas {producedWait} ici. Gardez les ressources partagées valides jusqu’à ce que {consumed} soit terminé, et enregistrez tous les changements de layout de texture requis par le consommateur. +concepts.synchronization.timelines.notes: "{wait} attend cette valeur de ligne de temps, puis vérifie les soumissions terminées sur la file propriétaire. Les tampons de commandes terminés sont réinitialisés pour être réutilisés, et leurs téléchargements intermédiaires sont copiés dans les destinations CPU fournies. {queueTimelineSignal} peut également mettre en file d’attente un point d’achèvement après un travail déjà soumis à cette file. Appeler {signal} ne signifie pas que le GPU a déjà atteint ce point." +concepts.synchronization.timelines.title: Utiliser une ligne de temps pour l’achèvement et les transferts de files +concepts.synchronization.title: Synchronisation +home.actions.reference: Consulter l’API +home.actions.tutorial: Commencer par un triangle +home.entries.description: Une première image. Un exemple ciblé. Un aperçu détaillé de l’API. +home.entries.label: Explorer la documentation +home.entries.reference.action: Explorer l’API +home.entries.reference.category: Référence +home.entries.reference.description: Trouvez les types, signatures et membres sous-jacents à votre application. +home.entries.reference.title: Référence de l’API +home.entries.samples.action: Parcourir les exemples +home.entries.samples.category: Exemples +home.entries.samples.description: Explorez des techniques ciblées de rendu et de calcul à travers leur code source. +home.entries.samples.title: Exemples +home.entries.title: Commencez à créer. +home.entries.tutorial.action: Démarrer le tutoriel +home.entries.tutorial.category: Tutoriel +home.entries.tutorial.description: Créez une application de rendu complète, de la configuration à la première image affichée. +home.entries.tutorial.title: Premier triangle +home.introduction.accent: "En C#." +home.introduction.description: Créez des ressources, enregistrez des commandes et soumettez des travaux de graphisme ou de calcul via une API .NET unifiée. +home.introduction.title: Créez votre moteur de rendu. +home.meta.description: "Une API C# cohérente pour les graphismes et le calcul sur DirectX, Metal et Vulkan." +home.scene.description: Étude de géométrie en rotation. Faites glisser ou utilisez les touches fléchées pour ajuster la vue. +home.scene.label: Affichage de la géométrie +home.scene.surface: Surface +home.scene.wireframe: Fil de fer +home.title: RHI moderne pour .NET +learning.concepts.description: Comprenez comment les commandes, les ressources, les données de shaders et la synchronisation s’articulent avant de combiner des passes de rendu. +learning.concepts.execution.description: Enregistrez des travaux GPU, soumettez-les et maintenez leurs ressources en vie. +learning.concepts.platforms.description: Connectez une fenêtre native ou un contrôle de rendu d’interface utilisateur. +learning.concepts.resources.description: Choisissez les usages des ressources, l’emplacement mémoire et les vues. +learning.concepts.shaders.description: "Faites correspondre les agencements C# et les handles de ressources avec Slang." +learning.concepts.synchronization.description: Ordonnez les accès dépendants et sachez quand les travaux se terminent. +learning.concepts.title: Concepts fondamentaux +learning.description: Commencez par un tutoriel complet sur un triangle. Utilisez ensuite les exemples ciblés et les guides conceptuels pour comprendre les ressources, les données et les dépendances derrière un moteur de rendu plus vaste. +learning.entries.samples.action: Parcourir les exemples +learning.entries.samples.description: "Trouvez des exemples en C# et Slang pour la géométrie, le calcul, les requêtes de rayons et le mesh shading." +learning.entries.tutorial.action: Ouvrir le tutoriel +learning.entries.tutorial.description: Créez une application console, ouvrez une fenêtre et dessinez un triangle. +learning.meta.description: Démarrez avec Zenith.NET et explorez son modèle de programmation. +learning.title: Apprendre +reference.description: Recherchez les types de ressources, les signatures de commandes et les intégrations de plateforme. +reference.entries.commands.description: Enregistrez des commandes de graphisme, de calcul et de transfert. +reference.entries.commands.label: Enregistrer des travaux +reference.entries.context.description: Créez des ressources GPU pour le backend sélectionné. +reference.entries.context.label: Commencer ici +reference.meta.description: Explorez les types et membres de Zenith.NET. +reference.navigation.core: Parcourir l’API principale. +reference.title: Référence de l’API +samples.computeShader.description: Convertit une image en niveaux de gris avec un dispatch de calcul et affiche la texture résultante. Il illustre les handles de ressources pour une texture d’entrée échantillonnée et une texture de sortie accessible en écriture, des nombres de groupes de threads arrondis au supérieur et une vérification des limites dans le shader. Conservez la ressource {assetsTexturesShokoPng} incluse ; le moteur de rendu la traite une fois et présente le résultat lors des images suivantes. +samples.computeShader.details: "{computeShaderRendererCs} · {computeShaderSlang}" +samples.computeShader.title: Shader de calcul +samples.cube.description: Ajoute le dessin indexé, les matrices de modèle, de vue et de projection dans un tampon de constantes, ainsi que le test de profondeur. La texture de profondeur est recréée lors du redimensionnement. Utilisez-le pour passer d’une géométrie dans l’espace de découpage à un objet transformé ; le moteur de rendu utilise un attachement de profondeur/stencil {d32FloatS8UInt}. +samples.cube.details: "{spinningCubeRendererCs} · {spinningCubeSlang}" +samples.cube.title: Cube en rotation +samples.description: "Choisissez un exemple ciblé pour la fonctionnalité que vous souhaitez étudier. Chaque exemple renvoie au moteur de rendu C# et à son shader Slang. Commencez par {link} si vous souhaitez une application complète expliquée à partir d’un projet vide." +samples.description.link: Premier triangle +samples.execution.description: "{link} contient six moteurs de rendu indépendants dans une seule application de bureau. Utilisez le SDK .NET 10 et un backend de bureau pris en charge, comme décrit ci-dessous. Compilez et exécutez l’application, puis choisissez un exemple dans le menu de la console :" +samples.execution.description.link: ZenithTutorials +samples.execution.details: L’hôte sélectionne DirectX 12 sous Windows, Metal sous macOS et Vulkan sous Linux. Utilisez un environnement de périphérique, pilote et compilateur de shaders pris en charge par le backend sélectionné. Le chemin de fenêtre Linux nécessite X11 ou XWayland. Le {link} déclare les dépendances de paquets et copie les ressources de shaders et de textures nécessaires au moment de l’exécution. +samples.execution.details.link: fichier de projet +samples.execution.guidance: Les exemples partagent le code de gestion des fenêtres et de présentation. Vous pouvez choisir n’importe quel exemple indépendamment selon la fonctionnalité que vous souhaitez étudier. +samples.execution.title: Exécuter les exemples du tutoriel +samples.host.description: "{appCs} crée le contexte, la fenêtre et la chaîne d’échange. Il obtient un tampon de commandes, appelle le moteur de rendu sélectionné, soumet l’image et la présente. {iRendererCs} définit les méthodes de mise à jour, de rendu, de redimensionnement et de libération du moteur de rendu." +samples.host.details: Le calcul et le lancer de rayons produisent des textures hors écran. {texturePresenterCs} et {presentTextureSlang} dessinent ces textures dans la texture de sortie de l’image en cours de rendu de la fenêtre. L’hôte conserve la propriété de la soumission et de la présentation de la chaîne d’échange. +samples.host.title: Hôte et présentation partagés +samples.indirectDrawing.description: Dessine plusieurs copies d’un cube à l’aide d’un tampon d’arguments indirects indexés et de données par instance dans un tampon structuré. Le CPU fournit les arguments de dessin et met à jour les transformations. Utilisez-le pour comprendre l’agencement des arguments indirects et l’accès du shader aux données d’instance avant d’ajouter des arguments générés par le GPU. +samples.indirectDrawing.details: "{indirectDrawingRendererCs} · {indirectDrawingSlang}" +samples.indirectDrawing.title: Dessin indirect +samples.meshShading.description: "Utilise un task shader pour écarter du rendu des instances de sphères et transmettre les indices des instances retenues à un mesh shader qui produit la géométrie. Le moteur de rendu vérifie {contextCapabilitiesMeshShadingSupported} avant de créer son pipeline. Cet exemple permet de suivre les handles de ressources et les données de charge utile entre les étapes de tâche et de maillage." +samples.meshShading.details: "{meshShadingRendererCs} · {meshShadingSlang}" +samples.meshShading.title: Mesh Shading +samples.rayTracing.description: Construit des structures d’accélération de bas et haut niveau pour un sol et des sphères procédurales, puis trace des requêtes de rayons en ligne dans un shader de calcul. Le moteur de rendu vérifie {contextCapabilitiesRayTracingSupported} avant de construire la charge de travail. Utilisez cet exemple pour les entrées de structure d’accélération et le parcours de rayons côté shader. +samples.rayTracing.details: "{rayTracingRendererCs} · {rayTracingSlang}" +samples.rayTracing.title: Lancer de rayons +samples.title: Exemples +samples.triangle.description: Crée un tampon de sommets et un agencement d’entrée correspondant, puis dessine trois sommets via un pipeline graphique. Utilisez-le pour relier la création de ressources aux commandes d’une passe de rendu. +samples.triangle.details: "{helloTriangleRendererCs} · {helloTriangleSlang} · {link}" +samples.triangle.details.link: Tutoriel complet +samples.triangle.title: Bonjour triangle +samples.workloads.description: "Le {link} du dépôt principal contient des applications qui combinent plusieurs fonctionnalités. Leurs projets font référence au code source de la bibliothèque. Depuis une copie locale de Zenith.NET, exécutez le projet choisi, par exemple :" +samples.workloads.description.link: répertoire Experiments +samples.workloads.details: Les expérimentations fenêtrées utilisent les mêmes choix d’hôtes pour Windows, macOS et Linux/X11. Pour dessiner au sein d’Avalonia, WinForms, WPF, WinUI/Uno ou MAUI, consultez {link} pour le cycle de vie des images du contrôle et les liens d’implémentation. +samples.workloads.details.link: Intégration de plateforme +samples.workloads.table.cornellBox.example: "{link}" +samples.workloads.table.cornellBox.example.link: CornellBox +samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: "Tracé de chemins, débruitage, mappage tonal, agrandissement de l’image et contrôles ImGui. Nécessite la prise en charge du lancer de rayons et l’environnement de compilation de shaders pour le backend de bureau utilisé." +samples.workloads.table.fluidTank.example: "{link}" +samples.workloads.table.fluidTank.example.link: FluidTank +samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: Simulation fluide par calcul, dépendances entre étapes de simulation et rendu de surface multipasse. Nécessite son backend de bureau et son environnement de compilation de shaders. +samples.workloads.table.headings.example: Exemple +samples.workloads.table.headings.whatItDemonstratesAndRequires: Ce qu’il démontre et prérequis +samples.workloads.table.inkCanvas.example: "{link}" +samples.workloads.table.inkCanvas.example.link: InkCanvas +samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: Dessin Skia et gestion des entrées dans une fenêtre native. Nécessite le backend et la bibliothèque native Skia pour la plateforme cible. +samples.workloads.table.platformDetection.example: "{link}" +samples.workloads.table.platformDetection.example.link: PlatformDetection +samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: Tente la création d’un contexte pour chaque backend et signale les fonctionnalités de l’appareil. Un échec de création de contexte est signalé comme non pris en charge ; ce résultat peut également indiquer un pilote manquant ou une dépendance d’exécution non satisfaite. +samples.workloads.title: Explorer des charges de travail plus vastes +tutorial.context.description: La fenêtre peut maintenant s’ouvrir, mais nous n’avons pas encore créé les objets GPU qui y effectueront le rendu. Un {graphicsContext} donne accès au backend graphique sélectionné et à ses files de commandes. +tutorial.context.details: "Insérez ce bloc {emphasis} :" +tutorial.context.details.emphasis: après les directives using, avant {iWindowWindow} +tutorial.context.guidance: Les branches sélectionnent DirectX 12 sous Windows, Metal sous macOS et Vulkan sous Linux. Le code de rendu qui suit utilise l’API partagée de Zenith.NET. Nous demandons la validation pendant le développement et affichons les messages signalés via {validationMessage}. Les diagnostics dépendent du backend et des composants de validation disponibles sur la machine. +tutorial.context.title: Créer le contexte graphique +tutorial.description: Créez une application console .NET qui ouvre une fenêtre et dessine un triangle avec un dégradé de couleurs fluide. Vous apprendrez comment les données de sommets, les shaders et l’état du pipeline fonctionnent ensemble, puis vous enregistrerez et soumettrez les commandes qui produisent l’image. +tutorial.details: Parcourez les sections dans l’ordre. Vous ouvrirez d’abord une fenêtre vide, puis afficherez une couleur d’arrière-plan, et enfin dessinerez le triangle. Chaque point de contrôle confirme une partie de l’application avant d’ajouter la suivante. L’initialisation s’exécute une fois ; le rappel de rendu enregistre une nouvelle image à chaque appel. +tutorial.draw.context: "Les arguments de {draw} sont :" +tutorial.draw.description: "Dans le rappel {windowRender}, remplacez {addTheTriangleDrawCommandsHereLater} par ces trois commandes, entre {beginRenderPass} et {endRenderPass} :" +tutorial.draw.details: "{setPipeline} sélectionne les shaders et l’état que nous venons de créer. Définissez-le avant de lier les données de sommets : le backend utilise l’agencement d’entrée du pipeline pour interpréter la liaison." +tutorial.draw.guidance: "{setVertexBufferVertexBuffer} lie le tampon en commençant au décalage d’octet 0 au slot d’entrée 0. Ce slot correspond à l’unique entrée dans {inputLayouts}. Il ne copie ni ne transfère à nouveau les données." +tutorial.draw.notes: Les commandes ne sont encore qu’enregistrées à ce stade. Les appels {submitWait} et {present} déjà présents à la fin du rappel de rendu exécutent le travail et affichent son résultat. L’effacement reste nécessaire car le triangle ne couvre qu’une partie de l’image ; l’arrière-plan doit également recevoir une couleur définie à chaque image. +tutorial.draw.table.firstInstance.meaning: Commencer la numérotation des instances à zéro. +tutorial.draw.table.firstVertex.meaning: Commencer avec le premier sommet dans le tampon. +tutorial.draw.table.headings.argument: Argument +tutorial.draw.table.headings.description: Valeur +tutorial.draw.table.headings.meaning: Signification +tutorial.draw.table.instanceCount.meaning: Dessiner une copie du triangle. +tutorial.draw.table.vertexCount.meaning: Lire trois sommets. +tutorial.draw.title: Dessiner le triangle à l’intérieur de la passe +tutorial.execution.description: "Compilez et exécutez depuis le répertoire {firstTriangle} :" +tutorial.execution.details: La fenêtre doit afficher un triangle avec un coin supérieur rouge, un coin inférieur droit vert et un coin inférieur gauche bleu sur un fond sombre. L’intérieur doit présenter un dégradé fluide entre ces couleurs. +tutorial.execution.guidance: Redimensionnez la fenêtre. Le rappel de redimensionnement met à jour les dimensions du tampon de trame et redimensionne la chaîne d’échange. La passe de rendu établit une fenêtre d’affichage correspondant à cette image. Étant donné que les positions des sommets restent en coordonnées normalisées, le triangle conserve la même fraction de la largeur et de la hauteur de la fenêtre ; changer le rapport d’aspect peut étirer sa forme. Préserver le rapport d’aspect d’un objet nécessite une stratégie de projection ou de fenêtre d’affichage, ce qui dépasse ce premier dessin. +tutorial.execution.title: Exécuter, redimensionner et fermer +tutorial.frame.commands.context: Après {endRenderPass}, la deuxième transition prépare l’image pour la présentation. {submit} termine l’enregistrement et soumet le tampon de commandes ; {wait} attend que le GPU termine cette soumission. {present} demande ensuite l’affichage de l’image rendue. +tutorial.frame.commands.description: Une passe de rendu regroupe les opérations de dessin qui utilisent les mêmes attachements. Ici, l’attachement de couleur est la texture de sortie de la chaîne d’échange, l’image qui reçoit notre dessin. {colorAttachmentClear} crée une description indiquant à la passe d’effacer à la couleur RGBA donnée et de conserver le résultat à la fin de la passe. {beginRenderPass} enregistre ces instructions ; le GPU effectue l’effacement après la soumission des commandes. +tutorial.frame.commands.details: Les crochets contiennent notre unique attachement de couleur. L’argument {null} signifie qu’il n’y a pas d’attachement de profondeur/stencil, qui stockerait les valeurs de profondeur et les masques de stencil pour les tests de profondeur et de stencil. +tutorial.frame.commands.guidance: "{beginRenderPass} définit une fenêtre d’affichage (viewport) et un découpage (scissor) couvrant l’attachement. La fenêtre d’affichage fait correspondre les coordonnées rendues aux pixels, et le découpage limite les pixels pouvant être écrits. Ces valeurs par défaut couvrent l’ensemble de la texture de sortie, ce dont ce triangle a besoin." +tutorial.frame.commands.title: Effacer, soumettre et présenter +tutorial.frame.description: Remplissez d’abord l’image avec une seule couleur d’arrière-plan. Cette opération s’appelle un effacement (clear). Si cette couleur apparaît dans la fenêtre, la surface, la soumission de commandes et le chemin de présentation fonctionnent ensemble. Ce point de contrôle vous permet de vérifier la boucle de trame avant d’ajouter de la géométrie et des shaders. +tutorial.frame.details: "Un rappel de rendu est du code que Silk.NET appelle lorsqu’il est temps de dessiner une image. Ce rappel n’a pas besoin de l’argument de temps écoulé de l’événement, il est donc nommé {value}. Enregistrez-le {emphasis} :" +tutorial.frame.details.emphasis: avant {windowRun} +tutorial.frame.target.description: "{graphicsQueueCommandBuffer} obtient un tampon de commandes dont l’enregistrement a déjà commencé. L’enregistrement décrit le travail pour le GPU ; il n’exécute pas ce travail immédiatement." +tutorial.frame.target.details: La première {transition} prépare la texture de sortie pour l’accès en attachement de couleur. {default} sélectionne le niveau mip 0 et la couche de tableau 0. Nous utilisons {undefined} comme layout précédent car nous allons effacer toute l’image et ignorer son contenu antérieur. Une passe qui doit préserver le contenu existant doit utiliser son layout précédent réel à la place. +tutorial.frame.target.guidance: Utilisez la texture de sortie actuelle de la chaîne d’échange à chaque image. La présentation peut modifier l’image disponible, de sorte qu’une texture enregistrée lors d’une image précédente n’est pas une cible de rendu de fenêtre permanente. +tutorial.frame.target.title: Préparer la texture de sortie +tutorial.frame.title: Afficher une couleur d’arrière-plan +tutorial.geometry.data.description: "Ajoutez ce tableau {emphasis}. Placez également les étapes suivantes de création des ressources avant ce rappel, dans l’ordre indiqué." +tutorial.geometry.data.description.emphasis: avant {windowRender} +tutorial.geometry.data.details: "Chaque entrée du tableau crée un {vertex}. Les deux expressions {new} internes créent sa position {vector3} et sa couleur {vector4}. Les sommets décrivent les coins supérieur, inférieur droit et inférieur gauche. Le shader de sommets fournira une quatrième coordonnée de position, {w}. Avec w égal à 1, x et y décrivent directement des coordonnées de périphérique normalisées : -1 et +1 sont les bords de l’image, et 0 est le centre. Ces coordonnées ne dépendent pas des dimensions en pixels de la fenêtre." +tutorial.geometry.data.guidance: Chaque couleur contient des composantes rouge, verte, bleue et alpha. Alpha vaut 1 aux trois coins. Les trois positions ont z = 0, ce qui les place dans le même plan. Ces positions n’ont pas besoin de caméra ni de matrice de transformation car elles décrivent déjà les coordonnées que nous voulons rendre. Pour ce triangle plat unique, nous désactiverons également le mélange et le test de profondeur et omettrons un tampon de profondeur. +tutorial.geometry.data.title: Choisir les coins +tutorial.geometry.description: Un sommet est un point associé aux données utilisées pour le dessiner. Notre triangle a trois sommets, un pour chaque coin. Chacun contient une position et une couleur. Le GPU interpolera les couleurs, calculant des valeurs intermédiaires à travers le triangle. +tutorial.geometry.format.description: "Ajoutez cette déclaration {emphasis} :" +tutorial.geometry.format.description.emphasis: à la fin de {programCs}, après les instructions de nettoyage +tutorial.geometry.format.details: "{file} limite ce type à {programCs}, et le constructeur initialise ses champs de position et de couleur. {layoutKindSequential} conserve les champs dans l’ordre de déclaration. {position} contient trois flottants 32 bits et {color} en contient quatre. Dans cette structure, la position commence à l’octet 0, la couleur commence à l’octet 12 et le sommet complet occupe 28 octets. Nous décrirons ce même agencement au pipeline graphique." +tutorial.geometry.format.title: Définir un sommet +tutorial.geometry.title: Fournir trois sommets au GPU +tutorial.geometry.upload.context: "{fixed} empêche le ramasse-miettes de déplacer le tableau pendant que son adresse est utilisée. Pour ce tampon accessible en écriture par le CPU, {upload} mappe, copie et démappe la mémoire avant de revenir, de sorte que le tableau n’a pas besoin de rester épinglé par la suite. Le tampon doit rester en vie tout au long du rendu, et le transfert ne doit avoir lieu qu’une seule fois car les sommets ne changent pas." +tutorial.geometry.upload.description: "Le tableau managé est constitué de données CPU. Un {buffer} donne au GPU un stockage dans lequel il peut lire les sommets. Après le tableau, ajoutez :" +tutorial.geometry.upload.details: "La taille totale est {sizeofVertexVerticesLength} : 28 octets par sommet, trois sommets, 84 octets en tout. {bufferUsagesVertex} autorise l’accès en entrée de sommets. {cpuWriteOnly} permet au CPU d’initialiser directement ce petit tampon. Le stride du descripteur enregistre la taille de l’élément ; l’agencement d’entrée que nous créons ci-dessous indiquera à la récupération des sommets comment lire les attributs individuels." +tutorial.geometry.upload.guidance: Créer un tampon ne le remplit pas. {upload} copie le tableau dans cette allocation en commençant au décalage d’octet de destination 0. Sa description source fournit un pointeur et le nombre d’octets à copier. +tutorial.geometry.upload.notes: Ajoutez {vertexBufferDispose} immédiatement avant {swapChainDispose} dans le nettoyage en bas de {programCs}. Pour une géométrie statique plus grande, {link} explique quand choisir un stockage réservé au GPU et des transferts à la place. +tutorial.geometry.upload.notes.link: Gestion des ressources +tutorial.geometry.upload.title: Allouer un tampon et transférer le tableau +tutorial.input.description: "Les octets de sommets et les shaders sont prêts. Décrivez ensuite comment le GPU doit lire chaque sommet. Un attribut est une valeur unique, telle que la position ou la couleur. L’agencement d’entrée donne à chaque attribut un format et un décalage d’octets ; le stride donne la distance en octets d’un sommet au suivant. Ajoutez ce bloc d’initialisation après la création du shader :" +tutorial.input.details: "{inputLayoutAdd} ajoute un élément au stride actuel et augmente ce stride de la taille de l’élément. Il n’inspecte pas la structure C#. Ici, il produit la correspondance suivante entre la mémoire CPU et les entrées du shader :" +tutorial.input.guidance: "Modifier l’ordre des champs C# ou le remplissage sans mettre à jour cette description amènerait le GPU à lire les mauvais octets. Le {semanticIndex} par défaut est zéro, correspondant à {pOSITION0} et {cOLOR0}. Les deux éléments appartiennent au même tampon, de sorte que le pipeline contiendra un agencement d’entrée et nous lierons ce tampon au slot 0." +tutorial.input.table.headings.byteOffset: Décalage d’octets +tutorial.input.table.headings.cField: "Champ C#" +tutorial.input.table.headings.format: Format +tutorial.input.table.headings.shaderInput: Entrée de shader +tutorial.input.table.nextVertex.cField: Sommet suivant +tutorial.input.table.nextVertex.format: "Stride total : 28 octets" +tutorial.input.table.nextVertex.shaderInput: Enregistrement d’entrée suivant +tutorial.input.table.vertexColor.format: "{float4} (16 octets)" +tutorial.input.table.vertexPosition.format: "{float3} (12 octets)" +tutorial.input.title: Décrire l’agencement d’entrée des sommets +tutorial.lifecycle.description: "L’application terminée répète cette séquence :" +tutorial.lifecycle.details: "Fermer la fenêtre met fin à {run}. Chaque image rendue a déjà attendu la fin de son travail GPU, nous pouvons donc maintenant libérer les ressources qu’elle a utilisées. Le nettoyage après {windowRun} doit être :" +tutorial.lifecycle.guidance: "Libérez la chaîne d’échange avant sa fenêtre native, et le contexte après toutes ses ressources. La file possède et recycle les tampons de commandes soumis ; la chaîne d’échange possède sa texture de sortie. Ces tampons de commandes et cette texture ne nécessitent donc pas d’appel {dispose} distinct dans cette application." +tutorial.lifecycle.title: Suivre le cycle de vie d’une image +tutorial.pipeline.behavior: "Après l’agencement d’entrée, ajoutez :" +tutorial.pipeline.context: "{cullNone} remplit le triangle sans éliminer aucune orientation de face. L’ordre de ses sommets détermine l’orientation de la face, donc la désactivation du culling empêche cet ordre de masquer notre premier triangle." +tutorial.pipeline.description: Nous avons maintenant des données de sommets, un agencement d’entrée et deux shaders. Le {graphicsPipeline} les connecte et spécifie comment le GPU assemble les sommets en primitives et écrit le résultat dans un attachement. +tutorial.pipeline.details: "Un pipeline combine des étapes de shader programmables avec des paramètres de fonction fixe, qui contrôlent les opérations GPU telles que l’assemblage de triangles, l’élimination des faces (culling) et le mélange. Pour ce triangle, choisissez ces paramètres :" +tutorial.pipeline.guidance: Le format de couleur provient de {swapChainDescFormat}. Il doit correspondre à l’image utilisée par la passe de rendu. {count1} signifie un échantillon par pixel. +tutorial.pipeline.item: "{triangleList} assemble chaque groupe consécutif de trois sommets en un triangle. Nous fournirons trois sommets et dessinerons une fois, de sorte qu’aucun tampon d’indices n’est nécessaire." +tutorial.pipeline.notes: "{depthNone} désactive les tests et l’écriture de profondeur, correspondant à la passe sans attachement de profondeur." +tutorial.pipeline.reference: "{opaque} désactive le mélange, de sorte que la couleur du shader de fragments remplace l’arrière-plan à l’intérieur du triangle." +tutorial.pipeline.title: Connecter les shaders et l’agencement de sommets +tutorial.pipeline.usage: Les objets de shader peuvent être libérés après la création du pipeline, comme dans le moteur de rendu d’exemple. Gardez le pipeline lui-même en vie pour chaque image qui dessine avec lui. Ajoutez {pipelineDispose} avant {vertexBufferDispose} dans le nettoyage. La création du pipeline est la dernière étape d’initialisation avant le rappel de rendu. +tutorial.pipeline.validation: La description du pipeline déclare la configuration d’attachement ; elle ne crée pas d’autre image. {inputLayouts} a une entrée car la position et la couleur sont stockées ensemble dans un seul tampon. +tutorial.presentation.title: Connecter le GPU à la fenêtre +tutorial.project.context: Activez {emphasis} ({allowUnsafeBlocks}) dans les paramètres de compilation du projet. Nous l’utiliserons pour transmettre des données de sommets au GPU et pour les appels natifs de l’assistant de fenêtre. +tutorial.project.context.emphasis: Autoriser le code non sécurisé +tutorial.project.description: "Créez le projet et accédez à son répertoire :" +tutorial.project.details: "Installez les paquets :" +tutorial.project.guidance: "{zenithNET} fournit l’API de rendu partagée. Les trois paquets de backend permettent au même programme de sélectionner l’implémentation adaptée à sa plateforme. {zenithNETCompiler} compile les shaders Slang – les petits programmes GPU que nous écrirons plus tard – pour cette implémentation. Silk.NET fournit la fenêtre et la boucle d’événements." +tutorial.project.title: Créer un projet console +tutorial.requirements.context: Vous pouvez suivre cette page à partir d’un projet vide. L’{link} et son {detail} sont disponibles comme référence pour les API de rendu et de fenêtrage utilisées ici. +tutorial.requirements.context.detail: hôte partagé +tutorial.requirements.context.link: exemple Bonjour triangle +tutorial.requirements.description: "Vous avez besoin du {emphasis}, d’un éditeur de code ou IDE et d’un ordinateur de bureau équipé d’un GPU et d’un pilote pris en charge par un backend de Zenith.NET. Une bonne connaissance de base de C# suffit ; les concepts graphiques sont introduits au fur et à mesure de leur utilisation. Il s’agit d’un projet console {net10} ordinaire. Un backend traduit les opérations de Zenith.NET en appels à une API graphique telle que DirectX 12, Metal ou Vulkan. L’application en choisit une au démarrage :" +tutorial.requirements.description.emphasis: SDK .NET 10 +tutorial.requirements.details: Linux nécessite une session fenêtrée compatible X11 pour le chemin de gestion de fenêtre utilisé ici. Les fonctionnalités optionnelles de lancer de rayons et de mesh shading ne sont pas nécessaires pour ce triangle. +tutorial.requirements.guidance: Zenith.NET effectue le rendu dans une surface fournie par l’application. Silk.NET.Windowing créera la fenêtre de bureau et traitera ses événements. Sous macOS, la cible de présentation est une couche Metal ({cAMetalLayerCs}) ; l’assistant de fenêtre du tutoriel attache cette couche pour nous. +tutorial.requirements.table.headings.graphicsBackend: Backend graphique +tutorial.requirements.table.headings.platform: Plateforme +tutorial.requirements.table.headings.windowSurface: Surface de fenêtre +tutorial.requirements.table.linux.graphicsBackend: Vulkan 1.4 +tutorial.requirements.table.linux.platform: Linux +tutorial.requirements.table.linux.windowSurface: Fenêtre et affichage X11 ; XWayland convient également +tutorial.requirements.table.macOS.graphicsBackend: Metal 4 +tutorial.requirements.table.macOS.platform: macOS +tutorial.requirements.table.macOS.windowSurface: Couche Metal attachée à la fenêtre +tutorial.requirements.table.windows.graphicsBackend: DirectX 12 +tutorial.requirements.table.windows.platform: Windows +tutorial.requirements.table.windows.windowSurface: Handle de fenêtre Win32 +tutorial.requirements.title: Avant de commencer +tutorial.resize.context: "Exécutez à nouveau {dotnetRun}. La fenêtre devrait maintenant avoir un arrière-plan sombre uniforme qui continue de la remplir après le redimensionnement. Conservez ce rappel : le triangle sera dessiné à l’intérieur de sa passe de rendu existante." +tutorial.resize.description: "Les images de la chaîne d’échange doivent suivre les dimensions du tampon de trame. Utilisez {framebufferResize} pour répondre aux changements de taille de pixels, y compris les changements causés par la mise à l’échelle de l’affichage. Après le rappel de rendu, toujours avant {windowRun}, ajoutez :" +tutorial.resize.details: Silk.NET distingue les changements de taille de fenêtre des {link}. Nous avons besoin de ces derniers car la chaîne d’échange stocke des pixels. Une fenêtre réduite peut avoir un tampon de trame de taille zéro. Dans ce cas, les deux rappels ignorent leur travail GPU. Après un redimensionnement, la passe de rendu utilisera les nouvelles dimensions d’attachement pour sa fenêtre d’affichage et son découpage. +tutorial.resize.details.link: changements de taille du tampon de trame +tutorial.resize.guidance: Nous attendons après chaque soumission, de sorte qu’aucune image précédente n’utilise encore les images lorsque le gestionnaire de redimensionnement les remplace. L’implémentation actuelle de {present} attend également sur la file graphique. Cette boucle simple maintient le travail d’une image terminé avant que la suivante ne commence ; {link} couvre une planification plus avancée. +tutorial.resize.guidance.link: Synchronisation +tutorial.resize.title: Réagir au redimensionnement +tutorial.shaders.compilation.context: La compilation a lieu une fois lors de l’initialisation. {appContextBaseDirectory} localise le shader copié à côté de l’exécutable, indépendamment du répertoire de travail actuel. Ces shaders ne consomment que des entrées de sommets, il n’y a donc pas encore de tampons de constantes, de textures ou de handles de ressources à lier. +tutorial.shaders.compilation.description: Dans les propriétés du fichier pour {triangleSlang}, définissez {emphasis} sur {detail}. Cela rend le shader disponible à côté de l’exécutable. +tutorial.shaders.compilation.description.detail: Copier si plus récent +tutorial.shaders.compilation.description.emphasis: Copier dans le répertoire de sortie +tutorial.shaders.compilation.details: "Revenez à {programCs}. Après le transfert des sommets, ajoutez ces instructions d’initialisation avant le rappel de rendu :" +tutorial.shaders.compilation.guidance: "{zenithCompiler} renvoie une description de shader contenant le code pour l’API graphique demandée. {createShader} crée l’objet de backend correspondant. L’API graphique et les noms des points d’entrée sont tous deux importants : utilisez {contextGraphicsApi}, et écrivez {vSMain} et {fSMain} exactement comme dans le fichier Slang." +tutorial.shaders.compilation.title: Compiler pour le backend sélectionné +tutorial.shaders.context: "{fSInput} connecte la sortie du shader de sommets à l’entrée du shader de fragments. Lorsqu’il est écrit par le shader de sommets, {sVPOSITION} fournit une position dans l’espace de découpage : les quatre coordonnées que le GPU utilise pour déterminer ce qui se trouve à l’intérieur de l’image visible. {cOLOR0} transporte la couleur à interpoler entre les sommets. Les deux étapes doivent s’accorder sur son type et sa sémantique." +tutorial.shaders.description: Un shader est un programme exécuté par le GPU. Ce dessin a besoin d’un shader de sommets pour positionner les sommets et d’un shader de fragments pour produire les couleurs à l’intérieur du triangle. Nous les écrirons en Slang, un langage de shaders, et compilerons deux points d’entrée à partir du même fichier. Un point d’entrée est la fonction où l’exécution d’une étape de shader commence. +tutorial.shaders.details: "Créez {triangleSlang}, en commençant par ces deux structures :" +tutorial.shaders.fragment.description: "Ajoutez le point d’entrée de fragment au même fichier :" +tutorial.shaders.fragment.details: La rastérisation détermine les emplacements d’image que le triangle couvre. Elle produit des fragments (les données traitées par le shader de fragments) avec des couleurs de sommets interpolées sur la zone couverte. {fSMain} renvoie cette couleur interpolée via {sVTARGET}, qui identifie le premier attachement de couleur. +tutorial.shaders.fragment.guidance: L’interpolation de couleur des sommets est distincte du mélange d’attachement. Le mélange combine la sortie d’un fragment avec la couleur déjà stockée dans l’attachement. Notre état de mélange opaque désactive cette combinaison, de sorte que la couleur interpolée remplace l’arrière-plan à l’intérieur du triangle. +tutorial.shaders.fragment.title: Colorer les fragments +tutorial.shaders.guidance: "{vSInput} décrit ce que le shader de sommets reçoit depuis le tampon de sommets. Les sémantiques {pOSITION0} et {cOLOR0} identifient les entrées ; les noms de champs C# seuls n’établissent pas ce mappage." +tutorial.shaders.title: Écrire les deux étapes de shader +tutorial.shaders.vertex.description: "Ajoutez le point d’entrée de sommet à {triangleSlang} :" +tutorial.shaders.vertex.details: Le GPU appelle ce point d’entrée pour chaque sommet d’entrée. Il ajoute la coordonnée homogène {w} à la position et transmet la couleur. Après l’étape de sommet, la position est divisée par w ; ici, cette division laisse x, y et z inchangés. C’est pourquoi les positions choisies ci-dessus peuvent être comprises directement en coordonnées de périphérique normalisées. +tutorial.shaders.vertex.title: Positionner chaque sommet +tutorial.surface.description: "Le contexte doit également savoir où afficher sa sortie. Ajoutez ce qui suit {emphasis} :" +tutorial.surface.description.emphasis: après {windowCenter} et avant {windowRun} +tutorial.surface.details: "{surface} décrit une cible de présentation native et ses dimensions en pixels. Le tampon de trame (framebuffer) est l’image de pixels associée à la fenêtre. {framebufferSize} donne ses dimensions en pixels ; les dimensions logiques de la fenêtre peuvent différer lorsque la mise à l’échelle de l’affichage est activée." +tutorial.surface.guidance: La surface correspond au backend sélectionné ci-dessus. Windows fournit un handle de fenêtre, Linux fournit un affichage et une fenêtre X11, et l’assistant macOS fournit la couche Metal attachée. C’est la seule partie spécifique à la plateforme pour connecter notre fenêtre au rendu. +tutorial.surface.title: Décrire la surface native +tutorial.swapChain.context: "La chaîne d’échange utilise à la fois le contexte et la fenêtre native. Remplacez la ligne {windowDispose} en bas de {programCs} par cet ordre de nettoyage :" +tutorial.swapChain.description: "Utilisez la description de surface pour créer les images qui seront présentées. Immédiatement après le bloc de surface, ajoutez :" +tutorial.swapChain.details: La {swapChain} gère les images affichées dans la fenêtre. À chaque image, {drawable} nous donne l’image actuelle sous forme de {texture}, le type d’API pour les données d’image. Après le dessin, {present} demande l’affichage du résultat et passe au drawable suivant. +tutorial.swapChain.guidance: "{b8G8R8A8UNorm} stocke quatre canaux de couleur de 8 bits dans l’ordre bleu, vert, rouge et alpha. {uNorm} signifie que les valeurs entières de 0 à 255 représentent des valeurs de 0 à 1. Le shader renverra toujours une valeur RGBA logique ; ce format détermine la façon dont ces canaux sont stockés dans l’image. Plus tard, le pipeline graphique utilisera {swapChainDescFormat} pour correspondre à cet attachement." +tutorial.swapChain.title: Créer la chaîne d’échange +tutorial.title: Premier triangle +tutorial.troubleshooting.description: "Lisez d’abord toute erreur dans la console, puis utilisez les points de contrôle précédents pour identifier l’étape qui a échoué :" +tutorial.troubleshooting.details: Utilisez le {link} et le {detail} pour comparer les données de sommets, l’agencement d’entrée et l’opération de dessin. Cet exemple place la gestion des fenêtres et la soumission dans un hôte partagé ; ce tutoriel conserve le flux applicatif dans {programCs}. Poursuivez avec {context} pour apprendre le dessin indexé, les transformations et les tests de profondeur. +tutorial.troubleshooting.details.context: Cube en rotation +tutorial.troubleshooting.details.detail: shader Slang +tutorial.troubleshooting.details.link: moteur de rendu d’exemple +tutorial.troubleshooting.table.backend.check: Vérifiez que le backend sélectionné est pris en charge par l’appareil et le pilote graphique installé. +tutorial.troubleshooting.table.backend.symptom: La création du backend échoue +tutorial.troubleshooting.table.drawing.check: Vérifiez la taille du transfert, l’agencement d’entrée, la sélection du pipeline et le placement des commandes de dessin à l’intérieur de la passe de rendu. +tutorial.troubleshooting.table.drawing.symptom: L’arrière-plan apparaît mais pas le triangle +tutorial.troubleshooting.table.headings.check: Vérification +tutorial.troubleshooting.table.headings.symptom: Symptôme +tutorial.troubleshooting.table.input.check: Vérifiez le stride de 28 octets et les décalages de position/couleur de 0 et 12. +tutorial.troubleshooting.table.input.symptom: Les positions ou les couleurs des sommets sont corrompues +tutorial.troubleshooting.table.shaders.check: Vérifiez le fichier {triangleSlang} copié, l’orthographe du point d’entrée et le diagnostic signalé par le compilateur. +tutorial.troubleshooting.table.shaders.symptom: L’étape de couleur d’effacement fonctionne, mais le chargement des shaders échoue +tutorial.troubleshooting.table.window.check: Confirmez que le projet .NET se compile et que l’étape de fenêtre seule s’exécute dans une session de bureau. Sous Linux, vérifiez que X11 ou XWayland est disponible. +tutorial.troubleshooting.table.window.symptom: Aucune fenêtre ne s’ouvre +tutorial.troubleshooting.title: Vérifier l’étape qui a échoué +tutorial.window.context: "{usingZenithTutorials} importe l’espace de noms de l’assistant. Chaque fichier C# utilise ses propres directives using ordinaires, de sorte que l’importation d’interopérabilité est nécessaire dans les deux fichiers. L’alias {buffer} fait référence au type de tampon de Zenith.NET et le distingue de {systemBuffer}." +tutorial.window.description: Ajoutez {cocoaHelperCs} au projet, en conservant son espace de noms. Ajoutez {interopUsing} en haut de ce fichier, avant sa déclaration d’espace de noms. L’assistant attache une couche Metal à la fenêtre sous macOS ; les autres branches de plateforme ne l’appellent pas. +tutorial.window.details: "Remplacez le fichier {programCs} généré par le code suivant. Il utilise des instructions de niveau supérieur, qui s’exécutent dans l’ordre sans méthode {main} explicite. Les sections suivantes vous indiqueront où ajouter du code à ce même fichier :" +tutorial.window.guidance: "{graphicsAPINone} demande à Silk.NET de créer une fenêtre sans son propre contexte graphique. Nous allons créer ce contexte avec Zenith.NET. {initialize} crée la fenêtre native et rend ses handles disponibles. Un handle est un identifiant fourni par le système de fenêtrage. {center} centre la fenêtre et {run} traite les événements jusqu’à sa fermeture. L’exécution se poursuit ensuite vers {dispose}, qui libère la fenêtre." +tutorial.window.notes: Exécutez {dotnetRun}. Une fenêtre vide doit s’ouvrir et répondre au déplacement, au redimensionnement et à la fermeture. Son contenu n’est pas encore défini car nous n’avons soumis aucune commande de rendu. Fermez-la avant de continuer. +tutorial.window.title: Ouvrir une fenêtre +ui.action.copy: Copier +ui.action.navigate: Naviguer +ui.action.open: Ouvrir +ui.action.source: Afficher la source +ui.api.browse: Parcourir les espaces de noms et les types. +ui.api.clearTypeSearch: Effacer la recherche de types +ui.api.findType: Trouver un type +ui.api.loadError: Impossible de charger les types. Rechargez cette page pour réessayer. +ui.api.loadingNamespaces: Chargement des espaces de noms… +ui.api.loadingTypes: Chargement des types… +ui.api.matchingTypes: Types correspondants +ui.api.namespace: Espace de noms +ui.api.namespaces: Espaces de noms +ui.api.noNamespaceTypes: Aucun type dans cet espace de noms. +ui.api.noTypes: Aucun type correspondant. +ui.api.types: Types +ui.content.reference: Référence +ui.content.source: Code source +ui.content.tutorial: Tutoriel +ui.contents.close: Fermer la table des matières +ui.contents.open: Ouvrir la table des matières +ui.contents.title: Table des matières +ui.footer.caption: RHI moderne pour .NET. +ui.footer.label: Pied de page +ui.language.label: Langue +ui.language.unavailable: Non traduit +ui.members.clear: Effacer la recherche de membres +ui.members.close: Fermer le chercheur de membres +ui.members.empty: Aucun membre correspondant. +ui.members.open: Aller au membre +ui.members.placeholder: Nom ou signature… +ui.members.search: Rechercher des membres +ui.members.title: Trouver un membre +ui.members.undeclared: Ce type ne possède aucun membre déclaré. +ui.navigation.api: API +ui.navigation.concepts: Concepts +ui.navigation.home: Accueil +ui.navigation.label: Navigation principale +ui.navigation.toggle: Basculer la navigation +ui.outline.title: Sur cette page +ui.reference.assembly: Assembly +ui.reference.classes: Classes +ui.reference.constructors: Constructeurs +ui.reference.declaration: "Déclaration de type C#" +ui.reference.delegates: Délégués +ui.reference.derived: Types dérivés +ui.reference.enums: Énumérations +ui.reference.events: Événements +ui.reference.examples: Exemples +ui.reference.exceptions: Exceptions +ui.reference.extensionMethods: Méthodes d’extension +ui.reference.fields: Champs +ui.reference.implementations: Implémentations explicites d’interface +ui.reference.implements: Implémente +ui.reference.inheritance: Héritage +ui.reference.inheritedMembers: Membres hérités +ui.reference.interfaces: Interfaces +ui.reference.metadata: Métadonnées du type +ui.reference.methods: Méthodes +ui.reference.namespace: Espace de noms +ui.reference.open: Ouvrir la référence pour {name} +ui.reference.operators: Opérateurs +ui.reference.parameters: Paramètres +ui.reference.properties: Propriétés +ui.reference.related: Voir aussi +ui.reference.relationships: Héritage et métadonnées +ui.reference.remarks: Remarques +ui.reference.returns: Retourne +ui.reference.structs: Structures +ui.reference.typeParameters: Paramètres de type +ui.reference.value: Valeur +ui.reference.values: Valeurs +ui.search.close: Fermer la recherche +ui.search.empty: Aucun résultat pour « {query} ». +ui.search.hint: Recherchez dans les tutoriels, concepts, exemples et la référence de l’API. +ui.search.loading: Chargement de la recherche… +ui.search.more: Afficher plus de résultats +ui.search.pending: Recherche en cours… +ui.search.placeholder: Que recherchez-vous ? +ui.search.resultCount: "Résultats : {count}" +ui.search.title: Rechercher dans la documentation +ui.search.unavailable: La recherche est indisponible. Vous pouvez toujours ouvrir les pages ci-dessous. diff --git a/documents/locales/ja-JP/strings.yml b/documents/locales/ja-JP/strings.yml new file mode 100644 index 00000000..09dc6e2d --- /dev/null +++ b/documents/locales/ja-JP/strings.yml @@ -0,0 +1,604 @@ +### YamlMime:Resources +concepts.execution.context.description: "{graphicsContext} は 1 つのバックエンドデバイスを表し、そのグラフィックス、コンピュート、転送の各キューを提供します。ワークロード用のバッファー、テクスチャ、シェーダー、パイプラインは同じコンテキストを通じて作成してください。別のコンテキストによって作成されたリソースやハンドルを、このコンテキストのコマンドバッファーにそのままバインドすることはできません。" +concepts.execution.context.details: プラットフォームとプレゼンテーションサーフェスに適したバックエンドを選択してください。API は共有されますが、デバイスのサポート状況は依然として重要です。{capabilities} はデバイス名と、{rayTracingSupported} および {meshShadingSupported} フラグを公開します。{link} や {detail} サンプルのように、オプションのワークロードを作成する前に対応するフラグを確認してください。これらのフラグは、フォーマット、メモリ、またはプラットフォームの制限に関する完全なリストではありません。 +concepts.execution.context.details.detail: メッシュシェーディング +concepts.execution.context.details.link: レイトレーシング +concepts.execution.context.title: コンテキストがリソースとキューを接続する +concepts.execution.description: Zenith.NET アプリケーションは GPU リソースを作成し、それらを使用するコマンドを記録して、それらのコマンドをキューにサブミットします。GPU がサブミットを実行している間も CPU は処理を続行できます。記録呼び出しが戻った後でも、その処理が終了するまでリソースを有効に保ってください。 +concepts.execution.ownership.description: "ここでの所有権とは、破棄に対する責任を意味します。C# の参照はマネージドオブジェクトへの到達可能性を維持しますが、明示的な {dispose} がネイティブリソースを破棄することを防ぐわけではありません。同様に、バッファーを使用するコマンドをサブミットしても、そのバッファーの所有権がキューに移るわけではありません。" +concepts.execution.ownership.details: シャットダウン時には、新しい作業のサブミットを停止し、関係するすべてのキューでの最後の使用を待機し、アプリケーションのリソースを解放してから、コンテキストを破棄してください。コンテキストの破棄はその独自のキューや内部ヘルパーを解放しますが、アプリケーションのすべての作業を待機したり、アプリケーションが作成したすべてのリソースを解放したりするわけではありません。 +concepts.execution.ownership.guidance: レンダリング中も同じライフサイクルのルールを適用してください。リソースの最後の使用に対する完了値を保持し、そのバイトがいつ上書き可能になるか、またはリソースがいつ交換可能になるかを把握できるようにします。ビューと基盤となるリソースの有効期間については、{link} を参照してください。 +concepts.execution.ownership.guidance.link: リソース管理 +concepts.execution.ownership.table.applicationResources.object: アプリケーションが作成したリソース +concepts.execution.ownership.table.applicationResources.ownership: アプリケーションが最後の GPU 使用後に解放します。 +concepts.execution.ownership.table.commandBuffers.object: 借用したコマンドバッファー +concepts.execution.ownership.table.commandBuffers.ownership: キューが管理およびリサイクルします。 +concepts.execution.ownership.table.headings.object: オブジェクト +concepts.execution.ownership.table.headings.ownership: 誰が解放するか? +concepts.execution.ownership.table.queues.object: コンテキストキューとそのタイムライン +concepts.execution.ownership.table.queues.ownership: コンテキストとキューが管理します。 +concepts.execution.ownership.table.swapChainDrawable.ownership: スワップチェーンが管理します。 +concepts.execution.ownership.title: 所有権と GPU 完了を明確に区別する +concepts.execution.pipelines.description: グラフィックスパイプラインは、シェーダー、頂点入力レイアウト、頂点をプリミティブに組み立てるルール、アタッチメントフォーマット、レンダー状態を結合します。頂点、インデックス、定数データをバインドし、描画コマンドを発行する前に設定してください。そのアタッチメントフォーマットとサンプル数は、レンダーパスのアタッチメントと一致している必要があります。 +concepts.execution.pipelines.details: コンピュートパイプラインは、GPU スレッドのグループを起動するディスパッチ用のシェーダーエントリポイントを提供します。ディスパッチの前に、パイプラインとその定数を設定してください。コンピュートディスパッチはグラフィックスレンダーパスの外側に配置します。パイプラインの変更は、後続のコマンドがその入力を解釈する方法の変更を意味します。選択したパイプラインに必要なデータは、使用する前にバインドしてください。 +concepts.execution.pipelines.guidance: "{link} は完全なグラフィックスシーケンスを示しています。{detail} はディスパッチを記録し、その後に結果を表示するグラフィックスパスを記録します。" +concepts.execution.pipelines.guidance.detail: コンピュートサンプル +concepts.execution.pipelines.guidance.link: 三角形の描画コールバック +concepts.execution.pipelines.title: パイプラインがコマンドによるデータの解釈方法を決定する +concepts.execution.queues.description: 1 つのフレームで描画、コンピュート、コピーを組み合わせる場合は、{graphicsQueue} から始めてください。依存する作業を 1 つのキューにまとめることで、その順序付けを追跡しやすくなります。 +concepts.execution.queues.details: "キューは、まとめられたコマンドを受け付けて実行します。別々のキューが別々のハードウェアエンジンに対応するとは限らないため、同時に実行されるとは限りません。処理を重ねて進める利点がある場合に別のキューを使い、一方のキューが他方の結果を使う場合は明示的な依存関係を設定してください。" +concepts.execution.queues.guidance: 後続のコマンドが先行の書き込みに依存する場合、アプリケーションはそれらの書き込みが後続のコマンドから利用可能であることも保証しなければなりません。両方のコマンドバッファーを同じキューにサブミットするだけでは、そのような依存関係が自動的にすべて確立されるわけではありません。コマンドは異なる GPU ステージを使用する可能性があり、後続のアクセスにはバリアやテクスチャ遷移が必要になる場合があります。{link} で、サブミットの順序とリソースの可視性の違いについて説明しています。 +concepts.execution.queues.guidance.link: 同期 +concepts.execution.queues.table.computeQueue.workToRecord: グラフィックスレンダーパスを含まない、コンピュートディスパッチおよび互換性のある転送作業。 +concepts.execution.queues.table.graphicsQueue.workToRecord: レンダーパスと描画、およびフレームで使用されるコンピュート操作と転送操作。 +concepts.execution.queues.table.headings.queue: キュー +concepts.execution.queues.table.headings.workToRecord: 記録する作業 +concepts.execution.queues.table.transferQueue.workToRecord: 描画やコンピュートディスパッチを含まない、アップロード、ダウンロード、コピーの作業。 +concepts.execution.queues.title: 実行する作業に応じたキューを選択する +concepts.execution.recording.context: キューは完了をポーリングし、終了したコマンドバッファーをリサイクルします。新しい記録ごとに {queueCommandBuffer} を呼び出してください。リサイクルされたインスタンスが返される場合があります。借用したコマンドバッファーを独自に破棄したり、2 回サブミットしたり、サブミット後も記録を続けたりしないでください。特定のコマンドバッファーへの記録は一度に 1 つのスレッドから行ってください。キューの内部ロックは、コマンドバッファーへの同時編集を保護しません。 +concepts.execution.recording.description: "{queueCommandBuffer} は、すでに記録が開始された {commandBuffer} を返します。コマンドとその依存関係を記録し、一度 {submit} を呼び出します。サブミットにより記録が終了し、そのキュー上の完了ポイントを識別する {timelineValue} が返されます。" +concepts.execution.recording.details: "たとえば、{commandBuffer} にフレームを記録した後、三角形のチュートリアルでは次のようにサブミットして完了を待機します:" +concepts.execution.recording.guidance: "{submit} は作業をスケジュールし、{wait} はそのサブミットが完了するまで CPU の続行を待機させます。描画の記録、レンダーパスの終了、コマンドバッファーのサブミットはそれぞれ別の操作です。描画の記録もパスの終了も、GPU を待機することはありません。" +concepts.execution.recording.title: 記録してもコマンドは実行されない +concepts.execution.title: 実行モデル +concepts.platforms.description: アプリケーションがネイティブウィンドウとフレームループを自ら所有するか、UI レンダリングコントロールを使用するかを選択します。その選択によって、誰が出力テクスチャを取得し、コマンドをサブミットし、結果を提示するかが決まります。出力テクスチャとは、現在のフレームの出力として使用されるテクスチャのことです。オフスクリーンのグラフィックスやコンピュート処理には、ウィンドウやスワップチェーンは不要です。 +concepts.platforms.frame.context: そのパスの内部にパイプラインバインディングと描画コマンドを追加してください。戻る前にパスを終了します。提供されたコマンドバッファーを独自にサブミットしたり個別に提示したりしないでください。また、コマンドバッファーや出力テクスチャを破棄しないでください。ハンドラーが出力テクスチャを別のレイアウトで使用する場合は、コントロールの最終遷移のために {colorAttachment} に戻してください。 +concepts.platforms.frame.description: 各統合機能は {iZenithView} を実装しています。アプリケーションはその {graphicsContext} を提供し、{updateRequested} でシーンデータを更新し、{renderEventArgs} を使用して {renderRequested} でレンダリングを記録します。 +concepts.platforms.frame.details: "コントロールが各フレームの一連の処理を管理します。出力テクスチャとコマンドバッファーを取得し、出力テクスチャを {colorAttachment} に遷移させ、ハンドラーを呼び出した後、そのフレームワークで必要なサブミットとプレゼンテーションを行います。" +concepts.platforms.frame.guidance: "コンテキストが割り当てられた {view} という名前の初期化済み {iZenithView} の場合、このハンドラーは完全なクリアパスを記録します。これには {usingZenithNET} が必要です:" +concepts.platforms.frame.notes: 各コントロールは各フレームの開始時に {undefined} から遷移するため、アプリケーションは出力テクスチャの以前の内容が保持されることに依存できません。フレームごとに必要な画像をクリアまたはレンダリングしてください。持続的な累積やキャッシュされたレンダリングはアプリケーションが所有するテクスチャに保持し、そのテクスチャをビュー経由で表示してください。 +concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat} は統合のデフォルトのカラーフォーマットを提供します。アタッチメントフォーマット、サンプル数、寸法を一致させる際は、実際のイベントの出力テクスチャを確認してください。" +concepts.platforms.frame.title: UI コントロールから提供されたフレームに記録する +concepts.platforms.integration.context: WinForms、WPF、および Windows の WinUI パスには Windows が必要です。MAUI アプリケーションにはターゲットプラットフォームのワークロードが必要であり、{useZenithView} を使用してコントロールハンドラーを登録する必要があります。{extensionsCs} を参照してください。フレームワークのサポートとバックエンドのサポートの両方が満たされている必要があります。 +concepts.platforms.integration.description: "各コントロールはイベントインターフェイスを共有していますが、すべてが同じ方法で提示されるわけではありません:" +concepts.platforms.integration.details: ビットマップリードバックは、UI が表示する前にレンダリングされたピクセルを CPU メモリにコピーします。共有テクスチャの相互運用はそのリードバックを回避しますが、GPU コピーと同期が依然として必要になる場合があります。したがって、共有の {renderRequested} インターフェイスが同じプレゼンテーションコストやネイティブ相互運用要件を意味するわけではありません。 +concepts.platforms.integration.guidance: "アプリケーションのフレームワーク用のパッケージを使用してください。例:" +concepts.platforms.integration.table.avalonia.integration: Avalonia +concepts.platforms.integration.table.avalonia.presentation: テクスチャにレンダリングし、ピクセルを {writeableBitmap} にダウンロードします。{zenithViewCs} および {surfaceCs} を参照してください。 +concepts.platforms.integration.table.headings.integration: 統合 +concepts.platforms.integration.table.headings.presentation: 画像が UI に届く仕組み +concepts.platforms.integration.table.maui.integration: .NET MAUI +concepts.platforms.integration.table.maui.presentation: Android、iOS、Mac Catalyst ではネイティブサーフェスを使用し、Windows では共有テクスチャコンポジションを使用します。{link} を参照してください。 +concepts.platforms.integration.table.maui.presentation.link: プラットフォーム実装 +concepts.platforms.integration.table.uno.integration: Uno パス +concepts.platforms.integration.table.uno.presentation: ピクセルを {writeableBitmap} にダウンロードします。{zenithViewUnoCs} を参照してください。 +concepts.platforms.integration.table.winForms.integration: WinForms +concepts.platforms.integration.table.winForms.presentation: コントロールの {hWND} 用に Zenith.NET スワップチェーンを作成します。{zenithViewCs} を参照してください。 +concepts.platforms.integration.table.winUI.integration: Windows 上の WinUI +concepts.platforms.integration.table.winUI.presentation: インポートされた共有 Direct3D 11 テクスチャにレンダリングし、{swapChainPanel} に接続されたコンポジションスワップチェーンにコピーします。{zenithViewWinUICs} を参照してください。 +concepts.platforms.integration.table.wpf.integration: WPF +concepts.platforms.integration.table.wpf.presentation: 共有 Direct3D 11 テクスチャをインポートし、Direct3D 相互運用を介して {d3DImage} によって表示されるサーフェスにコピーします。{surfaceCs} を参照してください。 +concepts.platforms.integration.title: フレームワークだけでなくプレゼンテーションパスも選択する +concepts.platforms.lifecycle.context: UI ビューの場合、一致するレンダリングリソースを作成する際に、イベントの出力テクスチャの {descWidth}、{descHeight}、{descFormat}、{descSampleCount} を使用してください。コントロールがその出力テクスチャの解像度を決定します。論理寸法やディスプレイスケールが常にテクスチャ寸法と等しいとは仮定しないでください。 +concepts.platforms.lifecycle.description: ネイティブスワップチェーンの場合、ピクセル単位のフレームバッファーサイズを渡してください。ディスプレイのスケーリングが有効な場合、論理単位で表されたウィンドウサイズとは異なることがあります。サイズがゼロのフレームバッファーはスキップし、ピクセルサイズが変化したときにスワップチェーンをリサイズし、フレームごとに {swapChainDrawable} を取得してください。出力テクスチャはスワップチェーンが所有しており、プレゼンテーションやリサイズ後に変更される可能性があります。 +concepts.platforms.lifecycle.details: "{swapChainResize} は既存のサーフェスの寸法を変更します。{swapChainRefresh} はネイティブハンドルを含むサーフェス記述を置き換えます。どちらの操作の前にも、影響を受けるリソースの未完了の使用を完了させてください。ネイティブプレゼンテーションターゲットを破棄する前に、スワップチェーンを解放してください。" +concepts.platforms.lifecycle.guidance: ウィンドウに従ってサイズが変わるアプリケーション所有の深度テクスチャやオフスクリーンテクスチャを再作成し、そのハンドルを含む定数を更新してください。アタッチメントフォーマットとサンプル数に互換性が維持されている場合、サイズ変更をまたいでパイプラインを使い続けることができます。{link} は深度テクスチャを置き換えながらパイプラインを維持します。 +concepts.platforms.lifecycle.guidance.link: 回転する立方体のレンダラー +concepts.platforms.lifecycle.title: 出力テクスチャのサイズとライフサイクルをホストに委ねる +concepts.platforms.ownership.description: アプリケーションは、割り当てたコンテキストおよびレンダリングのために作成したリソースを所有します。コントロールは独自のプレゼンテーションリソースを所有します。ビューの {graphicsContext} プロパティを変更すると、スケジューラはコントロールのリソースを再作成しますが、新しいコンテキスト用にアプリケーションのパイプライン、バッファー、テクスチャを再作成するわけではありません。 +concepts.platforms.ownership.details: リソースの置き換えはビューのフレームライフサイクルと協調させてください。アプリケーションのリソースや割り当てられたコンテキストを破棄する前に、ビューのフレームアクティビティを停止し、未完了の GPU 使用を終了させてください。ビューを削除しても、コンテキストの所有権がコントロールに移るわけではありません。 +concepts.platforms.ownership.guidance: 共有の {frameSchedulerCs} は、ビューの UI ディスパッチャーを介してフレーム処理をディスパッチします。フレームハンドラーはフレームの更新と記録に集中させてください。そこでの長時間の CPU 処理は UI の遅延にもつながります。 +concepts.platforms.ownership.title: アプリケーションリソースをコントロールの所有権外に保つ +concepts.platforms.surface.context: ウィンドウライブラリや UI フレームワークが特定のオペレーティングシステムをサポートしていても、そこで選択した GPU バックエンドが利用可能であるとは限りません。デバイス機能、ドライバー、およびネイティブサーフェスのサポートが一致している必要があります。オプションのレイトレーシングやメッシュシェーディングのワークロードを作成する前に、{contextCapabilities} で確認してください。 +concepts.platforms.surface.description: "{link} は Silk.NET を使用してウィンドウを作成し、イベントを処理します。Zenith.NET は、{surface} の記述と {swapChain} を介してそのウィンドウに接続します。サーフェスにはネイティブハンドルとサイズが含まれます。その記述を構築しても、オペレーティングシステムのウィンドウが作成または所有されるわけではありません。" +concepts.platforms.surface.description.link: 三角形チュートリアル +concepts.platforms.surface.details: "ハンドルは選択したバックエンドと一致している必要があります:" +concepts.platforms.surface.guidance: チュートリアルの {appCs} は Windows、macOS、X11 の選択肢を示しています。その Linux ホストは Xlib ハンドルを提供するため、Wayland セッションで使用するには XWayland が必要です。ネイティブ Wayland アプリケーションの場合は、{surfaceWayland} を通じて異なるハンドルを提供することになります。 +concepts.platforms.surface.table.android.backend: Android 上の Vulkan。 +concepts.platforms.surface.table.apple.backend: Apple プラットフォーム上の Metal。 +concepts.platforms.surface.table.headings.backend: バックエンドパス +concepts.platforms.surface.table.headings.factory: サーフェスファクトリ +concepts.platforms.surface.table.headings.handles: ホストから提供されるハンドル +concepts.platforms.surface.table.wayland.backend: ネイティブ Wayland ホストを使用した Vulkan。 +concepts.platforms.surface.table.wayland.handles: Wayland ディスプレイおよびサーフェス +concepts.platforms.surface.table.win32.backend: Windows 上の DirectX 12 または Vulkan。 +concepts.platforms.surface.table.xlib.backend: X11 または XWayland を使用した Linux 上の Vulkan。 +concepts.platforms.surface.table.xlib.handles: X11 ディスプレイおよびウィンドウ +concepts.platforms.surface.title: アプリケーションがプレゼンテーションを所有する場合はネイティブサーフェスを提供する +concepts.platforms.title: プラットフォーム統合 +concepts.resources.allocation.context: "独自のアロケーターが必要でなければ、まずコンテキストで作成するリソースを使ってください。ヒープを使う場合は、それらを使用するすべての GPU 処理が完了してから、配置したリソースを先に解放し、最後にヒープ自体を解放します。" +concepts.resources.allocation.description: "{heap} は、明示したバイトオフセットにリソースを配置するためのメモリを提供します。アプリケーションがオフセットを選び、使用中の領域を追跡します。" +concepts.resources.allocation.details: "配置前に、正確なバッファーまたはテクスチャの記述を指定して {contextGetSizeAndAlignment} を呼び出します。返されたアライメントの倍数をオフセットに選び、返されたサイズを確保して、リソースがヒープの総バイト数の範囲内に収まるようにしてください。使用中の割り当て領域は重ねないでください。テクスチャの格納にはバックエンド固有のパディングやアライメントが含まれることがあるため、ピクセル数と 1 ピクセル当たりのバイト数の積では割り当てサイズを求められません。" +concepts.resources.allocation.guidance: "配置したバッファーの常駐特性は、ヒープの常駐特性と一致させてください。ここで扱う通常の GPU テクスチャには GPU 専用ヒープを使います。サイズとアライメントは配置の要件であり、すべてのバックエンドで任意のリソースを任意のヒープに配置できるという保証ではありません。" +concepts.resources.allocation.title: 割り当て制御が必要な場合はヒープにリソースを配置する +concepts.resources.bufferUsages.table.constant.role: 定数バッファーバインディングを介して読み取られるシェーダーパラメーター。 +concepts.resources.bufferUsages.table.headings.role: "役割" +concepts.resources.bufferUsages.table.headings.usage: 用途 +concepts.resources.bufferUsages.table.index.role: インデックス描画で使用されるインデックス。 +concepts.resources.bufferUsages.table.indirect.role: "間接描画または間接ディスパッチのコマンドが読み取る引数。" +concepts.resources.bufferUsages.table.none.role: "バッファーの用途フラグは宣言されていません。" +concepts.resources.bufferUsages.table.storageReadOnly.role: "読み取り専用のシェーダーバインディングを介してアクセスするバッファーデータ。" +concepts.resources.bufferUsages.table.storageReadWrite.role: "読み書き可能なシェーダーバインディングを介してアクセスするバッファーデータ。" +concepts.resources.bufferUsages.table.transferDst.role: "GPU コピーの転送先ストレージ。" +concepts.resources.bufferUsages.table.transferSrc.role: "GPU コピーの転送元データ。" +concepts.resources.bufferUsages.table.vertex.role: 描画のためにフェッチされる頂点属性。 +concepts.resources.bufferUsages.title: バッファーの用途 +concepts.resources.description: "リソースを使用する処理に合わせて、その記述を選びます。描画先となり、シェーダーでサンプリングされ、さらに CPU に読み戻されるテクスチャには、3 つすべての用途の宣言と、それらの処理間の同期が必要です。メモリの配置とリソースの有効期間も別途検討します。" +concepts.resources.memory.context: CPU アクセス可能なバッファーの場合、{map} は CPU にアドレスを与えます。GPU が同じバイトへのアクセスを停止するのを待つことはありません。同様に {unmap} も作業をサブミットしたり完了を待ったりしません。CPU 書き込み可能なデータを上書きする前に、以前の内容を必要とする GPU 読み取りを終了させてください。 +concepts.resources.memory.description: "{bufferDesc} には {residency} フィールドがあります。CPU と GPU がデータにどのようにアクセスするかに応じて選択してください:" +concepts.resources.memory.details: 常駐特性は、割り当てに対する想定された CPU アクセスを記述します。これは、すべてのデバイスが物理的に分離された CPU および GPU メモリを持つことを意味するわけではありません。三角形チュートリアルでは、小さな頂点バッファーを直接初期化するために {cpuWriteOnly} を使用します。大規模な静的メッシュは、代わりに 1 回限りのアップロードを伴う GPU 専用ストレージの恩恵を受けることができます。 +concepts.resources.memory.guidance: "{textureDesc} には常駐特性フィールドがありません。通常のコンテキスト作成テクスチャは GPU ストレージを使用します。その公開 API は CPU データ転送のためのアップロードおよびダウンロード操作を提供し、直接マッピングメソッドは公開しません。明示的なヒープは、以下で説明するように配置の制御を提供します。" +concepts.resources.memory.table.cpuReadOnly.cPUAccess: "GPU コピーの完了後にマップされたメモリを読み取る。" +concepts.resources.memory.table.cpuReadOnly.typicalRole: "GPU が生成したリードバックデータ" +concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "先行する GPU 読み取りの完了後にマップされたメモリへ書き込む。" +concepts.resources.memory.table.cpuWriteOnly.typicalRole: "CPU が供給または更新するデータ" +concepts.resources.memory.table.gpuOnly.cPUAccess: "アップロードバッファーまたはリードバックバッファーを介してバイトを転送する。" +concepts.resources.memory.table.gpuOnly.typicalRole: "静的ジオメトリと GPU の作業用データ" +concepts.resources.memory.table.headings.cPUAccess: CPU アクセス +concepts.resources.memory.table.headings.residency: 常駐特性 +concepts.resources.memory.table.headings.typicalRole: 典型的な役割 +concepts.resources.memory.title: "必要な CPU アクセスに合わせてメモリを選ぶ" +concepts.resources.textureUsages.description: "転送用の用途フラグは GPU コピーの方向を表します。CPU アクセスは、それとは別のメモリ配置の選択であり、後で説明します。" +concepts.resources.textureUsages.details: "用途フラグの組み合わせは複数の役割を宣言するだけで、処理の実行やアクセス順序の制御は行いません。テクスチャには適切な{link}が引き続き必要であり、選択したデバイス上でそのフォーマットが要求する用途をサポートしている必要があります。" +concepts.resources.textureUsages.details.link: "レイアウトと同期" +concepts.resources.textureUsages.table.colorAttachment.role: "レンダーパスのカラーアタッチメント。" +concepts.resources.textureUsages.table.depthStencilAttachment.role: "レンダーパスの深度/ステンシルアタッチメント。" +concepts.resources.textureUsages.table.headings.role: "役割" +concepts.resources.textureUsages.table.headings.usage: 用途 +concepts.resources.textureUsages.table.none.role: "テクスチャの用途フラグは宣言されていません。" +concepts.resources.textureUsages.table.sampled.role: "サンプリング用テクスチャのバインディングを介して読み取るテクスチャデータ。" +concepts.resources.textureUsages.table.storage.role: "ストレージテクスチャのバインディングを介してシェーダーが読み書きするテクスチャデータ。" +concepts.resources.textureUsages.table.transferDst.role: "GPU コピーの転送先画像ストレージ。" +concepts.resources.textureUsages.table.transferSrc.role: "GPU コピーの転送元画像データ。" +concepts.resources.textureUsages.title: テクスチャの用途 +concepts.resources.title: リソース管理 +concepts.resources.transfers.context: ダウンロードは、内部のリードバックストレージへの GPU コピーを記録します。ライブラリは、完了したコマンドバッファーを再利用のためにリセットするときに、それらのバイトを指定された CPU 転送先にコピーします。サブミット値の {wait} が戻るまで、転送先の割り当てを維持し、マネージドメモリを固定したままにしてください。 +concepts.resources.transfers.description: "アップロードは CPU データを GPU リソースへコピーし、ダウンロードはリソースのデータを CPU メモリへコピーします。リソース自体のメソッドは、その転送が完了してから戻ります。" +concepts.resources.transfers.details: "これらの待機が対象とするのは、各メソッドがサブミットした転送です。別のキューですでにリソースを読み書きしていた処理との依存関係は検出しません。リソースのメソッドを呼ぶ前に、その依存関係を設定してください。マップされたメモリ経由の直接コピーでも、関連する GPU 処理の完了を確認するのは呼び出し側の責任です。" +concepts.resources.transfers.guidance: "コピーを他の作業と一緒に記録する必要がある場合は、{commandBufferUpload} または {commandBufferDownload} を使用してください。ポインターの有効期間はそれぞれ異なります:" +concepts.resources.transfers.item: "アップロードは呼び出し中に CPU 側の転送元を内部のアップロードバッファー、別名ステージングメモリへコピーします。転送元ポインターは、その呼び出しの間だけ有効であれば十分です。" +concepts.resources.transfers.notes: "テクスチャの行ストライドは CPU データの隣接する行の間のバイト距離であり、スライスストライドは隣接する深度スライスの間のバイト距離です。これらはテクスチャ内部の GPU メモリレイアウトを表しません。GPU 処理の完了とリードバックの違いは{link}を参照してください。" +concepts.resources.transfers.notes.link: 同期 +concepts.resources.transfers.table.bufferDownload.transfer: "{cpuReadOnly} の直接 CPU コピー。それ以外の場合は転送キューのダウンロードをサブミットして待機します。" +concepts.resources.transfers.table.bufferUpload.transfer: "{cpuWriteOnly} の直接 CPU コピー。それ以外の場合は転送キューのアップロードをサブミットして待機します。" +concepts.resources.transfers.table.headings.method: 方法 +concepts.resources.transfers.table.headings.transfer: "データの転送方法" +concepts.resources.transfers.table.textureTransfers.method: "{textureUpload} / {textureDownload}" +concepts.resources.transfers.table.textureTransfers.transfer: "グラフィックスキューを使い、選択したサブリソースをコピー用のレイアウトへ遷移させ、コピー後に指定された最終レイアウトへ遷移させて、完了を待ちます。" +concepts.resources.transfers.title: "即時に完了する転送とコマンドに記録する転送を選ぶ" +concepts.resources.usages.description: "{bufferUsages} と {textureUsages} は、リソースの想定される役割を宣言するフラグ列挙型です。これらはそれぞれ {bufferDescUsages} と {textureDescUsages} に割り当てられます。フラグ列挙型を使用すると、リソースに複数の役割がある場合に {value} を使用して複数のメンバーを組み合わせることができます。" +concepts.resources.usages.title: リソースを作成する前に必要な用途を宣言する +concepts.resources.views.description: "{bufferView} は、バッファー領域とその解釈を記述します。{textureView} は、互換性のあるテクスチャタイプ、フォーマット、およびサブリソース範囲を選択します。ビューは基盤となるストレージを共有します。データをコピーしたり、リソース作成時に欠落していた用途を追加したりすることはありません。また、その範囲はシェーダーの境界チェックのポータブルな保証にはなりません。" +concepts.resources.views.details: "デフォルトビューにはリソース自体のハンドルを使い、別の領域や互換性のある別の解釈が必要ならビューを作成します。GPU 処理が利用する可能性がある間は、ビューとその基になるリソースの両方への C# 参照を保持してください。リソースハンドルだけでは、どちらのオブジェクトも存続しません。最後の GPU 使用が完了してから解放してください。どちらかを置き換えたら、その古い{link}を含む定数も更新します。" +concepts.resources.views.details.link: "リソースハンドル" +concepts.resources.views.guidance: "{link} はリサイズ時に置き換えられる深度テクスチャを示しています。{detail} は、書き込み可能な出力から分離して保持される入力テクスチャを示しています。どちらも、リソースの有効期間をそれを実際に使用する処理に従わせています。" +concepts.resources.views.guidance.detail: コンピュートサンプル +concepts.resources.views.guidance.link: 回転する立方体のレンダラー +concepts.resources.views.title: "ビューとその基になるリソースを共に使用可能に保つ" +concepts.shaders.binding.context: "コンピュートサンプルでは、{input} には {inputTextureSampledHandle} が、{output} には {outputTextureStorageHandle} が入力されます。Slang の型付き {descriptorHandle} は、各リソースへのアクセス方法をシェーダーに伝えます:" +concepts.shaders.binding.description: "{setConstantBuffer} は、現在のパイプラインの定数データ用にバッファーとバイトオフセットをバインドします。これは既存の GPU から見えるストレージをバインドするものであり、C# の値をアップロードするわけではありません。最初にバッファーを埋め、以前の GPU 読み取り側が終了していることを確認してから、そのバイトを上書きしてください。" +concepts.shaders.binding.details: "定数バッファーの前にパイプラインを設定してください。リソースがすでに作成およびアップロードされているコンピュートワークロードの場合、記録はこの順序を使用します:" +concepts.shaders.binding.guidance: このコード片は、記録中の {commandBuffer}、{computePipeline}、{bufferUsagesConstant} 用途でアップロードされた {constantBuffer}、およびワークロードのスレッドグループ数を前提としています。オフセット 0 はバッファーの先頭をバインドします。複数の定数データレコードが 1 つのバッファーを共有する場合、各レコードの開始オフセットはバックエンドのバインディングアライメントを満たす必要があります。その要件は、レコード内のフィールドレイアウトとは別個のものです。 +concepts.shaders.binding.notes: "{resourceHandle} は 2 つの 32 ビットフィールドを格納しますが、その解釈はバックエンドに属します。これをコンテキスト間で転送可能なユニバーサル記述子インデックス、アドレス、または値として扱わないでください。ハンドルはリソースを作成せず、欠落している用途を追加せず、同期も実行しません。" +concepts.shaders.binding.reference: リソースおよびそのハンドルの取得に使用したビューへの参照を保持し、シェーダーの最後の使用が完了した後にのみ破棄してください。テクスチャまたはビューを交換する際は、その古いハンドルを含む定数を更新してください。{link} でそのライフサイクルの関係について説明しています。 +concepts.shaders.binding.reference.link: リソース管理 +concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: シェーダー型 {t} の構造化要素を読み取ります。 +concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: シェーダー型 {t} の構造化要素の読み取りまたは書き込みを行います。 +concepts.shaders.binding.table.headings.access: 想定されるアクセス +concepts.shaders.binding.table.headings.cHandle: "C# ハンドル" +concepts.shaders.binding.table.headings.slangFieldType: Slang フィールド型 +concepts.shaders.binding.table.samplerHandle.access: テクスチャサンプリング状態を提供します。 +concepts.shaders.binding.table.textureSampledHandle.access: テクスチャを読み取ります。 +concepts.shaders.binding.table.textureStorageHandle.access: ストレージテクスチャの読み取りまたは書き込みを行います。 +concepts.shaders.binding.title: 定数バッファーとそれが記述するリソースをバインドする +concepts.shaders.compilation.description: "{zenithCompiler} は指定された Slang エントリポイントをコンパイルし、{shaderDesc} を返します。コンテキストの {graphicsApi} を使用して、シェーダーを作成するバックエンド (DirectX 12 用の DXIL、Metal 用の Metal ライブラリ、Vulkan 用の SPIR-V) をターゲットにします。" +concepts.shaders.compilation.details: "たとえば、既存の {context} があり、三角形のシェーダーが実行可能ファイルの横にコピーされている場合は次のようになります:" +concepts.shaders.compilation.guidance: "{vSMain} はシェーダーファイル内のエントリポイント名と完全に一致している必要があります。パイプライン作成中はシェーダーオブジェクトを有効に維持し、{link} に示されているようにパイプライン作成後に破棄してください。フレームごとに再コンパイルするのではなく、この初期化を 1 回実行します。" +concepts.shaders.compilation.guidance.link: 最初の三角形 +concepts.shaders.compilation.title: 選択したコンテキスト用にエントリポイントをコンパイルする +concepts.shaders.description: "シェーダーはアプリケーションから提供されたデータを受け取ります。頂点属性は個々の頂点を記述し、バッファーはパラメーターや配列を保持し、リソースハンドルはシェーダーがアクセスする他のリソースを識別します。C# の宣言と Slang の宣言は、それらの値の意味について一致している必要があります。フィールド名を一致させるだけでは不十分です。レイアウト、リソースアクセス、バインディングのすべてが一致している必要があります。" +concepts.shaders.dispatch.description: "{dispatch} はスレッドグループの数を受け取ります。コンピュートサンプルの {numthreads} エントリポイントは、グループあたり 16 × 16 スレッドを実行します。画像寸法を 16 で除算し、切り上げてグループ数を求めます。たとえば、17 × 19 の画像には 2 × 2 のグループが必要です。最後のグループに画像外のスレッドが含まれる可能性があるため、シェーダーはそのピクセル座標を画像寸法と照合してチェックします。" +concepts.shaders.dispatch.details: コンパイラは、宣言されたエントリポイントのグループサイズを {shaderDescThreadGroupSize} に格納します。{dispatch} に指定されたピクセル寸法をグループ数に変換することはありません。完全なバインディングとディスパッチの例については、シェーダー付きの {computeShaderRendererCs} を使用し、別のパスが出力を消費する前には {link} を使用してください。 +concepts.shaders.dispatch.details.link: 同期 +concepts.shaders.dispatch.title: ピクセルではなくスレッドグループをディスパッチする +concepts.shaders.layout.context: "{link} はそのオフセットを明示しています。この宣言にはスコープ内に {systemRuntimeInteropServices} と {zenithNET} が必要です:" +concepts.shaders.layout.context.link: "コンピュートサンプルの C# 定数" +concepts.shaders.layout.description: "頂点入力の場合、パイプラインの {inputLayout} がフォーマット、オフセット、ストライド、セマンティクスを記述します。三角形の {float3} 位置に続く {float4} 色は 28 バイトを占め、色はバイト 12 にあります。{inputLayoutAdd} はこのパックされたレイアウトを計算します。C# の構造体を検査するわけではありません。C# フィールドにパディングが含まれている場合は、フィールドがパックされていると仮定せずに、一致するレイアウトを提供してください。" +concepts.shaders.layout.details: "定数バッファーはシェーダーパラメーターを保持し、構造化バッファーは宣言された型の要素の配列を保持します。どちらも Slang の宣言に従って読み取られます。{inputLayout} は使用しません。パディングを含め、コンパイルされたシェーダー表現のフィールドオフセットと要素サイズを確認してください。アンマネージド C# 型はバイト単位でのコピーに適していますが、それだけでシェーダー型と一致することが証明されるわけではありません。特に、頂点の密集した {float3} レイアウトをすべてのシェーダーバッファーに適用しないでください。" +concepts.shaders.layout.guidance: リソースハンドルは、既存のリソースを参照する小さな値です。ハンドルを定数バッファーにコピーしても、リソースの内容はコピーされません。 +concepts.shaders.layout.notes: "{computeShaderSlang} 内の対応する宣言は次のとおりです:" +concepts.shaders.layout.reference: "寸法が最初の 8 バイトを占め、その後に 2 つの 8 バイトリソースハンドルが続きます。C# サンプルは合計 256 バイトを予約しています。そのサイズはサンプルが選択したストレージサイズであり、すべての Slang 構造体や定数ペイロードが 256 バイトを占めるという規則ではありません。合計サイズをパディングしても、間違ったオフセットにあるフィールドは修正されません。" +concepts.shaders.layout.title: 頂点入力とシェーダーデータには異なるレイアウト規則がある +concepts.shaders.matrices.description: コンパイラは、各行の要素をまとめて格納する行優先 (row-major) の行列ストレージを要求します。{link} は 3 つの {matrix4x4} 値をオフセット 0、64、128 に配置します。その {detail} は、モデル、ビュー、プロジェクションの順序で {mulVectorMatrix} を使用します。 +concepts.shaders.matrices.description.detail: シェーダー +concepts.shaders.matrices.description.link: 回転する立方体のレンダラー +concepts.shaders.matrices.details: 格納順序は行列要素がどのようにメモリを占有するかを決定し、乗算順序は変換を決定します。両側の一貫性を維持してください。これら 2 つの選択を確認せずに転置を追加すると、別の不一致を招きながら 1 つの不一致を覆い隠してしまう可能性があります。 +concepts.shaders.matrices.title: 行列の格納と乗算の一貫性を維持する +concepts.shaders.title: シェーダーデータとバインディング +concepts.synchronization.backends.description: DirectX 12 と Vulkan は、レイアウトおよびアクセス情報とともにテクスチャ遷移をエンコードします。Metal は Zenith.NET の {transition} 実装において操作を持ちません。Metal は記録された作業をレンダーエンコーダーおよびコンピュートエンコーダーにグループ化します。バックエンドはこれらのグループを終了するときに可視性バリアを挿入し、先行の書き込みを後続の作業で利用可能にします。明示的な {barrier} 呼び出しは、同じエンコーダー内の連続するコンピュートディスパッチなどの依存関係を処理します。 +concepts.synchronization.backends.details: この違いはワークロードを変更する際に重要になります。{link} では、ディスパッチの後にグラフィックスレンダーパスが続き、Metal 上でもエンコーダー境界が作成されます。2 つの依存するコンピュートディスパッチは、テクスチャの宣言されたレイアウトを変更するだけではその境界を作成しません。共有 API で要求される遷移を維持し、実際のプロデューサーコマンドとコンシューマーコマンドの間の依存関係を個別に特定してください。 +concepts.synchronization.backends.details.link: コンピュートサンプル +concepts.synchronization.backends.title: 遷移はすべてのバックエンドで同一ではない +concepts.synchronization.barriers.context: "{barrierStagesAll} はより広いスコープであり、自動依存関係検出機能ではありません。処理を実際にカバーするステージを選択し、それらの操作をサポートするキューでのみ使用してください。" +concepts.synchronization.barriers.description: "2 つのコンピュートディスパッチを考えてみましょう。1 つ目がシミュレーションデータを書き込み、2 つ目が次のステップを実行するためにそのデータを読み取ります。両方ともストレージバッファーを使用するため、変更すべきテクスチャレイアウトはありません。コマンドバッファー上のディスパッチの間に次を挿入します:" +concepts.synchronization.barriers.details: 第 1 引数はプロデューサーステージを識別し、第 2 引数はコンシューマーステージを識別します。バリアは、GPU 上に対応する実行およびメモリの依存関係を確立します。バックエンドはそれらのステージを実行規則およびメモリアクセス規則に変換します。このバリアはテクスチャのレイアウトを変更せず、デバイス上のすべての処理を待機するわけでもありません。 +concepts.synchronization.barriers.guidance: "{link} は依存するディスパッチ間でこのパターンを使用しています。依存関係が発生する場所にバリアを配置してください。コンシューマーがすでに記録された後に配置されたバリアは、そのコンシューマーを先行のプロデューサーの後に順序付けることはできません。" +concepts.synchronization.barriers.guidance.link: FluidTank シミュレーション +concepts.synchronization.barriers.title: バリアで依存するコマンドを順序付ける +concepts.synchronization.dependencies.description: 共有リソースごとに、最初にアクセスする操作、それに続く操作、およびいずれかのアクセスが書き込みを行うかどうかを特定します。同じデータを 2 回読み取る場合、内容を保護するための順序付けは不要ですが、レイアウト変更やプレゼンテーションによって他の要件が課されることがあります。書き込みに続く読み取り、読み取りに続く上書き、または 2 回の書き込みには依存関係が必要になる場合があります。 +concepts.synchronization.dependencies.details: "次に、それらの操作が実行される場所に応じたメカニズムを選択します:" +concepts.synchronization.dependencies.guidance: "これらの仕組みは関連していますが、互いの代わりにはなりません。コマンドを順にサブミットするだけでは、すべてのメモリ依存関係を満たせません。キューの待機は新しいテクスチャレイアウトを宣言せず、コマンドバリアは呼び出し元の CPU スレッドを待機させません。" +concepts.synchronization.dependencies.table.cpuAccess.mechanism: 該当する完了値に対して {wait} を呼び出します。 +concepts.synchronization.dependencies.table.cpuAccess.situation: データへのアクセスまたは解放の前に CPU が待機する必要がある場合 +concepts.synchronization.dependencies.table.crossQueue.mechanism: その {timelineValue} をコンシューマー側のコマンドバッファーの {submit} に渡します。 +concepts.synchronization.dependencies.table.crossQueue.situation: 別のキューでのサブミットがデータを生成する場合 +concepts.synchronization.dependencies.table.headings.mechanism: メカニズム +concepts.synchronization.dependencies.table.headings.situation: 状況 +concepts.synchronization.dependencies.table.layoutChange.mechanism: 以前のレイアウトと次のレイアウトを指定した {commandBufferTransition}。 +concepts.synchronization.dependencies.table.layoutChange.situation: テクスチャサブリソースの使用方法の変更 +concepts.synchronization.dependencies.table.pipelineStages.mechanism: プロデューサーステージとコンシューマーステージを指定した {commandBufferBarrier}。 +concepts.synchronization.dependencies.table.pipelineStages.situation: コマンドストリーム内の依存する GPU ステージ +concepts.synchronization.dependencies.title: プロデューサーとコンシューマーから始める +concepts.synchronization.description: 先行のコマンドによって書き込まれたデータを読み取るコマンドは、それらの書き込みが完了し、自身に対して可視化されていることに依存します。書き込み側がプロデューサーであり、読み取り側がコンシューマーです。CPU も共有データの読み取り、上書き、解放の前に完了ポイントを必要とします。Zenith.NET は、これらの異なる依存関係のためにバリア、テクスチャ遷移、タイムラインを提供します。 +concepts.synchronization.layouts.context: "{undefined} は、以前の内容を保持する必要がないことを意味します。これは新しい画像や完全にクリアされるアタッチメントに適しています。内容が読み込まれたり、サンプリングされたり、蓄積されたりする画像のレイアウト追跡を回避するための手段ではありません。" +concepts.synchronization.layouts.description: "用途フラグはテクスチャがサポートする役割を記述します。{textureLayout} は、特定の操作のために特定のサブリソースがどのようにアクセスされるかを記述します。サブリソースとは、選択されたミップレベルと配列レイヤーです。そのレイアウトを変更することでそのアクセスの準備が行われますが、テクスチャが異なるピクセルフォーマットに変換されるわけではありません。たとえば、コンピュートサンプルは {storage} レイアウトで出力テクスチャを書き込み、その後グラフィックスパスでそれをサンプリングします。それらの使用の間に次を記録します:" +concepts.synchronization.layouts.details: このコード片は、{outputTexture} が {sampledStorage} 用途で作成され、その選択されたサブリソースが {storage} レイアウトにあることを前提としています。{default} はミップレベル 0 と配列レイヤー 0 を選択します。この操作は、テクスチャのすべてのミップやレイヤーを遷移させるわけではありません。 +concepts.synchronization.layouts.guidance: アプリケーションが以前のレイアウトを提供します。{transition} はアプリケーションから見えるレイアウトトラッカーを保持せず、先行のコマンドからその値を推測することもありません。リソースがレンダリングステージ間を通過する場所では、常にレイアウトを追跡してください。 +concepts.synchronization.layouts.title: 各テクスチャサブリソースのレイアウトを追跡する +concepts.synchronization.readback.description: "{isCompleted} は、GPU タイムラインが値に達したかどうかのみを問い合わせます。それ自体がコマンドバッファーを回収したり、ステージングされたダウンロードをアプリケーションの宛先ポインターにコピーしたりするわけではありません。" +concepts.synchronization.readback.details: "{commandBufferDownload} は、まず内部リードバックストレージへのコピーを記録します。完了したコマンドバッファーを再利用のためにリセットすると、指定されたポインターへの CPU コピーが行われます。そのダウンロードのサブミット値に対する {wait} が戻るまで、転送先を有効に保ち、マネージドメモリを固定してください。データの読み取りやメモリの解放はその後に行います。別のキューの後続サブミットを待っても、ダウンロードを管理するキュー自体はポーリングされません。" +concepts.synchronization.readback.guidance: そのため、{isCompleted} をポーリングして非同期ダウンロードの宛先を直ちに読み取るだけでは不十分です。{link} で直接コピーパスとステージング転送パスについて説明しています。 +concepts.synchronization.readback.guidance.link: リソース管理 +concepts.synchronization.readback.title: GPU 完了とダウンロードされた CPU データは別のステップである +concepts.synchronization.reuse.description: "最初のレンダラーでは、毎フレーム直後に待機する方法がわかりやすいでしょう。複数フレームの処理を重ねて進めるには、未完了のフレームごとに変更可能なデータを分け、各フレームの最終使用の完了値を保持してください。定数バッファーの更新、テクスチャの交換、パイプラインの破棄の前に、対象リソースへのすべての未完了アクセスを終わらせてください。" +concepts.synchronization.reuse.details: リサイズ時やシャットダウン時には、古い作業を待機する前に新しい使用を停止してください。{swapChainResize}、リソースの破棄、コンテキストの破棄は、アプリケーションの作業に対する一般的な待機の役割を果たしません。前の各フレームがすでにサブミットを完了しているため、三角形チュートリアルはコールバック間で安全にリサイズできます。 +concepts.synchronization.reuse.guidance: "現在の {swapChainPresent} も、プレゼンテーション操作の後にグラフィックスキューでシグナルを送って待機します。そのため、三角形の明示的なサブミット待機を削除するだけでは、複数フレームの処理を重ねて進める表示ループにはなりません。グラフィックスキューでの待機は、別のキューで実行中の独立した処理の完了も保証しません。" +concepts.synchronization.reuse.title: 最後のアクセス後にのみデータを再利用する +concepts.synchronization.timelines.context: "CPU がこれらのリソースの読み取り、上書き、解放を行う前に、その最後の使用を待機してください:" +concepts.synchronization.timelines.description: タイムラインは増加する値を使用してキュー上の完了を追跡します。{submit} はそのタイムラインとサブミットに関連付けられた値を含む {timelineValue} を返します。異なるタイムラインの完了値は、数値の {value} フィールドだけで比較することはできません。 +concepts.synchronization.timelines.details: "{producer} と {consumer} が同じコンテキストの 2 つのキューからすでに記録されたコマンドバッファーであると仮定します。プロデューサーはコンシューマーが使用するデータを書き込みます。次のようにサブミットします:" +concepts.synchronization.timelines.guidance: 生成された値を渡すと、コンシューマーキューは GPU 上でそれを待機します。CPU はここで {producedWait} を呼び出しません。{consumed} が完了するまで共有リソースを有効に保ち、コンシューマーに必要なテクスチャレイアウトの変更を記録してください。 +concepts.synchronization.timelines.notes: "{wait} はそのタイムライン値を待機し、完了したサブミットがないか所有キューを確認します。完了したコマンドバッファーは再利用のためにリセットされ、ステージングされたダウンロードは指定された CPU 宛先にコピーされます。{queueTimelineSignal} は、すでにそのキューにサブミットされた作業の後に完了ポイントをエンキューすることもできます。{signal} を呼び出しても、GPU がすでにそのポイントに達したことを意味するわけではありません。" +concepts.synchronization.timelines.title: 完了およびキューの引き渡しにタイムラインを使用する +concepts.synchronization.title: 同期 +home.actions.reference: API を参照 +home.actions.tutorial: 三角形から始める +home.entries.description: 最初のフレーム。焦点を絞ったサンプル。API の詳細。 +home.entries.label: ドキュメントを探索 +home.entries.reference.action: API を探索 +home.entries.reference.category: リファレンス +home.entries.reference.description: アプリケーションの基盤となる型、シグネチャ、メンバーを確認できます。 +home.entries.reference.title: API リファレンス +home.entries.samples.action: サンプルを参照 +home.entries.samples.category: サンプル +home.entries.samples.description: ソースコードを通じて、焦点を絞ったレンダリングやコンピュートの技術を調べます。 +home.entries.samples.title: サンプル +home.entries.title: 開発を始めましょう。 +home.entries.tutorial.action: チュートリアルを開始 +home.entries.tutorial.category: チュートリアル +home.entries.tutorial.description: セットアップから最初のフレームまで、完全なレンダリングアプリケーションを構築します。 +home.entries.tutorial.title: 最初の三角形 +home.introduction.accent: "C# で構築。" +home.introduction.description: 単一の .NET API を通じて、リソースの作成、コマンドの記録、グラフィックスやコンピュート処理のサブミットを行います。 +home.introduction.title: 独自のレンダラーを構築。 +home.meta.description: "DirectX、Metal、Vulkan を横断する、グラフィックスとコンピュートのための統一された C# API です。" +home.scene.description: 回転するジオメトリの研究です。ドラッグまたは矢印キーで視点を調整できます。 +home.scene.label: ジオメトリ表示 +home.scene.surface: サーフェス +home.scene.wireframe: ワイヤーフレーム +home.title: ".NET 向けモダン RHI" +learning.concepts.description: レンダリングパスを組み合わせる前に、コマンド、リソース、シェーダーデータ、同期がどのように連携するかを理解します。 +learning.concepts.execution.description: GPU 処理を記録してサブミットし、そのリソースを有効に維持します。 +learning.concepts.platforms.description: ネイティブウィンドウまたは UI レンダリングコントロールを接続します。 +learning.concepts.resources.description: リソースの用途、メモリ配置、ビューを選択します。 +learning.concepts.shaders.description: "C# のレイアウトとリソースハンドルを Slang と一致させます。" +learning.concepts.synchronization.description: 依存するアクセスを順序付け、処理が完了するタイミングを把握します。 +learning.concepts.title: 基本概念 +learning.description: 完全な三角形チュートリアルから始めます。その後、焦点を絞ったサンプルと概念ガイドを活用して、より大規模なレンダラーの背景にあるリソース、データ、依存関係を理解します。 +learning.entries.samples.action: サンプルを参照 +learning.entries.samples.description: "ジオメトリ、コンピュート、レイクエリ、メッシュシェーディングに関する C# と Slang のサンプルを確認できます。" +learning.entries.tutorial.action: チュートリアルを開く +learning.entries.tutorial.description: コンソールアプリケーションを作成し、ウィンドウを開いて三角形を描画します。 +learning.meta.description: Zenith.NET の基本を学び、そのプログラミングモデルを調べます。 +learning.title: 学習 +reference.description: リソース型、コマンドシグネチャ、プラットフォーム統合を調べます。 +reference.entries.commands.description: グラフィックス、コンピュート、転送コマンドを記録します。 +reference.entries.commands.label: 処理を記録 +reference.entries.context.description: 選択したバックエンド用の GPU リソースを作成します。 +reference.entries.context.label: ここから開始 +reference.meta.description: Zenith.NET の型とメンバーを調べます。 +reference.navigation.core: コア API を参照します。 +reference.title: API リファレンス +samples.computeShader.description: コンピュートディスパッチで画像をグレースケールに変換し、結果のテクスチャを表示します。サンプリングされる入力テクスチャと書き込み可能な出力テクスチャのリソースハンドル、切り上げられたスレッドグループ数、シェーダー内の境界チェックを示します。付属の {assetsTexturesShokoPng} アセットを保持してください。レンダラーはこれを一度処理し、以降のフレームで結果を提示します。 +samples.computeShader.details: "{computeShaderRendererCs} · {computeShaderSlang}" +samples.computeShader.title: コンピュートシェーダー +samples.cube.description: インデックス描画、定数バッファー内のモデル・ビュー・プロジェクション行列、深度テストを追加します。深度テクスチャはリサイズ時に再作成されます。クリップ空間ジオメトリから変換されたオブジェクトへ移行する際にご利用ください。レンダラーは {d32FloatS8UInt} 深度/ステンシルアタッチメントを使用します。 +samples.cube.details: "{spinningCubeRendererCs} · {spinningCubeSlang}" +samples.cube.title: 回転する立方体 +samples.description: "調べたい機能に応じた焦点を絞ったサンプルを選択してください。各サンプルから C# レンダラーとその Slang シェーダーにリンクしています。空のプロジェクトから完全なアプリケーションを段階的に理解したい場合は、{link} から始めてください。" +samples.description.link: 最初の三角形 +samples.execution.description: "{link} には、1 つのデスクトップアプリケーション内に 6 つの独立したレンダラーが含まれています。.NET 10 SDK と、以下で説明するサポート対象のデスクトップバックエンドを使用してください。アプリケーションをビルドして実行し、コンソールメニューからサンプルを選択します。" +samples.execution.description.link: ZenithTutorials +samples.execution.details: ホストは Windows では DirectX 12、macOS では Metal、Linux では Vulkan を選択します。選択したバックエンドでサポートされているデバイス、ドライバー、シェーダーコンパイラ環境を使用してください。Linux のウィンドウパスには X11 または XWayland が必要です。{link} はパッケージの依存関係を宣言し、実行時に必要なシェーダーとテクスチャのアセットをコピーします。 +samples.execution.details.link: プロジェクトファイル +samples.execution.guidance: 各サンプルはウィンドウ処理とプレゼンテーションのコードを共有しています。学習したい機能に応じて、任意のサンプルを個別に選択できます。 +samples.execution.title: チュートリアルサンプルを実行する +samples.host.description: "{appCs} はコンテキスト、ウィンドウ、スワップチェーンを作成します。コマンドバッファーを取得し、選択したレンダラーを呼び出し、フレームをサブミットして提示します。{iRendererCs} はレンダラーの更新、レンダリング、リサイズ、破棄の各メソッドを定義します。" +samples.host.details: コンピュートとレイトレーシングはオフスクリーンテクスチャを生成します。{texturePresenterCs} と {presentTextureSlang} は、それらのテクスチャをウィンドウの現在のフレームの出力テクスチャに描画します。ホストは引き続きサブミットとスワップチェーンのプレゼンテーションを所有します。 +samples.host.title: 共有ホストとプレゼンテーション +samples.indirectDrawing.description: インデックス付きの間接引数バッファーと構造化バッファー内のインスタンスごとのデータを使用して、立方体の複数のコピーを描画します。CPU が描画引数を提供し、変換を更新します。GPU 生成の引数を追加する前に、間接引数のレイアウトとインスタンスデータへのシェーダーアクセスを理解するためにご利用ください。 +samples.indirectDrawing.details: "{indirectDrawingRendererCs} · {indirectDrawingSlang}" +samples.indirectDrawing.title: 間接描画 +samples.meshShading.description: タスクシェーダーを使用して球体のインスタンスをカリングし、そのインデックスをジオメトリを出力するメッシュシェーダーに渡します。レンダラーはパイプラインを作成する前に {contextCapabilitiesMeshShadingSupported} を確認します。タスクステージとメッシュステージを通じてリソースハンドルとペイロードデータを追跡するためにご利用ください。 +samples.meshShading.details: "{meshShadingRendererCs} · {meshShadingSlang}" +samples.meshShading.title: メッシュシェーディング +samples.rayTracing.description: "地面とプロシージャルな球体のボトムレベルおよびトップレベルのアクセラレーション構造を構築し、コンピュートシェーダー内でインラインのレイクエリを実行します。レンダラーはワークロードを構築する前に {contextCapabilitiesRayTracingSupported} を確認します。アクセラレーション構造の入力とシェーダー側のレイ走査の確認にご利用ください。" +samples.rayTracing.details: "{rayTracingRendererCs} · {rayTracingSlang}" +samples.rayTracing.title: レイトレーシング +samples.title: サンプル +samples.triangle.description: 頂点バッファーと一致する入力レイアウトを作成し、グラフィックスパイプラインを介して 3 つの頂点を描画します。リソースの作成とレンダーパス内のコマンドを結びつけるためにご利用ください。 +samples.triangle.details: "{helloTriangleRendererCs} · {helloTriangleSlang} · {link}" +samples.triangle.details.link: 完全なチュートリアル +samples.triangle.title: Hello Triangle +samples.workloads.description: "メインリポジトリの {link} には、複数の機能を組み合わせたアプリケーションが含まれています。それらのプロジェクトはライブラリのソースコードを参照します。Zenith.NET のチェックアウトから、目的のプロジェクトを実行してください。例:" +samples.workloads.description.link: Experiments ディレクトリ +samples.workloads.details: ウィンドウ表示の実験では、Windows、macOS、Linux/X11 で同じホスト選択を使用します。Avalonia、WinForms、WPF、WinUI/Uno、MAUI 内での描画、コントロールのフレームライフサイクル、実装リンクについては、{link} を参照してください。 +samples.workloads.details.link: プラットフォーム統合 +samples.workloads.table.cornellBox.example: "{link}" +samples.workloads.table.cornellBox.example.link: CornellBox +samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: パストレーシング、デノイズ、トーンマッピング、アップスケーリング、ImGui コントロールを実証します。レイトレーシングのサポートと、デスクトップバックエンド用のシェーダーコンパイル環境が必要です。 +samples.workloads.table.fluidTank.example: "{link}" +samples.workloads.table.fluidTank.example.link: FluidTank +samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: コンピュートによる流体シミュレーション、シミュレーションステージ間の依存関係、マルチパスのサーフェスレンダリングを実証します。デスクトップバックエンドとシェーダーコンパイル環境が必要です。 +samples.workloads.table.headings.example: 例 +samples.workloads.table.headings.whatItDemonstratesAndRequires: 実証内容と要件 +samples.workloads.table.inkCanvas.example: "{link}" +samples.workloads.table.inkCanvas.example.link: InkCanvas +samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: ネイティブウィンドウでの Skia 描画と入力処理を実証します。ターゲットプラットフォーム用のバックエンドと Skia ネイティブライブラリが必要です。 +samples.workloads.table.platformDetection.example: "{link}" +samples.workloads.table.platformDetection.example.link: PlatformDetection +samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: 各バックエンドのコンテキスト作成を試行し、デバイス機能を報告します。コンテキスト作成が失敗した場合はサポートされていないと報告されます。この結果は、ドライバーやランタイム依存関係の欠如を示している可能性もあります。 +samples.workloads.title: より大規模なワークロードを探索する +tutorial.context.description: これでウィンドウを開くことができるようになりましたが、ウィンドウ内にレンダリングを行う GPU オブジェクトはまだ作成していません。{graphicsContext} は、選択したグラフィックスバックエンドとそのコマンドキューへのアクセスを提供します。 +tutorial.context.details: "このブロックを {emphasis} に挿入します:" +tutorial.context.details.emphasis: using ディレクティブの後、{iWindowWindow} の前 +tutorial.context.guidance: 分岐処理により、Windows では DirectX 12、macOS では Metal、Linux では Vulkan が選択されます。その後のレンダリングコードは共通の Zenith.NET API を使用します。開発中は検証を要求し、{validationMessage} を通じて報告されるメッセージを出力します。診断情報は、バックエンドおよびマシンで利用可能な検証コンポーネントによって異なります。 +tutorial.context.title: グラフィックスコンテキストを作成する +tutorial.description: ウィンドウを開き、滑らかなグラデーションの三角形を描画する .NET コンソールアプリケーションを作成します。頂点データ、シェーダー、パイプライン状態がどのように連携するかを学び、画像を生成するコマンドを記録してサブミットします。 +tutorial.details: 各セクションを順番に進めてください。まず空のウィンドウを開き、次に背景色を表示し、最後に三角形を描画します。各チェックポイントで、次の段階に進む前にアプリケーションの一部が正しく動作することを確認します。初期化は 1 回実行され、描画コールバックは呼び出されるたびに新しいフレームを記録します。 +tutorial.draw.context: "{draw} の引数は次のとおりです:" +tutorial.draw.description: "{windowRender} コールバックで、{beginRenderPass} と {endRenderPass} の間にある {addTheTriangleDrawCommandsHereLater} を次の 3 つのコマンドに置き換えます:" +tutorial.draw.details: "{setPipeline} は、先ほど作成したシェーダーと状態を選択します。頂点データをバインドする前に設定してください。バックエンドはパイプラインの入力レイアウトを使用してバインディングを解釈します。" +tutorial.draw.guidance: "{setVertexBufferVertexBuffer} は、バイトオフセット 0 から始まるバッファーを入力スロット 0 にバインドします。そのスロットは {inputLayouts} の単一エントリに対応します。これによりデータが再コピーされたり再アップロードされたりすることはありません。" +tutorial.draw.notes: この時点では、コマンドはまだ記録されただけです。描画コールバックの最後にある {submitWait} と {present} の呼び出しが処理を実行し、その結果を表示します。三角形は画像の一部しか覆わないため、クリア操作は引き続き必要です。背景も各フレームで定義された色を受け取る必要があります。 +tutorial.draw.table.firstInstance.meaning: インスタンスの番号付けをゼロから開始します。 +tutorial.draw.table.firstVertex.meaning: バッファー内の最初の頂点から開始します。 +tutorial.draw.table.headings.argument: 引数 +tutorial.draw.table.headings.description: 値 +tutorial.draw.table.headings.meaning: 意味 +tutorial.draw.table.instanceCount.meaning: 三角形のコピーを 1 つ描画します。 +tutorial.draw.table.vertexCount.meaning: 3 つの頂点を読み取ります。 +tutorial.draw.title: パス内で三角形を描画する +tutorial.execution.description: "{firstTriangle} ディレクトリからビルドして実行します:" +tutorial.execution.details: 暗い背景に対して、上が赤、右下が緑、左下が青の角を持つ三角形がウィンドウに表示されるはずです。内部はこれらの色間で滑らかなグラデーションを示す必要があります。 +tutorial.execution.guidance: ウィンドウのサイズを変更してください。リサイズコールバックがフレームバッファーのサイズを更新し、スワップチェーンをリサイズします。レンダーパスはその画像に一致するビューポートを確立します。頂点位置は正規化座標のままであるため、三角形はウィンドウの幅と高さに対する同じ比率を維持します。アスペクト比を変更すると形状が引き伸ばされることがあります。オブジェクトのアスペクト比を維持するには、この最初の描画の範囲を超えるプロジェクションまたはビューポートポリシーが必要です。 +tutorial.execution.title: 実行、リサイズ、および閉じる +tutorial.frame.commands.context: "{endRenderPass} の後、2 つ目の遷移によって画像がプレゼンテーション用に準備されます。{submit} は記録を完了してコマンドバッファーをサブミットし、{wait} は GPU がそのサブミットを完了するのを待機します。その後、{present} はレンダリングされた画像の表示を要求します。" +tutorial.frame.commands.description: レンダーパスは、同じアタッチメントを使用する描画操作をグループ化します。ここでは、カラーアタッチメントはスワップチェーンの出力テクスチャ、すなわち描画を受け取る画像です。{colorAttachmentClear} は、指定した RGBA カラーでクリアし、パスの終了時に結果を保持するよう指示する記述を作成します。{beginRenderPass} はこれらの命令を記録し、コマンドがサブミットされた後に GPU がクリアを実行します。 +tutorial.frame.commands.details: 角括弧には単一のカラーアタッチメントが含まれています。引数 {null} は、深度およびステンシルテスト用の深度値とステンシルマスクを格納する深度/ステンシルアタッチメントが存在しないことを意味します。 +tutorial.frame.commands.guidance: "{beginRenderPass} は、アタッチメントをカバーするビューポートとシザーを設定します。ビューポートはレンダリング座標をピクセルにマッピングし、シザーは書き込み可能なピクセルを制限します。これらのデフォルト設定は出力テクスチャ全体をカバーし、この三角形の描画に適しています。" +tutorial.frame.commands.title: クリア、サブミット、およびプレゼンテーション +tutorial.frame.description: まず画像を単一の背景色で塗りつぶします。この操作はクリアと呼ばれます。その色がウィンドウに表示されれば、サーフェス、コマンドのサブミット、およびプレゼンテーションパスが正常に連携しています。このチェックポイントにより、ジオメトリやシェーダーを追加する前にフレームループを検証できます。 +tutorial.frame.details: "描画コールバックは、フレームを描画するタイミングで Silk.NET が呼び出すコードです。このコールバックではイベントの経過時間引数は不要なため、{value} と命名されています。これを {emphasis} に登録します:" +tutorial.frame.details.emphasis: "{windowRun} の前" +tutorial.frame.target.description: "{graphicsQueueCommandBuffer} は、すでに記録が開始されたコマンドバッファーを取得します。記録は GPU に対する処理を記述するものであり、その処理を即時に実行するわけではありません。" +tutorial.frame.target.details: 最初の {transition} は、カラーアタッチメントとしてのアクセスのために出力テクスチャを準備します。{default} はミップレベル 0 と配列レイヤー 0 を選択します。画像全体をクリアして以前の内容を破棄するため、以前のレイアウトとして {undefined} を使用します。既存の内容を保持する必要があるパスでは、代わりに実際の以前のレイアウトを使用する必要があります。 +tutorial.frame.target.guidance: 各フレームでスワップチェーンの現在の出力テクスチャを使用してください。プレゼンテーションによって利用可能な画像が変わる可能性があるため、以前のフレームから保存したテクスチャは永続的なウィンドウのレンダーターゲットにはなりません。 +tutorial.frame.target.title: 出力テクスチャを準備する +tutorial.frame.title: 背景色を表示する +tutorial.geometry.data.description: この配列を {emphasis} に追加します。後続のリソース作成ステップも、示された順序でこのコールバックの前に配置します。 +tutorial.geometry.data.description.emphasis: "{windowRender} の前" +tutorial.geometry.data.details: 配列の各エントリが 1 つの {vertex} を作成します。内側の 2 つの {new} 式は、その {vector3} 位置と {vector4} 色を作成します。頂点は上、右下、左下のコーナーを記述します。頂点シェーダーは 4 番目の位置座標 {w} を提供します。w が 1 の場合、x と y は正規化デバイス座標を直接表します。-1 と +1 が画像の端で、0 が中心です。これらの座標はウィンドウのピクセルサイズに依存しません。 +tutorial.geometry.data.guidance: 各色には赤、緑、青、アルファの成分が含まれます。3 つのコーナーすべてでアルファは 1 です。3 つの位置はすべて z = 0 であり、同じ平面上に配置されます。これらの位置はレンダリングしたい座標をすでに直接記述しているため、カメラや変換行列は不要です。この単一の平坦な三角形では、ブレンディングと深度テストも無効にし、深度バッファーも省略します。 +tutorial.geometry.data.title: コーナーの位置を選択する +tutorial.geometry.description: 頂点は、描画に使用されるデータと結びついた点です。この三角形には、各コーナーに 1 つずつ、計 3 つの頂点があります。各頂点には位置と色が含まれます。GPU は色を補間し、三角形全体の中間値を計算します。 +tutorial.geometry.format.description: "この宣言を {emphasis} に追加します:" +tutorial.geometry.format.description.emphasis: "{programCs} の末尾、クリーンアップステートメントの後" +tutorial.geometry.format.details: "{file} はこの型を {programCs} に限定し、コンストラクターがその位置と色のフィールドを初期化します。{layoutKindSequential} はフィールドを宣言順に維持します。{position} は 3 つの 32 ビット浮動小数点数を含み、{color} は 4 つを含みます。この構造体では、位置はバイト 0 から、色はバイト 12 から始まり、完全な頂点は 28 バイトを占めます。この同じレイアウトをグラフィックスパイプラインに記述します。" +tutorial.geometry.format.title: 頂点を定義する +tutorial.geometry.title: GPU に 3 つの頂点を提供する +tutorial.geometry.upload.context: "{fixed} は、アドレスが使用されている間にガベージコレクターが配列を移動するのを防ぎます。この CPU 書き込み可能バッファーの場合、{upload} は戻る前にメモリをマップ、コピー、アンマップするため、その後配列を固定したままにする必要はありません。バッファーはレンダリング全体を通じて存続する必要があり、頂点は変化しないためアップロードは 1 回だけ行えば十分です。" +tutorial.geometry.upload.description: "マネージド配列は CPU データです。{buffer} は、GPU が頂点を読み取るためのストレージを提供します。配列の後に次を追加します:" +tutorial.geometry.upload.details: "合計サイズは {sizeofVertexVerticesLength} です。頂点あたり 28 バイト、3 つの頂点で合計 84 バイトになります。{bufferUsagesVertex} は頂点入力アクセスを許可します。{cpuWriteOnly} は、CPU がこの小さなバッファーを直接初期化することを可能にします。記述子の ストライド は要素サイズを記録し、後で作成する入力レイアウトが個々の属性の読み取り方法を頂点フェッチに伝えます。" +tutorial.geometry.upload.guidance: バッファーを作成しただけではデータは格納されません。{upload} は、宛先のバイトオフセット 0 から始まる割り当てに配列をコピーします。そのソース記述はポインターとコピーするバイト数を提供します。 +tutorial.geometry.upload.notes: "{programCs} の末尾のクリーンアップで、{swapChainDispose} の直前に {vertexBufferDispose} を追加します。より大規模な静的ジオメトリについては、GPU 専用メモリと転送アップロードを選択する基準について {link} で説明しています。" +tutorial.geometry.upload.notes.link: リソース管理 +tutorial.geometry.upload.title: バッファーを割り当てて配列をアップロードする +tutorial.input.description: "頂点バイトとシェーダーの準備が整いました。次に、GPU が各頂点をどのように読み取るかを記述します。属性とは、位置や色などの 1 つの値です。入力レイアウトは各属性にフォーマットとバイトオフセットを与え、ストライド は 1 つの頂点から次の頂点までのバイト単位の距離を与えます。シェーダー作成後に次の初期化ブロックを追加します:" +tutorial.input.details: "{inputLayoutAdd} は現在の ストライド に要素を追加し、その ストライド を要素のサイズ分だけ増加させます。C# の構造体を検査するわけではありません。ここでは、CPU メモリとシェーダー入力との間で次の一致関係を生成します:" +tutorial.input.guidance: "この記述を更新せずに C# フィールドの順序やパディングを変更すると、GPU は間違ったバイトを読み取ることになります。デフォルトの {semanticIndex} はゼロで、{pOSITION0} および {cOLOR0} と一致します。両方の要素は同じバッファーに属するため、パイプラインには 1 つの入力レイアウトが含まれ、そのバッファーをスロット 0 にバインドします。" +tutorial.input.table.headings.byteOffset: バイトオフセット +tutorial.input.table.headings.cField: "C# フィールド" +tutorial.input.table.headings.format: フォーマット +tutorial.input.table.headings.shaderInput: シェーダー入力 +tutorial.input.table.nextVertex.cField: 次の頂点 +tutorial.input.table.nextVertex.format: "合計 ストライド: 28 バイト" +tutorial.input.table.nextVertex.shaderInput: 次の入力レコード +tutorial.input.table.vertexColor.format: "{float4} (16 バイト)" +tutorial.input.table.vertexPosition.format: "{float3} (12 バイト)" +tutorial.input.title: 頂点入力レイアウトを記述する +tutorial.lifecycle.description: "完成したアプリケーションはこのシーケンスを繰り返します:" +tutorial.lifecycle.details: "ウィンドウを閉じると {run} から戻ります。描画された各フレームはすでに GPU 処理の完了を待機しているため、使用されたリソースを安全に破棄できます。{windowRun} 後のクリーンアップは次のようになります:" +tutorial.lifecycle.guidance: "ネイティブウィンドウより先にスワップチェーンを解放し、すべてのリソースを解放した後にコンテキストを解放してください。サブミットされたコマンドバッファーはキューが所有して再利用し、出力テクスチャはスワップチェーンが所有します。このアプリケーションでは、それらのコマンドバッファーと出力テクスチャに個別の {dispose} 呼び出しは不要です。" +tutorial.lifecycle.title: 1 つのフレームのライフサイクルを追跡する +tutorial.pipeline.behavior: "入力レイアウトの後に次を追加します:" +tutorial.pipeline.context: "{cullNone} は、どちらの面の向きも破棄せずに三角形を塗りつぶします。頂点の順序が面の巻き方向を決定するため、カリングを無効にすることで、その順序によって最初の三角形が隠れてしまうのを防ぎます。" +tutorial.pipeline.description: これで頂点データ、入力レイアウト、2 つのシェーダーが揃いました。{graphicsPipeline} はこれらを接続し、GPU が頂点をプリミティブに組み立てて結果をアタッチメントに書き込む方法を指定します。 +tutorial.pipeline.details: "パイプラインは、プログラム可能なシェーダーステージと、三角形の組み立て、面カリング、ブレンディングなどの GPU 操作を制御する固定機能設定を結合します。この三角形には、以下の設定を選択します:" +tutorial.pipeline.guidance: カラーフォーマットは {swapChainDescFormat} から取得します。これはレンダーパスで使用される画像と一致している必要があります。{count1} はピクセルあたり 1 つのサンプルを意味します。 +tutorial.pipeline.item: "{triangleList} は、連続する 3 つの頂点ごとに 1 つの三角形を組み立てます。3 つの頂点を提供して 1 回描画するため、インデックスバッファーは不要です。" +tutorial.pipeline.notes: "{depthNone} は深度テストと書き込みを無効にし、深度アタッチメントのないパスと一致させます。" +tutorial.pipeline.reference: "{opaque} はブレンディングを無効にするため、三角形の内側ではフラグメントシェーダーの色が背景を置き換えます。" +tutorial.pipeline.title: シェーダーと頂点レイアウトを接続する +tutorial.pipeline.usage: シェーダーオブジェクトは、サンプルレンダラーのようにパイプラインを作成した後に破棄できます。パイプライン自体は、これを使用して描画するすべてのフレームで有効に保ってください。クリーンアップで {vertexBufferDispose} の前に {pipelineDispose} を追加します。パイプラインの作成は、描画コールバック前の最後の初期化ステップです。 +tutorial.pipeline.validation: パイプライン記述はアタッチメント構成を宣言するものであり、別の画像を作成するわけではありません。位置と色が 1 つのバッファーにまとめて格納されているため、{inputLayouts} には 1 つのエントリがあります。 +tutorial.presentation.title: GPU をウィンドウに接続する +tutorial.project.context: プロジェクトのビルド設定で {emphasis} ({allowUnsafeBlocks}) を有効にしてください。これは頂点データを GPU に渡す際や、ウィンドウヘルパーのネイティブ呼び出しに使用します。 +tutorial.project.context.emphasis: アンセーフコードの許可 +tutorial.project.description: "プロジェクトを作成し、そのディレクトリに移動します:" +tutorial.project.details: "パッケージをインストールします:" +tutorial.project.guidance: "{zenithNET} は共通のレンダリング API を提供します。3 つのバックエンドパッケージにより、同じプログラムがそのプラットフォームに適した実装を選択できます。{zenithNETCompiler} は、後で作成する小さな GPU プログラムである Slang シェーダーをその実装用にコンパイルします。Silk.NET はウィンドウとイベントループを提供します。" +tutorial.project.title: コンソールプロジェクトを作成する +tutorial.requirements.context: 空のプロジェクトからこのページに沿って進めることができます。ここで使用するレンダリング API とウィンドウ処理 API のリファレンスとして、{link} とその {detail} を参照できます。 +tutorial.requirements.context.detail: 共有ホスト +tutorial.requirements.context.link: Hello Triangle サンプル +tutorial.requirements.description: "{emphasis}、コードエディターまたは IDE、および Zenith.NET バックエンドでサポートされている GPU とドライバーを備えたデスクトップ環境が必要です。C# の基礎知識があれば十分です。グラフィックスの概念は使用する場面で説明します。これは通常の {net10} コンソールプロジェクトです。バックエンドは、Zenith.NET の操作を DirectX 12、Metal、Vulkan などのグラフィックス API の呼び出しに変換します。アプリケーションは起動時にそのうちの 1 つを選択します:" +tutorial.requirements.description.emphasis: .NET 10 SDK +tutorial.requirements.details: Linux では、ここで使用するウィンドウパスに X11 互換のウィンドウセッションが必要です。この三角形を描画するにあたり、オプションのレイトレーシングやメッシュシェーディング機能は不要です。 +tutorial.requirements.guidance: Zenith.NET は、アプリケーションが提供するサーフェスに描画します。Silk.NET.Windowing がデスクトップウィンドウを作成し、そのイベントを処理します。macOS では、プレゼンテーションターゲットは Metal レイヤー ({cAMetalLayerCs}) です。チュートリアルのウィンドウヘルパーがそのレイヤーを自動的に接続します。 +tutorial.requirements.table.headings.graphicsBackend: グラフィックスバックエンド +tutorial.requirements.table.headings.platform: プラットフォーム +tutorial.requirements.table.headings.windowSurface: ウィンドウサーフェス +tutorial.requirements.table.linux.graphicsBackend: Vulkan 1.4 +tutorial.requirements.table.linux.platform: Linux +tutorial.requirements.table.linux.windowSurface: X11 ウィンドウとディスプレイ (XWayland も使用可能) +tutorial.requirements.table.macOS.graphicsBackend: Metal 4 +tutorial.requirements.table.macOS.platform: macOS +tutorial.requirements.table.macOS.windowSurface: ウィンドウに接続された Metal レイヤー +tutorial.requirements.table.windows.graphicsBackend: DirectX 12 +tutorial.requirements.table.windows.platform: Windows +tutorial.requirements.table.windows.windowSurface: Win32 ウィンドウハンドル +tutorial.requirements.title: 始める前に +tutorial.resize.context: "{dotnetRun} を再度実行してください。ウィンドウは均一な暗い背景色になり、リサイズ後も塗りつぶされた状態が維持されるはずです。このコールバックは保持してください。三角形はこの既存のレンダーパス内で描画されます。" +tutorial.resize.description: "スワップチェーンの画像はフレームバッファーのサイズに従う必要があります。{framebufferResize} を使用して、ディスプレイのスケーリングによる変化を含め、ピクセルサイズの変化に対応します。描画コールバックの後、引き続き {windowRun} の前に次を追加します:" +tutorial.resize.details: Silk.NET はウィンドウサイズの変化と {link} を区別します。スワップチェーンはピクセルを格納するため、後者が必要です。最小化されたウィンドウではフレームバッファーのサイズがゼロになることがあります。その場合、両方のコールバックは GPU の処理をスキップします。リサイズ後、レンダーパスはそのビューポートとシザーに新しいアタッチメントサイズを使用します。 +tutorial.resize.details.link: フレームバッファーサイズの変化 +tutorial.resize.guidance: サブミットごとに待機するため、リサイズハンドラーが画像を置き換える際に、以前のフレームがその画像を使用していることはありません。現在の {present} 実装もグラフィックスキューで待機します。このシンプルなループにより、次のフレームが開始する前に 1 つのフレームの処理が確実に完了します。より高度なスケジューリングについては {link} で解説しています。 +tutorial.resize.guidance.link: 同期 +tutorial.resize.title: リサイズに対応する +tutorial.shaders.compilation.context: コンパイルは初期化中に 1 回だけ行われます。{appContextBaseDirectory} は現在の作業ディレクトリに関係なく、実行可能ファイルの横にあるコピーされたシェーダーを見つけます。これらのシェーダーは頂点入力のみを消費するため、定数バッファー、テクスチャ、リソースハンドルをバインドする必要はまだありません。 +tutorial.shaders.compilation.description: "{triangleSlang} のファイルプロパティで、{emphasis} を {detail} に設定します。これにより、シェーダーが実行可能ファイルの横で使用可能になります。" +tutorial.shaders.compilation.description.detail: 新しい場合はコピーする +tutorial.shaders.compilation.description.emphasis: 出力ディレクトリにコピー +tutorial.shaders.compilation.details: "{programCs} に戻ります。頂点アップロードの後、描画コールバックの前にこれらの初期化ステートメントを追加します:" +tutorial.shaders.compilation.guidance: "{zenithCompiler} は要求されたグラフィックス API 用のコードを含むシェーダー記述を返します。{createShader} は対応するバックエンドオブジェクトを作成します。グラフィックス API とエントリポイント名の両方が重要です。{contextGraphicsApi} を使用し、{vSMain} と {fSMain} は Slang ファイルと完全に同じスペルで指定してください。" +tutorial.shaders.compilation.title: 選択したバックエンド用にコンパイルする +tutorial.shaders.context: "{fSInput} は、頂点シェーダーの出力とフラグメントシェーダーの入力を接続します。頂点シェーダーによって書き込まれた場合、{sVPOSITION} はクリップ空間の位置を提供します。これは、GPU が可視画像の内側にあるものを判定するために使用する 4 つの座標です。{cOLOR0} は頂点間で補間する色を伝達します。2 つのステージはその型とセマンティクスで一致している必要があります。" +tutorial.shaders.description: シェーダーは GPU によって実行されるプログラムです。この描画には、頂点を配置する頂点シェーダーと、三角形の内側の色を生成するフラグメントシェーダーが必要です。これらをシェーダー言語である Slang で記述し、同じファイルから 2 つのエントリポイントをコンパイルします。エントリポイントとは、シェーダーステージの実行が開始される関数です。 +tutorial.shaders.details: "次の 2 つの構造体から始めて、{triangleSlang} を作成します:" +tutorial.shaders.fragment.description: "同じファイルにフラグメントエントリポイントを追加します:" +tutorial.shaders.fragment.details: ラスタライズによって、三角形がカバーする画像領域が決定されます。カバーされた領域全体にわたって頂点色が補間され、フラグメントシェーダーによって処理されるデータであるフラグメントが生成されます。{fSMain} は {sVTARGET} を介してこの補間された色を返します。これは最初のカラーアタッチメントを識別します。 +tutorial.shaders.fragment.guidance: 頂点色の補間はアタッチメントのブレンディングとは別個の処理です。ブレンディングは、フラグメントの出力とアタッチメントにすでに格納されている色を結合します。今回の不透明ブレンド状態はその結合を無効にするため、三角形の内側では補間された色が背景を置き換えます。 +tutorial.shaders.fragment.title: フラグメントを着色する +tutorial.shaders.guidance: "{vSInput} は、頂点シェーダーが頂点バッファーから受け取る内容を記述します。セマンティクス {pOSITION0} と {cOLOR0} が入力を識別します。C# のフィールド名だけではそのマッピングは確立されません。" +tutorial.shaders.title: 2 つのシェーダーステージを作成する +tutorial.shaders.vertex.description: "頂点エントリポイントを {triangleSlang} に追加します:" +tutorial.shaders.vertex.details: "GPU は入力頂点ごとにこのエントリポイントを呼び出します。位置に同次座標 {w} を加え、色を引き渡します。頂点ステージの後で位置は w で除算されますが、ここでは x、y、z は変化しません。そのため、上で選んだ位置を正規化デバイス座標として直接理解できます。" +tutorial.shaders.vertex.title: 各頂点を配置する +tutorial.surface.description: "コンテキストは、出力を表示する場所も認識する必要があります。以下を {emphasis} に追加します:" +tutorial.surface.description.emphasis: "{windowCenter} の後、{windowRun} の前" +tutorial.surface.details: "{surface} はネイティブプレゼンテーションターゲットとそのピクセルサイズを記述します。フレームバッファーは、ウィンドウに関連付けられたピクセル画像です。{framebufferSize} はそのピクセル単位のサイズを示します。ディスプレイのスケーリングが有効な場合、ウィンドウの論理サイズとは異なることがあります。" +tutorial.surface.guidance: サーフェスは上で選択したバックエンドと一致します。Windows はウィンドウハンドルを提供し、Linux は X11 ディスプレイとウィンドウを提供し、macOS ヘルパーは接続された Metal レイヤーを提供します。これはウィンドウをレンダリングに接続するための唯一のプラットフォーム固有の部分です。 +tutorial.surface.title: ネイティブサーフェスを記述する +tutorial.swapChain.context: "スワップチェーンはコンテキストとネイティブウィンドウの両方を使用します。{programCs} の末尾にある {windowDispose} の行を、次のクリーンアップ順序に置き換えます:" +tutorial.swapChain.description: "サーフェスの記述を使用して、表示される画像を作成します。サーフェスブロックの直後に以下を追加してください:" +tutorial.swapChain.details: "{swapChain} はウィンドウに表示される画像を管理します。各フレームで、{drawable} は画像データの API 型である {texture} として現在の画像を提供します。描画後、{present} は結果の表示を要求し、次の drawable へ進みます。" +tutorial.swapChain.guidance: "{b8G8R8A8UNorm} は、青、緑、赤、アルファの順序で 4 つの 8 ビットカラーチャンネルを格納します。{uNorm} は、0 から 255 の整数値が 0 から 1 の値を表すことを意味します。シェーダーは論理的な RGBA 値を返しますが、この形式によって画像内でのチャンネルの格納方法が決まります。後ほどグラフィックスパイプラインは {swapChainDescFormat} を使用してこのアタッチメントと一致させます。" +tutorial.swapChain.title: スワップチェーンを作成する +tutorial.title: 最初の三角形 +tutorial.troubleshooting.description: "まずコンソールでエラーを確認し、前のチェックポイントを使用して失敗したステージを特定します:" +tutorial.troubleshooting.details: "{link} と {detail} を使用して、頂点データ、入力レイアウト、描画操作を比較してください。そのサンプルではウィンドウ処理とサブミットを共有ホストに配置していますが、このチュートリアルではアプリケーションフローを {programCs} 内に保持しています。インデックス描画、変換、深度テストを学習するには、{context} に進んでください。" +tutorial.troubleshooting.details.context: 回転する立方体 +tutorial.troubleshooting.details.detail: Slang シェーダー +tutorial.troubleshooting.details.link: サンプルレンダラー +tutorial.troubleshooting.table.backend.check: 選択したバックエンドがデバイスおよびインストールされているグラフィックスドライバーでサポートされていることを確認してください。 +tutorial.troubleshooting.table.backend.symptom: バックエンドの作成に失敗する +tutorial.troubleshooting.table.drawing.check: アップロードサイズ、入力レイアウト、パイプラインの選択、およびレンダーパス内の描画コマンドの配置を確認してください。 +tutorial.troubleshooting.table.drawing.symptom: 背景は表示されるが三角形が表示されない +tutorial.troubleshooting.table.headings.check: 確認事項 +tutorial.troubleshooting.table.headings.symptom: 症状 +tutorial.troubleshooting.table.input.check: "28 バイトの ストライド と、0 および 12 の位置/色のオフセットを確認してください。" +tutorial.troubleshooting.table.input.symptom: 頂点の位置や色が破損している +tutorial.troubleshooting.table.shaders.check: コピーされた {triangleSlang}、エントリポイントのスペル、およびコンパイラが報告した診断情報を確認してください。 +tutorial.troubleshooting.table.shaders.symptom: クリア色のステップは機能するが、シェーダーの読み込みに失敗する +tutorial.troubleshooting.table.window.check: .NET プロジェクトがビルドされ、ウィンドウ単体のステップがデスクトップセッションで実行されることを確認してください。Linux では、X11 または XWayland が利用可能であることを確認してください。 +tutorial.troubleshooting.table.window.symptom: ウィンドウが開かない +tutorial.troubleshooting.title: 失敗したステージを確認する +tutorial.window.context: "{usingZenithTutorials} はヘルパーの名前空間をインポートします。各 C# ファイルは通常の using ディレクティブを使用するため、相互運用機能のインポートは両方のファイルで必要です。エイリアス {buffer} は Zenith.NET のバッファー型を指し、{systemBuffer} と区別します。" +tutorial.window.description: "{cocoaHelperCs} を名前空間を維持したままプロジェクトに追加します。そのファイルの先頭、名前空間宣言の前に {interopUsing} を追加してください。このヘルパーは macOS で Metal レイヤーをウィンドウに接続します。他のプラットフォームブランチではこれを呼び出しません。" +tutorial.window.details: "生成された {programCs} を次のコードに置き換えます。明示的な {main} メソッドなしで順番に実行される最上位レベルのステートメントを使用しています。以降のセクションで、この同じファイルにコードを追加する場所を説明します:" +tutorial.window.guidance: "{graphicsAPINone} は、Silk.NET に独自のグラフィックスコンテキストを持たないウィンドウを作成するよう要求します。そのコンテキストは Zenith.NET で作成します。{initialize} はネイティブウィンドウを作成し、そのハンドルを使用可能にします。ハンドルとは、ウィンドウシステムによって提供される識別子です。{center} はウィンドウを中央に配置し、{run} はウィンドウが閉じるまでイベントを処理します。その後、実行はウィンドウを解放する {dispose} に進みます。" +tutorial.window.notes: "{dotnetRun} を実行してください。空のウィンドウが開き、移動、サイズ変更、閉じる操作に応答するはずです。レンダリングコマンドをまだサブミットしていないため、内容はまだ定義されていません。確認したら閉じて次に進んでください。" +tutorial.window.title: ウィンドウを開く +ui.action.copy: コピー +ui.action.navigate: 移動 +ui.action.open: 開く +ui.action.source: ソースを表示 +ui.api.browse: 名前空間と型を参照します。 +ui.api.clearTypeSearch: 型の検索をクリア +ui.api.findType: 型を検索 +ui.api.loadError: 型を読み込めませんでした。このページを再読み込みしてやり直してください。 +ui.api.loadingNamespaces: 名前空間を読み込み中… +ui.api.loadingTypes: 型を読み込み中… +ui.api.matchingTypes: 一致する型 +ui.api.namespace: 名前空間 +ui.api.namespaces: 名前空間 +ui.api.noNamespaceTypes: この名前空間には型がありません。 +ui.api.noTypes: 一致する型はありません。 +ui.api.types: 型 +ui.content.reference: リファレンス +ui.content.source: ソースコード +ui.content.tutorial: チュートリアル +ui.contents.close: 目次を閉じる +ui.contents.open: 目次を開く +ui.contents.title: 目次 +ui.footer.caption: .NET 向けモダン RHI。 +ui.footer.label: フッター +ui.language.label: 言語 +ui.language.unavailable: 未翻訳 +ui.members.clear: メンバー検索をクリア +ui.members.close: メンバー検索を閉じる +ui.members.empty: 一致するメンバーはありません。 +ui.members.open: メンバーへ移動 +ui.members.placeholder: 名前またはシグネチャ… +ui.members.search: メンバーを検索 +ui.members.title: メンバーを検索 +ui.members.undeclared: この型には宣言されたメンバーがありません。 +ui.navigation.api: API +ui.navigation.concepts: 概念 +ui.navigation.home: ホーム +ui.navigation.label: メインナビゲーション +ui.navigation.toggle: ナビゲーションの切り替え +ui.outline.title: このページの内容 +ui.reference.assembly: アセンブリ +ui.reference.classes: クラス +ui.reference.constructors: コンストラクター +ui.reference.declaration: "C# 型宣言" +ui.reference.delegates: デリゲート +ui.reference.derived: 派生型 +ui.reference.enums: 列挙型 +ui.reference.events: イベント +ui.reference.examples: 例 +ui.reference.exceptions: 例外 +ui.reference.extensionMethods: 拡張メソッド +ui.reference.fields: フィールド +ui.reference.implementations: 明示的なインターフェイスの実装 +ui.reference.implements: 実装 +ui.reference.inheritance: 継承 +ui.reference.inheritedMembers: 継承されたメンバー +ui.reference.interfaces: インターフェイス +ui.reference.metadata: 型のメタデータ +ui.reference.methods: メソッド +ui.reference.namespace: 名前空間 +ui.reference.open: "{name} のリファレンスを開く" +ui.reference.operators: 演算子 +ui.reference.parameters: パラメーター +ui.reference.properties: プロパティ +ui.reference.related: 関連項目 +ui.reference.relationships: 継承とメタデータ +ui.reference.remarks: 注記 +ui.reference.returns: 戻り値 +ui.reference.structs: 構造体 +ui.reference.typeParameters: 型パラメーター +ui.reference.value: 値 +ui.reference.values: 値 +ui.search.close: 検索を閉じる +ui.search.empty: 「{query}」に一致する結果は見つかりませんでした。 +ui.search.hint: チュートリアル、概念、サンプル、API リファレンスを検索します。 +ui.search.loading: 検索を読み込み中… +ui.search.more: さらに結果を表示 +ui.search.pending: 検索中… +ui.search.placeholder: 何をお探しですか? +ui.search.resultCount: "検索結果: {count} 件" +ui.search.title: ドキュメントを検索 +ui.search.unavailable: 検索は利用できません。以下のページを直接開くことができます。 diff --git a/documents/locales/ko-KR/strings.yml b/documents/locales/ko-KR/strings.yml new file mode 100644 index 00000000..d93714ff --- /dev/null +++ b/documents/locales/ko-KR/strings.yml @@ -0,0 +1,604 @@ +### YamlMime:Resources +concepts.execution.context.description: "{graphicsContext}는 하나의 백엔드 장치를 나타내며 그래픽, 컴퓨팅 및 전송 큐를 제공합니다. 동일한 컨텍스트를 통해 워크로드에 대한 버퍼, 텍스처, 셰이더 및 파이프라인을 생성하세요. 다른 컨텍스트에서 생성된 리소스나 핸들은 이 컨텍스트의 명령 버퍼에 단순히 바인딩할 수 없습니다." +concepts.execution.context.details: 플랫폼 및 프레젠테이션 서피스에 적합한 백엔드를 선택하세요. API는 공유되지만 장치 지원 여부는 여전히 중요합니다. {capabilities}는 장치 이름과 {rayTracingSupported} 및 {meshShadingSupported} 플래그를 노출합니다. {link} 및 {detail} 샘플에서처럼 선택적 워크로드를 생성하기 전에 해당 플래그를 확인하세요. 이러한 플래그는 형식, 메모리 또는 플랫폼 제한 사항에 대한 완전한 목록이 아닙니다. +concepts.execution.context.details.detail: 메시 셰이딩 +concepts.execution.context.details.link: 레이 트레이싱 +concepts.execution.context.title: 컨텍스트는 리소스와 큐를 연결 +concepts.execution.description: Zenith.NET 애플리케이션은 GPU 리소스를 생성하고, 이를 사용하는 명령을 기록하며, 해당 명령을 큐에 제출합니다. GPU가 제출된 작업을 실행하는 동안 CPU는 작업을 계속할 수 있습니다. 기록 호출이 반환된 후에도 해당 작업이 완료될 때까지 리소스를 유효하게 유지하세요. +concepts.execution.ownership.description: "여기서 소유권은 해제에 대한 책임을 의미합니다. C# 참조는 관리되는 개체에 대한 도달 가능성을 유지하지만 명시적인 {dispose}가 네이티브 리소스를 파괴하는 것을 막지는 않습니다. 마찬가지로 버퍼를 사용하는 명령을 제출한다고 해서 해당 버퍼의 소유권이 큐로 이전되는 것은 아닙니다." +concepts.execution.ownership.details: "종료 시 새 작업 제출을 중지하고 관련된 모든 큐의 마지막 사용을 기다린 후 애플리케이션의 리소스를 해제한 다음 컨텍스트를 해제하세요. 컨텍스트를 해제하면 자체 큐와 내부 도우미가 해제되며, 모든 애플리케이션 작업을 기다리거나 애플리케이션이 생성한 모든 리소스를 해제하지는 않습니다." +concepts.execution.ownership.guidance: "렌더링 중에도 같은 수명 규칙을 적용하세요. 리소스의 마지막 사용에 대한 완료 값을 보관하여 데이터를 덮어쓰거나 리소스를 교체할 수 있는 시점을 판단하세요. 뷰와 기반 리소스의 수명은 {link}를 참고하세요." +concepts.execution.ownership.guidance.link: 리소스 관리 +concepts.execution.ownership.table.applicationResources.object: 애플리케이션이 생성한 리소스 +concepts.execution.ownership.table.applicationResources.ownership: 애플리케이션이 마지막 GPU 사용 후 해제합니다. +concepts.execution.ownership.table.commandBuffers.object: 대여한 명령 버퍼 +concepts.execution.ownership.table.commandBuffers.ownership: 큐가 관리하고 재활용합니다. +concepts.execution.ownership.table.headings.object: 개체 +concepts.execution.ownership.table.headings.ownership: 누가 해제하는가? +concepts.execution.ownership.table.queues.object: 컨텍스트 큐 및 해당 타임라인 +concepts.execution.ownership.table.queues.ownership: 컨텍스트와 큐가 관리합니다. +concepts.execution.ownership.table.swapChainDrawable.ownership: 스왑 체인이 관리합니다. +concepts.execution.ownership.title: 소유권과 GPU 완료를 구분하여 유지 +concepts.execution.pipelines.description: "그래픽 파이프라인은 셰이더, 정점 입력 레이아웃, 정점을 기본형으로 조립하는 규칙, 어태치먼트 형식과 렌더 상태를 결합합니다. 정점, 인덱스 또는 상수 데이터를 바인딩하고 드로잉 명령을 기록하기 전에 설정하세요. 어태치먼트 형식과 샘플 수는 렌더 패스의 어태치먼트와 일치해야 합니다." +concepts.execution.pipelines.details: 컴퓨팅 파이프라인은 GPU 스레드 그룹을 시작하는 디스패치용 셰이더 진입점을 제공합니다. 디스패치하기 전에 파이프라인과 해당 상수를 설정하세요. 컴퓨팅 디스패치는 그래픽 렌더 패스 외부에 속합니다. 파이프라인 변경은 후속 명령이 입력을 해석하는 방식의 변경을 의미하므로, 선택한 파이프라인에 필요한 데이터를 사용하기 전에 바인딩하세요. +concepts.execution.pipelines.guidance: "{link}는 전체 그래픽 시퀀스를 보여줍니다. {detail}는 디스패치를 기록한 다음 결과를 표시하는 그래픽 패스를 기록합니다." +concepts.execution.pipelines.guidance.detail: 컴퓨팅 샘플 +concepts.execution.pipelines.guidance.link: 삼각형의 렌더링 콜백 +concepts.execution.pipelines.title: 파이프라인이 명령의 데이터 해석 방식 결정 +concepts.execution.queues.description: 한 프레임에서 드로잉, 컴퓨팅 및 복사를 결합하는 경우 {graphicsQueue}로 시작하세요. 종속된 작업을 하나의 큐에 유지하면 순서를 파악하기가 더 쉬워집니다. +concepts.execution.queues.details: 큐는 실행을 위한 명령 배치를 수락합니다. 별도의 큐가 반드시 별도의 하드웨어 엔진에 해당하는 것은 아니므로 작업이 동시에 실행되지 않을 수도 있습니다. 워크로드가 중첩 실행의 이점을 얻을 수 있는 경우 다른 큐를 사용하고, 한 큐가 다른 큐의 결과를 소비할 때 명시적 종속성을 추가하세요. +concepts.execution.queues.guidance: 이후 명령이 이전 쓰기에 의존하는 경우, 애플리케이션은 해당 쓰기가 이후 명령에서 사용 가능한지 확인해야 합니다. 두 명령 버퍼를 동일한 큐에 제출한다고 해서 이러한 모든 종속성이 자동으로 설정되는 것은 아닙니다. 명령은 서로 다른 GPU 단계를 사용할 수 있으며, 이후 접근 시 배리어나 텍스처 전환이 필요할 수 있습니다. {link}에서 제출 순서와 리소스 가시성의 차이를 설명합니다. +concepts.execution.queues.guidance.link: 동기화 +concepts.execution.queues.table.computeQueue.workToRecord: 그래픽 렌더 패스를 제외한 컴퓨팅 디스패치 및 호환 가능한 전송 작업. +concepts.execution.queues.table.graphicsQueue.workToRecord: 렌더 패스 및 드로잉, 그리고 프레임에서 사용되는 컴퓨팅 및 전송 작업. +concepts.execution.queues.table.headings.queue: 큐 +concepts.execution.queues.table.headings.workToRecord: 기록할 작업 +concepts.execution.queues.table.transferQueue.workToRecord: 드로잉이나 컴퓨팅 디스패치를 제외한 업로드, 다운로드 및 복사 작업. +concepts.execution.queues.title: 실행할 작업에 맞는 큐 선택 +concepts.execution.recording.context: "큐는 완료를 폴링하고 완료된 명령 버퍼를 재활용합니다. 새로운 각 기록에 대해 {queueCommandBuffer}를 호출하세요. 재활용된 인스턴스가 반환될 수 있습니다. 대여한 명령 버퍼를 직접 해제하거나, 두 번 제출하거나, 제출 후에도 계속 기록하지 마세요. 지정된 명령 버퍼는 한 번에 하나의 스레드에서만 기록하세요. 큐의 내부 잠금은 명령 버퍼에 대한 동시 편집을 보호하지 않습니다." +concepts.execution.recording.description: "{queueCommandBuffer}는 기록이 이미 시작된 {commandBuffer}를 반환합니다. 명령과 해당 종속성을 기록한 다음 {submit}을 한 번 호출합니다. 제출하면 기록이 종료되고 해당 큐의 완료 지점을 식별하는 {timelineValue}가 반환됩니다." +concepts.execution.recording.details: "예를 들어, 프레임을 {commandBuffer}에 기록한 후 삼각형 튜토리얼은 이를 제출하고 다음과 같이 완료를 기다립니다:" +concepts.execution.recording.guidance: "{submit}은 작업을 예약하고, {wait}는 해당 제출이 완료될 때까지 CPU가 계속 진행되지 않도록 유지합니다. 드로잉 기록, 렌더 패스 종료 및 명령 버퍼 제출은 별개의 작업입니다. 드로잉을 기록하거나 패스를 종료하는 작업 모두 GPU를 기다리지 않습니다." +concepts.execution.recording.title: 기록은 명령을 실행하지 않음 +concepts.execution.title: 실행 모델 +concepts.platforms.description: 애플리케이션이 네이티브 윈도우와 프레임 루프를 소유할지 아니면 UI 렌더링 컨트롤을 사용할지 선택하세요. 이 선택에 따라 출력 텍스처를 얻고, 명령을 제출하며, 결과를 표시하는 주체가 결정됩니다. 출력 텍스처는 현재 프레임의 출력으로 사용되는 텍스처입니다. 오프스크린 그래픽 및 컴퓨팅 작업에는 윈도우나 스왑 체인이 필요하지 않습니다. +concepts.platforms.frame.context: "해당 패스 내에 파이프라인 바인딩과 드로잉 명령을 추가하세요. 반환하기 전에 패스를 종료합니다. 제공된 명령 버퍼를 독립적으로 제출하거나 별도로 표시하지 마세요. 또한 명령 버퍼나 출력 텍스처를 해제하지 마세요. 핸들러가 다른 레이아웃에서 출력 텍스처를 사용하는 경우 컨트롤의 최종 전환을 위해 {colorAttachment}로 되돌립니다." +concepts.platforms.frame.description: 통합 기능은 {iZenithView}를 구현합니다. 애플리케이션은 {graphicsContext}를 제공하고, {updateRequested}에서 장면 데이터를 업데이트하며, {renderEventArgs}를 사용하여 {renderRequested}에서 렌더링을 기록합니다. +concepts.platforms.frame.details: "컨트롤은 각 프레임의 전체 흐름을 관리합니다. 출력 텍스처와 명령 버퍼를 가져오고, 출력 텍스처를 {colorAttachment}로 전환한 뒤 핸들러를 호출합니다. 이후 프레임워크에 필요한 제출과 프레젠테이션 단계를 수행합니다." +concepts.platforms.frame.guidance: "컨텍스트가 할당된 {view}라는 초기화된 {iZenithView}의 경우, 이 핸들러는 완전한 클리어 패스를 기록합니다. {usingZenithNET}이 필요합니다:" +concepts.platforms.frame.notes: 컨트롤은 각 프레임 시작 시 {undefined}에서 전환하므로 애플리케이션은 출력 텍스처의 이전 내용이 보존되는 것에 의존할 수 없습니다. 각 프레임마다 필요한 이미지를 지우거나 렌더링하세요. 지속적인 누적이나 캐시된 렌더링은 애플리케이션 소유의 텍스처에 유지한 다음 뷰를 통해 해당 텍스처를 표시하세요. +concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat}은 통합의 기본 색상 형식을 제공합니다. 어태치먼트 형식, 샘플 수 및 치수를 일치시킬 때 실제 이벤트의 출력 텍스처를 확인하세요." +concepts.platforms.frame.title: UI 컨트롤이 제공하는 프레임에 기록 +concepts.platforms.integration.context: WinForms, WPF 및 Windows WinUI 경로는 Windows가 필요합니다. MAUI 애플리케이션에는 대상 플랫폼의 워크로드가 필요하며 {useZenithView}로 컨트롤 핸들러를 등록해야 합니다. {extensionsCs}를 참조하세요. 프레임워크 지원과 백엔드 지원이 모두 충족되어야 합니다. +concepts.platforms.integration.description: "컨트롤은 이벤트 인터페이스를 공유하지만 모두 동일한 방식으로 표시되지는 않습니다:" +concepts.platforms.integration.details: 비트맵 리드백(bitmap readback)은 UI가 표시하기 전에 렌더링된 픽셀을 CPU 메모리에 복사합니다. 공유 텍스처 상호 운용성은 해당 리드백을 방지하지만 여전히 GPU 복사 및 동기화가 필요할 수 있습니다. 따라서 공유 {renderRequested} 인터페이스가 동일한 프레젠테이션 비용이나 네이티브 상호 운용성 요구 사항을 의미하지는 않습니다. +concepts.platforms.integration.guidance: "애플리케이션 프레임워크에 맞는 패키지를 사용하세요. 예:" +concepts.platforms.integration.table.avalonia.integration: Avalonia +concepts.platforms.integration.table.avalonia.presentation: 텍스처에 렌더링하고 픽셀을 {writeableBitmap}으로 다운로드합니다. {zenithViewCs} 및 {surfaceCs}를 참조하세요. +concepts.platforms.integration.table.headings.integration: 통합 +concepts.platforms.integration.table.headings.presentation: 이미지가 UI에 도달하는 방식 +concepts.platforms.integration.table.maui.integration: .NET MAUI +concepts.platforms.integration.table.maui.presentation: Android, iOS 및 Mac Catalyst에서는 네이티브 서피스를 사용하고 Windows에서는 공유 텍스처 구성을 사용합니다. {link}를 참조하세요. +concepts.platforms.integration.table.maui.presentation.link: 플랫폼 구현 +concepts.platforms.integration.table.uno.integration: Uno 경로 +concepts.platforms.integration.table.uno.presentation: 픽셀을 {writeableBitmap}으로 다운로드합니다. {zenithViewUnoCs}를 참조하세요. +concepts.platforms.integration.table.winForms.integration: WinForms +concepts.platforms.integration.table.winForms.presentation: 컨트롤의 {hWND}에 대한 Zenith.NET 스왑 체인을 생성합니다. {zenithViewCs}를 참조하세요. +concepts.platforms.integration.table.winUI.integration: Windows의 WinUI +concepts.platforms.integration.table.winUI.presentation: 가져온 공유 Direct3D 11 텍스처에 렌더링한 다음 {swapChainPanel}에 연결된 구성 스왑 체인에 복사합니다. {zenithViewWinUICs}를 참조하세요. +concepts.platforms.integration.table.wpf.integration: WPF +concepts.platforms.integration.table.wpf.presentation: 공유 Direct3D 11 텍스처를 가져온 다음 Direct3D 상호 운용성을 통해 {d3DImage}로 표시되는 서피스에 복사합니다. {surfaceCs}를 참조하세요. +concepts.platforms.integration.title: 프레임워크뿐만 아니라 프레젠테이션 경로도 선택 +concepts.platforms.lifecycle.context: UI 뷰의 경우 일치하는 렌더링 리소스를 생성할 때 이벤트 출력 텍스처의 {descWidth}, {descHeight}, {descFormat} 및 {descSampleCount}를 사용하세요. 컨트롤이 해당 출력 텍스처의 해상도를 결정합니다. 논리적 치수나 디스플레이 배율이 항상 텍스처 치수와 같다고 가정하지 마세요. +concepts.platforms.lifecycle.description: 네이티브 스왑 체인의 경우 프레임버퍼 치수를 픽셀 단위로 전달하세요. 디스플레이 배율이 활성화된 경우 논리 단위로 표현된 윈도우 크기와 다를 수 있습니다. 크기가 0인 프레임버퍼는 건너뛰고, 픽셀 크기가 변경되면 스왑 체인의 크기를 조정하며, 각 프레임마다 {swapChainDrawable}을 가져옵니다. 출력 텍스처는 스왑 체인이 소유하며 프레젠테이션 또는 크기 조정 후에 변경될 수 있습니다. +concepts.platforms.lifecycle.details: "{swapChainResize}는 기존 서피스의 크기를 변경합니다. {swapChainRefresh}는 네이티브 핸들을 포함하여 서피스 설명을 대체합니다. 두 작업 중 하나를 수행하기 전에 영향을 받는 리소스의 미해결 사용을 완료하세요. 네이티브 프레젠테이션 대상을 해제하기 전에 스왑 체인을 해제하세요." +concepts.platforms.lifecycle.guidance: 윈도우 크기를 따르는 애플리케이션 소유의 깊이 또는 오프스크린 텍스처를 다시 생성하고 해당 핸들이 포함된 상수를 업데이트하세요. 파이프라인은 어태치먼트 형식과 샘플 수가 호환되는 한 크기 변경 후에도 계속 사용할 수 있습니다. {link}는 깊이 텍스처를 교체하면서 파이프라인을 유지합니다. +concepts.platforms.lifecycle.guidance.link: 회전하는 큐브 렌더러 +concepts.platforms.lifecycle.title: 출력 텍스처의 크기와 수명을 호스트와 함께 유지 +concepts.platforms.ownership.description: 애플리케이션은 할당한 컨텍스트와 렌더링을 위해 생성한 리소스를 소유합니다. 컨트롤은 자체 프레젠테이션 리소스를 소유합니다. 뷰의 {graphicsContext} 속성을 변경하면 스케줄러가 컨트롤의 리소스를 다시 생성하지만, 새 컨텍스트를 위해 애플리케이션의 파이프라인, 버퍼 또는 텍스처를 다시 생성하지는 않습니다. +concepts.platforms.ownership.details: "리소스 교체를 뷰의 프레임 수명 주기와 조정하세요. 애플리케이션 리소스 또는 할당된 컨텍스트를 해제하기 전에 뷰의 프레임 활동을 중지하고 미해결 GPU 사용을 완료하세요. 뷰를 제거한다고 해서 컨텍스트 소유권이 컨트롤로 이전되는 것은 아닙니다." +concepts.platforms.ownership.guidance: 공유 {frameSchedulerCs}는 뷰의 UI 디스패처를 통해 프레임 작업을 디스패치합니다. 프레임 핸들러가 프레임 업데이트 및 기록에 집중하도록 유지하세요. 장시간의 CPU 작업은 UI를 지연시킵니다. +concepts.platforms.ownership.title: 애플리케이션 리소스를 컨트롤 소유권 외부에 유지 +concepts.platforms.surface.context: 윈도우 라이브러리나 UI 프레임워크가 운영 체제를 지원한다고 해서 선택한 GPU 백엔드를 해당 환경에서 사용할 수 있다는 보장은 없습니다. 장치 기능, 드라이버 및 네이티브 서피스 지원이 여전히 일치해야 합니다. 해당 워크로드를 생성하기 전에 {contextCapabilities}를 통해 선택적 레이 트레이싱 및 메시 셰이딩을 확인하세요. +concepts.platforms.surface.description: "{link}는 Silk.NET을 사용하여 윈도우를 생성하고 이벤트를 처리합니다. Zenith.NET은 {surface} 설명과 {swapChain}을 통해 해당 윈도우에 연결됩니다. 서피스에는 네이티브 핸들과 치수가 포함됩니다. 설명을 구성한다고 해서 운영 체제 윈도우가 생성되거나 소유되는 것은 아닙니다." +concepts.platforms.surface.description.link: 삼각형 튜토리얼 +concepts.platforms.surface.details: "핸들은 선택한 백엔드와 일치해야 합니다:" +concepts.platforms.surface.guidance: 튜토리얼의 {appCs}는 Windows, macOS 및 X11 선택 항목을 보여줍니다. Linux 호스트는 Xlib 핸들을 제공하므로 Wayland 세션에서 사용하려면 XWayland가 필요합니다. 네이티브 Wayland 애플리케이션은 {surfaceWayland}를 통해 다른 핸들을 제공합니다. +concepts.platforms.surface.table.android.backend: Android의 Vulkan. +concepts.platforms.surface.table.apple.backend: Apple 플랫폼의 Metal. +concepts.platforms.surface.table.headings.backend: 백엔드 경로 +concepts.platforms.surface.table.headings.factory: 서피스 팩토리 +concepts.platforms.surface.table.headings.handles: 호스트에서 제공하는 핸들 +concepts.platforms.surface.table.wayland.backend: 네이티브 Wayland 호스트를 사용하는 Vulkan. +concepts.platforms.surface.table.wayland.handles: Wayland 디스플레이 및 서피스 +concepts.platforms.surface.table.win32.backend: Windows의 DirectX 12 또는 Vulkan. +concepts.platforms.surface.table.xlib.backend: X11 또는 XWayland를 사용하는 Linux의 Vulkan. +concepts.platforms.surface.table.xlib.handles: X11 디스플레이 및 윈도우 +concepts.platforms.surface.title: 애플리케이션이 프레젠테이션을 소유할 때 네이티브 서피스 제공 +concepts.platforms.title: 플랫폼 통합 +concepts.resources.allocation.context: "자체 메모리 할당기가 필요한 경우가 아니라면 컨텍스트에서 생성한 리소스부터 사용하세요. 힙을 사용할 때는 해당 리소스를 사용하는 모든 GPU 작업이 완료된 후 배치된 리소스를 먼저 해제하고, 마지막으로 힙 자체를 해제하세요." +concepts.resources.allocation.description: "{heap}은 명시적인 바이트 오프셋에 리소스를 배치할 메모리를 제공합니다. 애플리케이션이 오프셋을 선택하고 사용 중인 영역을 추적합니다." +concepts.resources.allocation.details: "리소스를 배치하기 전에 정확한 버퍼 또는 텍스처 설명을 사용해 {contextGetSizeAndAlignment}를 호출하세요. 반환된 정렬 값의 배수인 오프셋을 선택하고, 반환된 크기만큼 공간을 확보하며, 리소스가 힙의 전체 바이트 범위 안에 있도록 하세요. 사용 중인 할당 영역은 겹치면 안 됩니다. 텍스처 저장 공간에는 백엔드별 패딩과 정렬이 포함될 수 있으므로 픽셀 수에 픽셀당 바이트 수를 곱한 값으로 할당 크기를 계산할 수는 없습니다." +concepts.resources.allocation.guidance: "배치된 버퍼의 상주 특성은 힙의 상주 특성과 일치시켜야 합니다. 여기서 설명하는 일반 GPU 텍스처에는 GPU 전용 힙을 사용하세요. 크기와 정렬은 배치 요구 사항이며, 모든 백엔드에서 임의의 리소스를 임의의 힙에 배치할 수 있다는 보장은 아닙니다." +concepts.resources.allocation.title: 할당 제어가 필요한 경우 힙에 리소스 배치 +concepts.resources.bufferUsages.table.constant.role: 상수 버퍼 바인딩을 통해 읽는 셰이더 매개 변수. +concepts.resources.bufferUsages.table.headings.role: "역할" +concepts.resources.bufferUsages.table.headings.usage: 용도 +concepts.resources.bufferUsages.table.index.role: 인덱스 드로잉에 사용되는 인덱스. +concepts.resources.bufferUsages.table.indirect.role: "간접 드로잉 또는 디스패치 명령이 읽는 인수." +concepts.resources.bufferUsages.table.none.role: "버퍼 용도 플래그를 선언하지 않음." +concepts.resources.bufferUsages.table.storageReadOnly.role: "읽기 전용 셰이더 바인딩으로 접근하는 버퍼 데이터." +concepts.resources.bufferUsages.table.storageReadWrite.role: "읽기 및 쓰기 셰이더 바인딩으로 접근하는 버퍼 데이터." +concepts.resources.bufferUsages.table.transferDst.role: "GPU 복사의 대상 저장 공간." +concepts.resources.bufferUsages.table.transferSrc.role: "GPU 복사의 원본 데이터." +concepts.resources.bufferUsages.table.vertex.role: 드로잉을 위해 가져오는 정점 속성. +concepts.resources.bufferUsages.title: 버퍼 용도 +concepts.resources.description: "리소스를 사용할 작업에 맞춰 리소스 설명을 선택하세요. 렌더링 대상으로 쓰고, 셰이더에서 샘플링하고, CPU로 읽어 올 텍스처라면 세 가지 용도를 모두 선언하고 작업 사이의 동기화도 처리해야 합니다. 메모리 배치와 리소스 수명은 별도로 결정할 사항입니다." +concepts.resources.memory.context: CPU 접근 가능한 버퍼의 경우 {map}은 CPU에 주소를 제공합니다. GPU가 동일한 바이트에 대한 접근을 중지할 때까지 기다리지 않습니다. {unmap} 역시 작업을 제출하거나 완료를 기다리지 않습니다. CPU 쓰기 가능 데이터를 덮어쓰기 전에 이전 내용이 여전히 필요한 GPU 읽기를 완료하세요. +concepts.resources.memory.description: "{bufferDesc}에는 {residency} 필드가 있습니다. CPU와 GPU가 데이터에 접근하는 방식에 따라 선택하세요:" +concepts.resources.memory.details: 상주 특성은 할당에 대한 의도된 CPU 접근을 설명합니다. 이는 모든 장치가 물리적으로 분리된 CPU 및 GPU 메모리를 갖는다는 것을 의미하지는 않습니다. 삼각형 튜토리얼은 작은 정점 버퍼를 직접 초기화하기 위해 {cpuWriteOnly}를 사용합니다. 대규모 정적 메시는 일회성 업로드를 포함하는 GPU 전용 스토리지의 이점을 얻을 수 있습니다. +concepts.resources.memory.guidance: "{textureDesc}에는 상주 필드가 없습니다. 일반적인 컨텍스트 생성 텍스처는 GPU 스토리지를 사용합니다. 해당 공개 API는 직접 매핑 메서드를 노출하지 않고 CPU 데이터 전송을 위한 업로드 및 다운로드 작업을 제공합니다. 명시적 힙은 아래에 설명된 배치 제어를 제공합니다." +concepts.resources.memory.table.cpuReadOnly.cPUAccess: "GPU 복사가 끝난 후 매핑된 메모리를 읽음." +concepts.resources.memory.table.cpuReadOnly.typicalRole: "GPU가 생성한 리드백 데이터" +concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "이전 GPU 읽기가 끝난 후 매핑된 메모리에 씀." +concepts.resources.memory.table.cpuWriteOnly.typicalRole: "CPU가 제공하거나 갱신하는 데이터" +concepts.resources.memory.table.gpuOnly.cPUAccess: "업로드 또는 리드백 버퍼를 통해 바이트를 전송함." +concepts.resources.memory.table.gpuOnly.typicalRole: "정적 지오메트리와 GPU 작업 데이터" +concepts.resources.memory.table.headings.cPUAccess: CPU 접근 +concepts.resources.memory.table.headings.residency: 상주 특성 +concepts.resources.memory.table.headings.typicalRole: 일반적인 역할 +concepts.resources.memory.title: "필요한 CPU 접근 방식에 맞춰 메모리 선택" +concepts.resources.textureUsages.description: "전송 용도 플래그는 GPU 복사의 방향을 나타냅니다. CPU 접근은 이와 별개인 메모리 배치 선택 사항이며 아래에서 설명합니다." +concepts.resources.textureUsages.details: "용도 플래그를 조합하면 여러 역할을 선언할 수 있지만, 작업을 실행하거나 접근 순서를 지정하지는 않습니다. 텍스처에는 여전히 적절한 {link}가 필요하며, 선택한 장치에서 해당 포맷이 요청한 용도를 지원해야 합니다." +concepts.resources.textureUsages.details.link: "레이아웃과 동기화" +concepts.resources.textureUsages.table.colorAttachment.role: "렌더 패스의 색상 어태치먼트." +concepts.resources.textureUsages.table.depthStencilAttachment.role: "렌더 패스의 깊이/스텐실 어태치먼트." +concepts.resources.textureUsages.table.headings.role: "역할" +concepts.resources.textureUsages.table.headings.usage: 용도 +concepts.resources.textureUsages.table.none.role: "텍스처 용도 플래그를 선언하지 않음." +concepts.resources.textureUsages.table.sampled.role: "샘플링 텍스처 바인딩을 통해 읽는 텍스처 데이터." +concepts.resources.textureUsages.table.storage.role: "스토리지 텍스처 바인딩을 통해 셰이더가 읽거나 쓰는 텍스처 데이터." +concepts.resources.textureUsages.table.transferDst.role: "GPU 복사의 대상 이미지 저장 공간." +concepts.resources.textureUsages.table.transferSrc.role: "GPU 복사의 원본 이미지 데이터." +concepts.resources.textureUsages.title: 텍스처 용도 +concepts.resources.title: 리소스 관리 +concepts.resources.transfers.context: 다운로드는 내부 리드백 스토리지에 GPU 복사를 기록합니다. 라이브러리는 재사용을 위해 완료된 명령 버퍼를 재설정할 때 해당 바이트를 제공된 CPU 대상으로 복사합니다. 제출 값의 {wait}가 반환될 때까지 대상을 할당된 상태로 유지하고 관리 메모리를 고정된 상태로 유지하세요. +concepts.resources.transfers.description: "업로드는 CPU 데이터를 GPU 리소스로 복사하고, 다운로드는 리소스 데이터를 CPU 메모리로 복사합니다. 리소스 자체가 제공하는 메서드는 해당 전송을 완료한 뒤 반환합니다." +concepts.resources.transfers.details: "이러한 대기는 해당 메서드가 제출한 전송만 대상으로 합니다. 다른 큐에서 이미 리소스를 읽거나 쓰고 있던 작업과의 종속성은 찾아내지 않습니다. 리소스의 전송 메서드를 호출하기 전에 종속성을 설정하세요. 매핑된 메모리를 통한 직접 복사도 호출자가 관련 GPU 작업의 완료를 보장해야 합니다." +concepts.resources.transfers.guidance: "복사를 다른 작업과 함께 기록해야 하는 경우 {commandBufferUpload} 또는 {commandBufferDownload}를 사용하세요. 포인터 수명은 서로 다릅니다:" +concepts.resources.transfers.item: "업로드는 호출 중에 CPU 원본 데이터를 내부 업로드 버퍼인 스테이징 메모리로 복사합니다. 원본 포인터는 해당 호출이 진행되는 동안만 유효하면 됩니다." +concepts.resources.transfers.notes: "텍스처의 행 스트라이드는 CPU 데이터의 연속된 두 행 사이의 바이트 거리이며, 슬라이스 스트라이드는 연속된 깊이 슬라이스 사이의 바이트 거리입니다. 이 값은 텍스처 내부의 GPU 메모리 레이아웃이 아닙니다. GPU 완료와 리드백의 차이는 {link}를 참고하세요." +concepts.resources.transfers.notes.link: 동기화 +concepts.resources.transfers.table.bufferDownload.transfer: "{cpuReadOnly}의 경우 직접 CPU 복사, 그렇지 않으면 전송 큐 다운로드를 제출하고 대기." +concepts.resources.transfers.table.bufferUpload.transfer: "{cpuWriteOnly}의 경우 직접 CPU 복사, 그렇지 않으면 전송 큐 업로드를 제출하고 대기." +concepts.resources.transfers.table.headings.method: 방법 +concepts.resources.transfers.table.headings.transfer: "데이터 전송 방식" +concepts.resources.transfers.table.textureTransfers.method: "{textureUpload} / {textureDownload}" +concepts.resources.transfers.table.textureTransfers.transfer: "그래픽스 큐를 사용하여 선택한 하위 리소스를 복사용 레이아웃으로 전환하고, 복사 후 요청한 최종 레이아웃으로 전환한 다음 전송 완료를 기다림." +concepts.resources.transfers.title: "즉시 완료하는 전송과 명령에 기록하는 전송 중 선택" +concepts.resources.usages.description: "{bufferUsages} 및 {textureUsages}는 리소스의 의도된 역할을 선언하는 플래그 열거형입니다. 각각 {bufferDescUsages} 및 {textureDescUsages}에 할당됩니다. 플래그 열거형을 사용하면 리소스에 둘 이상의 역할이 있을 때 {value}를 사용하여 여러 멤버를 결합할 수 있습니다." +concepts.resources.usages.title: 리소스를 생성하기 전에 필요한 용도 선언 +concepts.resources.views.description: "{bufferView}는 버퍼 영역과 그 해석을 설명합니다. {textureView}는 호환 가능한 텍스처 형식, 포맷 및 하위 리소스 범위를 선택합니다. 뷰는 기본 스토리지를 공유하며 데이터를 복사하거나 리소스 생성 시 누락된 용도를 추가하지 않습니다. 해당 범위는 셰이더 경계 검사의 이식 가능한 보장이 아닙니다." +concepts.resources.views.details: "기본 뷰에는 리소스 자체의 핸들을 사용하고, 다른 영역이나 호환되는 다른 해석이 필요하면 뷰를 생성하세요. GPU 작업이 뷰와 기본 리소스를 사용할 수 있는 동안 두 객체에 대한 C# 참조를 유지하세요. 리소스 핸들만으로는 어느 객체의 수명도 유지되지 않습니다. 마지막 GPU 사용이 완료된 뒤에만 해제하세요. 둘 중 하나를 교체하면 이전 {link}을 포함하는 상수도 갱신하세요." +concepts.resources.views.details.link: "리소스 핸들" +concepts.resources.views.guidance: "{link}는 크기 조정 시 교체되는 깊이 텍스처를 보여줍니다. {detail}는 쓰기 가능한 출력과 분리되어 유지되는 입력 텍스처를 보여줍니다. 둘 다 리소스 수명이 실제로 이를 사용하는 작업을 따르도록 합니다." +concepts.resources.views.guidance.detail: 컴퓨팅 샘플 +concepts.resources.views.guidance.link: 회전하는 큐브 렌더러 +concepts.resources.views.title: "뷰와 기본 리소스를 함께 사용 가능한 상태로 유지" +concepts.shaders.binding.context: "컴퓨팅 샘플에서 {input}은 {inputTextureSampledHandle}로 채워지고 {output}은 {outputTextureStorageHandle}로 채워집니다. Slang의 형식화된 {descriptorHandle}은 각 리소스에 접근하는 방법을 셰이더에 알려줍니다:" +concepts.shaders.binding.description: "{setConstantBuffer}는 현재 파이프라인의 상수 데이터에 사용할 버퍼와 바이트 오프셋을 바인딩합니다. 기존 GPU 가시적 저장 공간을 바인딩할 뿐 C# 값을 업로드하지는 않습니다. 버퍼를 먼저 채우고, 그 바이트를 덮어쓰기 전에 이전 GPU 읽기 작업이 완료되었는지 확인하세요." +concepts.shaders.binding.details: "상수 버퍼 앞에 파이프라인을 설정하세요. 리소스가 이미 생성되고 업로드된 컴퓨팅 워크로드의 경우 기록 시 다음 순서를 사용합니다:" +concepts.shaders.binding.guidance: 이 조각은 기록 중인 {commandBuffer}, {computePipeline}, {bufferUsagesConstant} 용도로 업로드된 {constantBuffer} 및 워크로드의 스레드 그룹 수를 전제로 합니다. 오프셋 0은 버퍼의 시작을 바인딩합니다. 여러 상수 데이터 레코드가 하나의 버퍼를 공유하는 경우 각 레코드의 시작 오프셋은 백엔드의 바인딩 정렬을 충족해야 합니다. 이 요구 사항은 레코드 내부의 필드 레이아웃과 별개입니다. +concepts.shaders.binding.notes: "{resourceHandle}은 두 개의 32비트 필드를 저장하지만 그 해석은 백엔드에 속합니다. 이를 컨텍스트 간에 전송할 수 있는 범용 설명자 인덱스, 주소 또는 값으로 취급하지 마세요. 핸들은 리소스를 생성하거나 누락된 용도를 추가하거나 동기화를 수행하지 않습니다." +concepts.shaders.binding.reference: "리소스 및 핸들을 얻는 데 사용된 모든 뷰에 대한 참조를 유지하고 셰이더의 마지막 사용이 완료된 후에만 해제하세요. 텍스처나 뷰를 교체할 때 이전 핸들이 포함된 상수를 업데이트하세요. {link}에서 해당 수명 관계를 설명합니다." +concepts.shaders.binding.reference.link: 리소스 관리 +concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: 셰이더 형식 {t}의 구조화된 요소를 읽습니다. +concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: 셰이더 형식 {t}의 구조화된 요소를 읽거나 씁니다. +concepts.shaders.binding.table.headings.access: 의도된 접근 +concepts.shaders.binding.table.headings.cHandle: "C# 핸들" +concepts.shaders.binding.table.headings.slangFieldType: Slang 필드 형식 +concepts.shaders.binding.table.samplerHandle.access: 텍스처 샘플링 상태를 제공합니다. +concepts.shaders.binding.table.textureSampledHandle.access: 텍스처를 읽습니다. +concepts.shaders.binding.table.textureStorageHandle.access: 스토리지 텍스처를 읽거나 씁니다. +concepts.shaders.binding.title: 상수 버퍼 및 해당 버퍼가 설명하는 리소스 바인딩 +concepts.shaders.compilation.description: "{zenithCompiler}는 명명된 Slang 진입점을 컴파일하고 {shaderDesc}를 반환합니다. 결과가 셰이더를 생성할 백엔드(DirectX 12의 경우 DXIL, Metal의 경우 Metal 라이브러리, Vulkan의 경우 SPIR-V)를 대상으로 하도록 컨텍스트의 {graphicsApi}를 사용하세요." +concepts.shaders.compilation.details: "예를 들어 기존 {context}가 있고 삼각형 셰이더가 실행 파일 옆에 복사된 경우:" +concepts.shaders.compilation.guidance: "{vSMain}은 셰이더 파일의 진입점 이름과 정확히 일치해야 합니다. 파이프라인을 생성하는 동안 셰이더 개체를 유효하게 유지한 다음, {link}에 표시된 대로 파이프라인 생성 후에 해제하세요. 매 프레임마다 다시 컴파일하는 대신 이 초기화를 한 번 수행하세요." +concepts.shaders.compilation.guidance.link: 첫 번째 삼각형 +concepts.shaders.compilation.title: 선택한 컨텍스트를 위한 진입점 컴파일 +concepts.shaders.description: "셰이더는 애플리케이션에서 제공하는 데이터를 수신합니다. 정점 속성은 개별 정점을 설명하고, 버퍼는 매개 변수나 배열을 보유하며, 리소스 핸들은 셰이더가 접근할 다른 리소스를 식별합니다. C# 선언과 Slang 선언은 해당 값이 의미하는 바에 대해 일치해야 합니다. 필드 이름을 일치시키는 것만으로는 충분하지 않으며 레이아웃, 리소스 접근 및 바인딩이 모두 일치해야 합니다." +concepts.shaders.dispatch.description: "{dispatch}는 스레드 그룹 수를 받습니다. 컴퓨팅 샘플의 {numthreads} 진입점은 그룹당 16 × 16개의 스레드를 실행합니다. 이미지 치수를 16으로 나누고 올림하여 그룹 수를 계산합니다. 예를 들어 17 × 19 이미지는 2 × 2 그룹이 필요합니다. 마지막 그룹에는 이미지 외부의 스레드가 포함될 수 있으므로 셰이더는 픽셀 좌표를 이미지 크기와 비교하여 검사합니다." +concepts.shaders.dispatch.details: 컴파일러는 진입점의 선언된 그룹 크기를 {shaderDescThreadGroupSize}에 저장하며 {dispatch}에 제공된 픽셀 치수를 그룹 수로 변환하지 않습니다. 완전한 바인딩 및 디스패치 예제에는 셰이더와 함께 {computeShaderRendererCs}를 사용하고 다른 패스가 출력을 사용하기 전에 {link}를 사용하세요. +concepts.shaders.dispatch.details.link: 동기화 +concepts.shaders.dispatch.title: 픽셀이 아닌 스레드 그룹 디스패치 +concepts.shaders.layout.context: "{link}는 해당 오프셋을 명시적으로 표시합니다. 이 선언에는 범위 내에 {systemRuntimeInteropServices} 및 {zenithNET}이 필요합니다:" +concepts.shaders.layout.context.link: "컴퓨팅 샘플의 C# 상수" +concepts.shaders.layout.description: "정점 입력의 경우 파이프라인의 {inputLayout}은 형식, 오프셋, 스트라이드 및 의미 체계를 설명합니다. 삼각형의 {float3} 위치 뒤에 오는 {float4} 색상은 28바이트를 차지하며 바이트 12에 색상이 있습니다. {inputLayoutAdd}는 이 패킹된 레이아웃을 계산하며 C# 구조체를 검사하지 않습니다. C# 필드에 패딩이 포함된 경우 필드가 패킹되어 있다고 가정하지 말고 일치하는 레이아웃을 제공하세요." +concepts.shaders.layout.details: "상수 버퍼는 셰이더 매개 변수를 보유하는 반면, 구조화된 버퍼는 선언된 형식의 요소 배열을 보유합니다. 둘 다 Slang 선언에 따라 읽힙니다. {inputLayout}을 사용하지 않습니다. 패딩을 포함하여 컴파일된 셰이더 표현에 대한 필드 오프셋과 요소 크기를 확인하세요. 관리되지 않는 C# 형식은 바이트 단위로 복사하기에 적합하지만 그것만으로는 셰이더 형식과 일치함을 입증할 수 없습니다. 특히 정점의 밀접하게 패킹된 {float3} 레이아웃을 모든 셰이더 버퍼에 적용하지 마세요." +concepts.shaders.layout.guidance: 리소스 핸들은 기존 리소스를 참조하는 작은 값입니다. 핸들을 상수 버퍼에 복사한다고 해서 리소스의 내용이 복사되는 것은 아닙니다. +concepts.shaders.layout.notes: "{computeShaderSlang}의 해당 선언은 다음과 같습니다:" +concepts.shaders.layout.reference: "치수는 처음 8바이트를 차지하고 그 뒤에 8바이트 리소스 핸들 2개가 옵니다. C# 샘플은 총 256바이트를 예약합니다. 해당 크기는 샘플이 선택한 스토리지 크기이며 모든 Slang 구조체나 상수 페이로드가 256바이트를 차지해야 한다는 규칙은 아닙니다. 전체 크기를 패딩해도 잘못된 오프셋의 필드가 수정되지는 않습니다." +concepts.shaders.layout.title: 정점 입력과 셰이더 데이터의 서로 다른 레이아웃 규칙 +concepts.shaders.matrices.description: 컴파일러는 각 행의 요소를 함께 저장하는 행 우선(row-major) 행렬 스토리지를 요청합니다. {link}는 오프셋 0, 64 및 128에 세 개의 {matrix4x4} 값을 배치합니다. 해당 {detail}는 모델, 뷰 및 프로젝션 순서로 {mulVectorMatrix}를 사용합니다. +concepts.shaders.matrices.description.detail: 셰이더 +concepts.shaders.matrices.description.link: 회전하는 큐브 렌더러 +concepts.shaders.matrices.details: 저장 순서는 행렬 요소가 메모리를 차지하는 방식을 결정하고 곱셈 순서는 변환을 결정합니다. 양쪽의 일관성을 유지하세요. 두 가지 선택을 확인하지 않고 전치(transpose)를 추가하면 다른 불일치를 유발하면서 한 가지 불일치를 숨길 수 있습니다. +concepts.shaders.matrices.title: 행렬 스토리지 및 곱셈의 일관성 유지 +concepts.shaders.title: 셰이더 데이터 및 바인딩 +concepts.synchronization.backends.description: DirectX 12 및 Vulkan은 레이아웃 및 접근 정보로 텍스처 전환을 인코딩합니다. Metal은 Zenith.NET의 {transition} 구현에 작업이 없습니다. Metal은 기록된 작업을 렌더 및 컴퓨팅 인코더로 그룹화합니다. 백엔드는 이러한 그룹을 끝낼 때 가시성 배리어를 삽입하여 이후 작업에서 이전 쓰기를 사용할 수 있도록 합니다. 명시적 {barrier} 호출은 동일한 인코더 내에서 연속적인 컴퓨팅 디스패치와 같은 종속성을 처리합니다. +concepts.synchronization.backends.details: 이 차이점은 워크로드를 변경할 때 중요합니다. {link}에서 디스패치 뒤에는 그래픽 렌더 패스가 오며, 이는 Metal에서도 인코더 경계를 생성합니다. 두 개의 종속 컴퓨팅 디스패치는 텍스처의 선언된 레이아웃을 변경하는 것만으로는 해당 경계를 생성하지 않습니다. 공유 API에 필요한 전환을 유지하고 실제 생성 및 소비 명령 간의 종속성을 별도로 식별하세요. +concepts.synchronization.backends.details.link: 컴퓨팅 샘플 +concepts.synchronization.backends.title: 전환이 모든 백엔드에서 동일하지는 않음 +concepts.synchronization.barriers.context: "{barrierStagesAll}은 더 넓은 범위이며 자동 종속성 감지기가 아닙니다. 작업을 실제로 포괄하는 단계를 선택하고 해당 작업을 지원하는 큐에서만 사용하세요." +concepts.synchronization.barriers.description: "두 개의 컴퓨팅 디스패치를 생각해 보세요. 첫 번째는 시뮬레이션 데이터를 쓰고 두 번째는 다음 단계를 수행하기 위해 해당 데이터를 읽습니다. 둘 다 스토리지 버퍼를 사용하므로 변경할 텍스처 레이아웃이 없습니다. 명령 버퍼의 디스패치 사이에 다음을 삽입합니다:" +concepts.synchronization.barriers.details: 첫 번째 인수는 생산 단계를 식별하고 두 번째 인수는 소비 단계를 식별합니다. 배리어는 GPU에 해당 실행 및 메모리 종속성을 설정합니다. 백엔드는 이러한 단계를 실행 및 메모리 접근 규칙으로 변환합니다. 이 배리어는 텍스처의 레이아웃을 변경하지 않으며 장치의 모든 작업을 대기하지도 않습니다. +concepts.synchronization.barriers.guidance: "{link}는 종속 디스패치 간에 이 패턴을 사용합니다. 종속성이 발생하는 곳에 배리어를 배치하세요. 소비자가 이미 기록된 후의 배리어는 해당 소비자를 이전 생산자 뒤에 순서대로 배치할 수 없습니다." +concepts.synchronization.barriers.guidance.link: FluidTank 시뮬레이션 +concepts.synchronization.barriers.title: 배리어로 종속 명령 순서 지정 +concepts.synchronization.dependencies.description: 각 공유 리소스에 대해 먼저 접근하는 작업, 그 뒤를 잇는 작업, 둘 중 쓰기 접근이 있는지 식별합니다. 동일한 데이터를 두 번 읽는 것은 내용을 보호하기 위한 순서 지정이 필요하지 않지만, 레이아웃 변경이나 프레젠테이션으로 인해 다른 요구 사항이 적용될 수 있습니다. 쓰기 후 읽기, 읽기 후 덮어쓰기 또는 두 번의 쓰기에는 종속성이 필요할 수 있습니다. +concepts.synchronization.dependencies.details: "그런 다음 해당 작업이 실행되는 위치에 대한 메커니즘을 선택합니다:" +concepts.synchronization.dependencies.guidance: 이러한 메커니즘은 관련되어 있지만 상호 교환할 수 없습니다. 명령을 순서대로 제출한다고 해서 모든 메모리 종속성이 대체되는 것은 아닙니다. 큐 대기는 새 텍스처 레이아웃을 선언하지 않으며 명령 배리어는 호출하는 CPU 스레드에서 대기하지 않습니다. +concepts.synchronization.dependencies.table.cpuAccess.mechanism: 해당 완료 값에 대해 {wait}를 호출합니다. +concepts.synchronization.dependencies.table.cpuAccess.situation: CPU가 데이터에 접근하거나 해제하기 전에 대기해야 하는 경우 +concepts.synchronization.dependencies.table.crossQueue.mechanism: 소비하는 명령 버퍼의 {submit}에 해당 {timelineValue}를 전달합니다. +concepts.synchronization.dependencies.table.crossQueue.situation: 다른 큐의 제출이 데이터를 생성하는 경우 +concepts.synchronization.dependencies.table.headings.mechanism: 메커니즘 +concepts.synchronization.dependencies.table.headings.situation: 상황 +concepts.synchronization.dependencies.table.layoutChange.mechanism: 이전 및 다음 레이아웃이 포함된 {commandBufferTransition}. +concepts.synchronization.dependencies.table.layoutChange.situation: 텍스처 하위 리소스 사용 방식 변경 +concepts.synchronization.dependencies.table.pipelineStages.mechanism: 생산 및 소비 단계를 포함하는 {commandBufferBarrier}. +concepts.synchronization.dependencies.table.pipelineStages.situation: 명령 스트림의 종속 GPU 단계 +concepts.synchronization.dependencies.title: 생산자와 소비자로 시작 +concepts.synchronization.description: "이전 명령이 쓴 데이터를 읽는 명령은 쓰기가 완료되어 그 결과를 읽을 수 있어야 합니다. 쓰는 쪽은 생산자이고 읽는 쪽은 소비자입니다. CPU도 공유 데이터를 읽거나 덮어쓰거나 해제하기 전에 완료 지점이 필요합니다. Zenith.NET은 이러한 종속성에 맞춰 배리어, 텍스처 전환과 타임라인을 제공합니다." +concepts.synchronization.layouts.context: "{undefined}는 이전 내용을 보존할 필요가 없음을 의미합니다. 새 이미지나 완전히 지워질 어태치먼트에 적합합니다. 내용을 로드, 샘플링 또는 누적할 이미지의 레이아웃 추적을 피하기 위한 방법이 아닙니다." +concepts.synchronization.layouts.description: "용도 플래그는 텍스처가 지원하는 역할을 설명합니다. {textureLayout}은 작업을 위해 특정 하위 리소스에 접근하는 방식을 설명합니다. 하위 리소스는 선택된 밉 레벨과 배열 레이어입니다. 레이아웃을 변경하면 해당 접근이 준비되지만 텍스처가 다른 픽셀 형식으로 변환되지는 않습니다. 예를 들어 컴퓨팅 샘플은 {storage} 레이아웃으로 출력 텍스처를 작성한 다음 그래픽 패스에서 이를 샘플링합니다. 이러한 사용 사이에 다음을 기록합니다:" +concepts.synchronization.layouts.details: 이 조각은 {outputTexture}가 {sampledStorage} 용도로 생성되었고 선택된 하위 리소스가 {storage} 레이아웃에 있다고 가정합니다. {default}는 밉 레벨 0과 배열 레이어 0을 선택합니다. 이 작업은 텍스처의 모든 밉 또는 레이어를 전환하지는 않습니다. +concepts.synchronization.layouts.guidance: 애플리케이션은 이전 레이아웃을 제공합니다. {transition}은 애플리케이션에 표시되는 레이아웃 추적기를 유지 관리하지 않으며 이전 명령에서 해당 값을 유추하지도 않습니다. 리소스가 렌더링 단계 간에 전달되는 곳마다 레이아웃을 추적하세요. +concepts.synchronization.layouts.title: 각 텍스처 하위 리소스의 레이아웃 추적 +concepts.synchronization.readback.description: "{isCompleted}는 GPU 타임라인이 값에 도달했는지만 쿼리합니다. 명령 버퍼를 회수하거나 스테이징된 다운로드를 애플리케이션의 대상 포인터에 복사하지는 않습니다." +concepts.synchronization.readback.details: "{commandBufferDownload}는 먼저 내부 리드백 저장 공간으로의 복사를 기록합니다. 완료된 명령 버퍼를 재사용하도록 재설정할 때 CPU가 데이터를 제공된 포인터로 복사합니다. 해당 다운로드 제출 값의 {wait}가 반환될 때까지 대상 메모리를 유효하게 유지하고 관리 메모리를 고정하세요. 데이터 읽기나 메모리 해제는 그 이후에 해야 합니다. 다른 큐의 후속 제출을 기다리는 것만으로는 다운로드를 관리하는 큐가 폴링되지 않습니다." +concepts.synchronization.readback.guidance: 이것이 {isCompleted}를 폴링하고 비동기 다운로드 대상을 즉시 읽는 것만으로는 충분하지 않은 이유입니다. {link}에서 직접 복사 및 스테이징 전송 경로를 다룹니다. +concepts.synchronization.readback.guidance.link: 리소스 관리 +concepts.synchronization.readback.title: GPU 완료와 다운로드된 CPU 데이터는 별개의 단계임 +concepts.synchronization.reuse.description: "첫 번째 렌더러의 경우 각 프레임 직후에 대기하는 것이 간단합니다. 작업을 중첩하려면 미해결 프레임에 별도의 가변 데이터를 제공하고 각 프레임의 최종 사용 완료 값을 유지하세요. 상수 버퍼를 업데이트하거나 텍스처를 교체하거나 파이프라인을 해제하기 전에 영향을 받는 리소스에 대한 모든 미해결 접근을 완료하세요." +concepts.synchronization.reuse.details: "크기 조정 또는 종료 시 이전 작업을 기다리기 전에 새 사용을 중지하세요. {swapChainResize}, 리소스 해제 및 컨텍스트 해제는 애플리케이션 작업에 대한 일반적인 대기 역할을 하지 않습니다. 이전 각 프레임이 이미 제출을 완료했으므로 삼각형 튜토리얼은 콜백 간에 안전하게 크기를 조정할 수 있습니다." +concepts.synchronization.reuse.guidance: 현재 {swapChainPresent}도 프레젠테이션 작업 후 그래픽 큐에서 신호를 보내고 대기합니다. 따라서 삼각형의 명시적 제출 대기를 제거한다고 해서 그 자체로 중첩 프레젠테이션 루프가 설정되지는 않습니다. 또한 그래픽 큐 대기는 다른 큐에서 여전히 실행 중인 독립적인 작업에 대해서는 아무것도 보장하지 않습니다. +concepts.synchronization.reuse.title: 최종 접근 후에만 데이터 재사용 +concepts.synchronization.timelines.context: "CPU가 이러한 리소스를 읽거나 덮어쓰거나 해제하기 전에 최종 사용을 기다리세요:" +concepts.synchronization.timelines.description: 타임라인은 증가하는 값을 사용하여 큐의 완료를 추적합니다. {submit}은 해당 타임라인과 제출과 관련된 값을 포함하는 {timelineValue}를 반환합니다. 서로 다른 타임라인의 완료 값은 숫자 {value} 필드만으로는 비교할 수 없습니다. +concepts.synchronization.timelines.details: "{producer}와 {consumer}가 동일한 컨텍스트의 두 큐에서 이미 기록된 명령 버퍼라고 가정합니다. 생산자는 소비자가 사용하는 데이터를 씁니다. 다음과 같이 제출하세요:" +concepts.synchronization.timelines.guidance: 생성된 값을 전달하면 소비 큐가 GPU에서 이를 기다립니다. CPU는 여기서 {producedWait}를 호출하지 않습니다. {consumed}가 완료될 때까지 공유 리소스를 유효하게 유지하고 소비자가 요구하는 텍스처 레이아웃 변경 사항을 기록하세요. +concepts.synchronization.timelines.notes: "{wait}는 해당 타임라인 값을 기다린 다음 소유 큐에서 완료된 제출을 확인합니다. 완료된 명령 버퍼는 재사용을 위해 재설정되고 스테이징된 다운로드는 제공된 CPU 대상에 복사됩니다. {queueTimelineSignal}은 해당 큐에 이미 제출된 작업 후에 완료 지점을 큐에 추가할 수도 있습니다. {signal}을 호출한다고 해서 GPU가 이미 해당 지점에 도달했음을 의미하지는 않습니다." +concepts.synchronization.timelines.title: 완료 및 큐 전달에 타임라인 사용 +concepts.synchronization.title: 동기화 +home.actions.reference: API 탐색 +home.actions.tutorial: 삼각형으로 시작하기 +home.entries.description: 첫 번째 프레임. 핵심 예제. API에 대한 자세한 정보. +home.entries.label: 문서 탐색 +home.entries.reference.action: API 탐색 +home.entries.reference.category: 참조 +home.entries.reference.description: 애플리케이션의 기반이 되는 형식, 시그니처 및 멤버를 확인하세요. +home.entries.reference.title: API 참조 +home.entries.samples.action: 예제 탐색 +home.entries.samples.category: 예제 +home.entries.samples.description: 소스 코드를 통해 핵심 렌더링 및 컴퓨팅 기법을 살펴보세요. +home.entries.samples.title: 예제 +home.entries.title: 빌드를 시작하세요. +home.entries.tutorial.action: 튜토리얼 시작 +home.entries.tutorial.category: 튜토리얼 +home.entries.tutorial.description: 설정부터 첫 번째 프레임까지 완전한 렌더링 애플리케이션을 구축하세요. +home.entries.tutorial.title: 첫 번째 삼각형 +home.introduction.accent: "C#으로 구축." +home.introduction.description: 단일 .NET API를 통해 리소스를 생성하고, 명령을 기록하며, 그래픽 또는 컴퓨팅 작업을 제출하세요. +home.introduction.title: 나만의 렌더러를 구축하세요. +home.meta.description: "DirectX, Metal 및 Vulkan 전반에서 그래픽 및 컴퓨팅을 위한 일관된 C# API를 제공합니다." +home.scene.description: 회전하는 지오메트리 연구입니다. 드래그하거나 화살표 키를 사용하여 보기를 조정하세요. +home.scene.label: 지오메트리 표시 +home.scene.surface: 서피스 +home.scene.wireframe: 와이어프레임 +home.title: .NET을 위한 모던 RHI +learning.concepts.description: 렌더 패스를 결합하기 전에 명령, 리소스, 셰이더 데이터 및 동기화가 어떻게 맞물려 동작하는지 이해하세요. +learning.concepts.execution.description: GPU 작업을 기록하고 제출하며, 해당 리소스를 유효하게 유지하세요. +learning.concepts.platforms.description: 네이티브 윈도우 또는 UI 렌더링 컨트롤을 연결하세요. +learning.concepts.resources.description: 리소스 용도, 메모리 배치 및 뷰를 선택하세요. +learning.concepts.shaders.description: "C# 레이아웃과 리소스 핸들을 Slang과 일치시키세요." +learning.concepts.synchronization.description: 종속적인 접근 순서를 지정하고 작업 완료 시점을 파악하세요. +learning.concepts.title: 핵심 개념 +learning.description: 완전한 삼각형 튜토리얼로 시작하세요. 그런 다음 핵심 예제와 개념 가이드를 활용하여 더 큰 렌더러의 기반이 되는 리소스, 데이터 및 종속성을 이해하세요. +learning.entries.samples.action: 예제 탐색 +learning.entries.samples.description: "지오메트리, 컴퓨팅, 레이 쿼리 및 메시 셰이딩에 대한 C# 및 Slang 예제를 찾아보세요." +learning.entries.tutorial.action: 튜토리얼 열기 +learning.entries.tutorial.description: 콘솔 애플리케이션을 생성하고, 윈도우를 열며, 삼각형을 그립니다. +learning.meta.description: Zenith.NET을 시작하고 해당 프로그래밍 모델을 살펴보세요. +learning.title: 학습 +reference.description: 리소스 형식, 명령 시그니처 및 플랫폼 통합을 조회하세요. +reference.entries.commands.description: 그래픽, 컴퓨팅 및 전송 명령을 기록하세요. +reference.entries.commands.label: 작업 기록 +reference.entries.context.description: 선택한 백엔드를 위한 GPU 리소스를 생성하세요. +reference.entries.context.label: 여기서 시작 +reference.meta.description: Zenith.NET의 형식과 멤버를 살펴보세요. +reference.navigation.core: 핵심 API를 탐색하세요. +reference.title: API 참조 +samples.computeShader.description: 컴퓨팅 디스패치로 이미지를 그레이스케일로 변환하고 결과 텍스처를 표시합니다. 샘플링된 입력 텍스처 및 쓰기 가능한 출력 텍스처를 위한 리소스 핸들, 올림 처리된 스레드 그룹 수, 셰이더 내 경계 검사를 보여줍니다. 포함된 {assetsTexturesShokoPng} 에셋을 유지하세요. 렌더러는 이를 한 번 처리하고 후속 프레임에서 결과를 표시합니다. +samples.computeShader.details: "{computeShaderRendererCs} · {computeShaderSlang}" +samples.computeShader.title: 컴퓨팅 셰이더 +samples.cube.description: 상수 버퍼의 모델, 뷰, 프로젝션 행렬, 인덱스 드로잉 및 깊이 테스트를 추가합니다. 크기 조정 시 깊이 텍스처가 다시 생성됩니다. 클립 공간 지오메트리에서 변환된 객체로 전환할 때 사용하세요. 렌더러는 {d32FloatS8UInt} 깊이/스텐실 어태치먼트를 사용합니다. +samples.cube.details: "{spinningCubeRendererCs} · {spinningCubeSlang}" +samples.cube.title: 회전하는 큐브 +samples.description: "연구하고자 하는 기능에 맞춘 예제를 선택하세요. 각 예제는 C# 렌더러와 해당 Slang 셰이더로 연결됩니다. 빈 프로젝트부터 전체 애플리케이션에 대한 설명을 원하시면 {link}부터 시작하세요." +samples.description.link: 첫 번째 삼각형 +samples.execution.description: "{link}에는 하나의 데스크톱 애플리케이션 내에 6개의 독립적인 렌더러가 포함되어 있습니다. .NET 10 SDK와 아래에 설명된 지원되는 데스크톱 백엔드를 사용하세요. 애플리케이션을 빌드 및 실행한 다음 콘솔 메뉴에서 예제를 선택하세요." +samples.execution.description.link: ZenithTutorials +samples.execution.details: 호스트는 Windows에서 DirectX 12, macOS에서 Metal, Linux에서 Vulkan을 선택합니다. 선택한 백엔드에서 지원하는 장치, 드라이버 및 셰이더 컴파일러 환경을 사용하세요. Linux 윈도우 경로는 X11 또는 XWayland가 필요합니다. {link}는 패키지 종속성을 선언하고 런타임에 필요한 셰이더 및 텍스처 에셋을 복사합니다. +samples.execution.details.link: 프로젝트 파일 +samples.execution.guidance: 예제들은 윈도우 처리 및 프레젠테이션 코드를 공유합니다. 연구하려는 기능에 따라 각 예제를 독립적으로 선택할 수 있습니다. +samples.execution.title: 튜토리얼 예제 실행하기 +samples.host.description: "{appCs}는 컨텍스트, 윈도우 및 스왑 체인을 생성합니다. 명령 버퍼를 가져오고, 선택한 렌더러를 호출하며, 프레임을 제출하고 표시합니다. {iRendererCs}는 렌더러의 업데이트, 렌더링, 크기 조정 및 해제 메서드를 정의합니다." +samples.host.details: 컴퓨팅 및 레이 트레이싱은 오프스크린 텍스처를 생성합니다. {texturePresenterCs} 및 {presentTextureSlang}은 해당 텍스처를 윈도우의 현재 프레임의 출력 텍스처에 그립니다. 호스트는 여전히 제출 및 스왑 체인 프레젠테이션을 소유합니다. +samples.host.title: 공유 호스트 및 프레젠테이션 +samples.indirectDrawing.description: 인덱스화된 간접 인수 버퍼와 구조화된 버퍼의 인스턴스별 데이터를 사용하여 큐브의 여러 복사본을 그립니다. CPU가 드로잉 인수를 제공하고 변환을 업데이트합니다. GPU 생성 인수를 추가하기 전에 간접 인수 레이아웃과 인스턴스 데이터에 대한 셰이더 접근을 이해하는 데 사용하세요. +samples.indirectDrawing.details: "{indirectDrawingRendererCs} · {indirectDrawingSlang}" +samples.indirectDrawing.title: 간접 드로잉 +samples.meshShading.description: 태스크 셰이더를 사용하여 구 인스턴스를 컬링하고 지오메트리를 내보내는 메시 셰이더로 인덱스를 전달합니다. 렌더러는 파이프라인을 생성하기 전에 {contextCapabilitiesMeshShadingSupported}를 확인합니다. 태스크 및 메시 단계를 통해 리소스 핸들과 페이로드 데이터를 추적하는 데 사용하세요. +samples.meshShading.details: "{meshShadingRendererCs} · {meshShadingSlang}" +samples.meshShading.title: 메시 셰이딩 +samples.rayTracing.description: 지면과 절차적 구체를 위한 하위 및 상위 가속 구조를 구축한 다음 컴퓨팅 셰이더에서 인라인 레이 쿼리를 추적합니다. 렌더러는 워크로드를 구성하기 전에 {contextCapabilitiesRayTracingSupported}를 확인합니다. 가속 구조 입력 및 셰이더 측 광선 순회에 이 예제를 사용하세요. +samples.rayTracing.details: "{rayTracingRendererCs} · {rayTracingSlang}" +samples.rayTracing.title: 레이 트레이싱 +samples.title: 예제 +samples.triangle.description: 정점 버퍼와 일치하는 입력 레이아웃을 생성한 다음 그래픽스 파이프라인을 통해 세 개의 정점을 그립니다. 리소스 생성과 렌더 패스 내의 명령을 연결하는 데 사용하세요. +samples.triangle.details: "{helloTriangleRendererCs} · {helloTriangleSlang} · {link}" +samples.triangle.details.link: 전체 튜토리얼 +samples.triangle.title: Hello Triangle +samples.workloads.description: "메인 저장소의 {link}에는 여러 기능을 결합한 애플리케이션이 포함되어 있습니다. 해당 프로젝트는 라이브러리 소스 코드를 참조합니다. Zenith.NET 체크아웃에서 원하는 프로젝트를 실행하세요. 예:" +samples.workloads.description.link: Experiments 디렉터리 +samples.workloads.details: 윈도우 기반 실험은 Windows, macOS 및 Linux/X11에 대해 동일한 호스트 선택을 사용합니다. Avalonia, WinForms, WPF, WinUI/Uno 또는 MAUI 내에서의 드로잉, 컨트롤 프레임 수명 주기 및 구현 링크에 대해서는 {link}를 참조하세요. +samples.workloads.details.link: 플랫폼 통합 +samples.workloads.table.cornellBox.example: "{link}" +samples.workloads.table.cornellBox.example.link: CornellBox +samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: 패스 트레이싱, 디노이징, 톤 매핑, 업스케일링 및 ImGui 컨트롤을 보여줍니다. 레이 트레이싱 지원과 데스크톱 백엔드용 셰이더 컴파일러 환경이 필요합니다. +samples.workloads.table.fluidTank.example: "{link}" +samples.workloads.table.fluidTank.example.link: FluidTank +samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: 컴퓨팅 유체 시뮬레이션, 시뮬레이션 단계 간 종속성 및 다중 패스 표면 렌더링을 보여줍니다. 데스크톱 백엔드 및 셰이더 컴파일러 환경이 필요합니다. +samples.workloads.table.headings.example: 예제 +samples.workloads.table.headings.whatItDemonstratesAndRequires: 시연 내용 및 요구 사항 +samples.workloads.table.inkCanvas.example: "{link}" +samples.workloads.table.inkCanvas.example.link: InkCanvas +samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: 네이티브 윈도우에서의 Skia 드로잉 및 입력 처리를 보여줍니다. 대상 플랫폼용 백엔드 및 네이티브 Skia 라이브러리가 필요합니다. +samples.workloads.table.platformDetection.example: "{link}" +samples.workloads.table.platformDetection.example.link: PlatformDetection +samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: 각 백엔드에 대한 컨텍스트 생성을 시도하고 장치 기능을 보고합니다. 컨텍스트 생성이 실패하면 지원되지 않는 것으로 보고되며, 이 결과는 드라이버 또는 런타임 종속성 누락을 나타낼 수도 있습니다. +samples.workloads.title: 더 큰 규모의 워크로드 살펴보기 +tutorial.context.description: 이제 윈도우를 열 수 있지만 윈도우에 렌더링할 GPU 개체는 아직 생성하지 않았습니다. {graphicsContext}는 선택한 그래픽 백엔드 및 해당 명령 큐에 대한 액세스를 제공합니다. +tutorial.context.details: "이 블록을 {emphasis}에 삽입합니다:" +tutorial.context.details.emphasis: using 지시문 뒤, {iWindowWindow} 앞 +tutorial.context.guidance: 분기는 Windows에서는 DirectX 12, macOS에서는 Metal, Linux에서는 Vulkan을 선택합니다. 이어지는 렌더링 코드는 공유 Zenith.NET API를 사용합니다. 개발 중에 유효성 검사를 요청하고 {validationMessage}를 통해 보고된 메시지를 출력합니다. 진단은 백엔드 및 컴퓨터에서 사용 가능한 유효성 검사 구성 요소에 따라 다릅니다. +tutorial.context.title: 그래픽스 컨텍스트 생성 +tutorial.description: 윈도우를 열고 부드러운 그라데이션이 있는 삼각형을 그리는 .NET 콘솔 애플리케이션을 빌드합니다. 정점 데이터, 셰이더 및 파이프라인 상태가 함께 작동하는 방식을 배우고, 이미지를 생성하는 명령을 기록하고 제출합니다. +tutorial.details: 섹션을 순서대로 진행하세요. 먼저 빈 윈도우를 연 다음 배경색을 표시하고 마지막으로 삼각형을 그립니다. 각 체크포인트는 다음 단계를 추가하기 전에 애플리케이션의 한 부분을 확인합니다. 초기화는 한 번 실행되며, 렌더링 콜백은 호출될 때마다 새 프레임을 기록합니다. +tutorial.draw.context: "{draw}에 대한 인수는 다음과 같습니다:" +tutorial.draw.description: "{windowRender} 콜백에서 {beginRenderPass}와 {endRenderPass} 사이의 {addTheTriangleDrawCommandsHereLater}를 다음 세 가지 명령으로 바꿉니다:" +tutorial.draw.details: "{setPipeline}은 방금 생성한 셰이더와 상태를 선택합니다. 정점 데이터를 바인딩하기 전에 설정하세요. 백엔드는 파이프라인의 입력 레이아웃을 사용하여 바인딩을 해석합니다." +tutorial.draw.guidance: "{setVertexBufferVertexBuffer}는 바이트 오프셋 0부터 시작하는 버퍼를 입력 슬롯 0에 바인딩합니다. 해당 슬롯은 {inputLayouts}의 단일 항목에 해당합니다. 데이터를 다시 복사하거나 업로드하지는 않습니다." +tutorial.draw.notes: 이 시점에서는 명령이 여전히 기록되기만 한 상태입니다. 렌더링 콜백 끝에 이미 있는 {submitWait} 및 {present} 호출이 작업을 실행하고 결과를 표시합니다. 삼각형이 이미지의 일부만 가리기 때문에 클리어 작업은 여전히 필요합니다. 배경 역시 각 프레임마다 정의된 색상을 받아야 합니다. +tutorial.draw.table.firstInstance.meaning: 인스턴스 번호 매기기를 0부터 시작합니다. +tutorial.draw.table.firstVertex.meaning: 버퍼의 첫 번째 정점부터 시작합니다. +tutorial.draw.table.headings.argument: 인수 +tutorial.draw.table.headings.description: 값 +tutorial.draw.table.headings.meaning: 의미 +tutorial.draw.table.instanceCount.meaning: 삼각형 한 개를 그립니다. +tutorial.draw.table.vertexCount.meaning: 세 개의 정점을 읽습니다. +tutorial.draw.title: 패스 내부에서 삼각형 그리기 +tutorial.execution.description: "{firstTriangle} 디렉터리에서 빌드하고 실행합니다:" +tutorial.execution.details: 윈도우에는 어두운 배경에 위쪽 모서리는 빨간색, 오른쪽 아래 모서리는 녹색, 왼쪽 아래 모서리는 파란색인 삼각형이 표시되어야 합니다. 내부는 해당 색상 간의 부드러운 그라데이션을 보여야 합니다. +tutorial.execution.guidance: 윈도우 크기를 조정해 보세요. 크기 조정 콜백은 프레임버퍼 치수를 업데이트하고 스왑 체인의 크기를 조정합니다. 렌더 패스는 해당 이미지와 일치하는 뷰포트를 설정합니다. 정점 위치가 정규화된 좌표로 유지되기 때문에 삼각형은 윈도우 너비와 높이의 동일한 비율을 유지합니다. 종횡비를 변경하면 모양이 늘어날 수 있습니다. 개체의 종횡비를 유지하려면 투영 또는 뷰포트 정책이 필요하며, 이는 이 첫 번째 드로잉의 범위를 벗어납니다. +tutorial.execution.title: 실행, 크기 조정 및 닫기 +tutorial.frame.commands.context: "{endRenderPass} 후 두 번째 전환은 프레젠테이션을 위해 이미지를 준비합니다. {submit}은 기록을 완료하고 명령 버퍼를 제출하며, {wait}는 GPU가 해당 제출을 완료할 때까지 기다립니다. 그런 다음 {present}는 렌더링된 이미지의 표시를 요청합니다." +tutorial.frame.commands.description: 렌더 패스는 동일한 어태치먼트를 사용하는 드로잉 작업을 그룹화합니다. 여기서 색상 어태치먼트는 스왑 체인의 출력 텍스처, 즉 드로잉을 수신하는 이미지입니다. {colorAttachmentClear}는 지정된 RGBA 색상으로 지우고 패스가 끝날 때 결과를 유지하도록 지시하는 설명을 생성합니다. {beginRenderPass}는 해당 지침을 기록하며, GPU는 명령이 제출된 후 지우기를 수행합니다. +tutorial.frame.commands.details: 대괄호에는 단일 색상 어태치먼트가 포함되어 있습니다. {null} 인수는 깊이 및 스텐실 테스트를 위한 깊이 값과 스텐실 마스크를 저장할 깊이/스텐실 어태치먼트가 없음을 의미합니다. +tutorial.frame.commands.guidance: "{beginRenderPass}는 어태치먼트를 덮는 뷰포트와 시저를 설정합니다. 뷰포트는 렌더링된 좌표를 픽셀에 매핑하고 시저는 쓸 수 있는 픽셀을 제한합니다. 이러한 기본값은 출력 텍스처 전체를 포괄하며, 이는 이 삼각형에 필요한 설정입니다." +tutorial.frame.commands.title: 클리어, 제출 및 프레젠테이션 +tutorial.frame.description: 먼저 이미지를 단일 배경색으로 채웁니다. 이 작업을 클리어(clear)라고 합니다. 해당 색상이 윈도우에 나타나면 서피스, 명령 제출 및 프레젠테이션 경로가 함께 작동하고 있는 것입니다. 이 체크포인트를 사용하면 지오메트리와 셰이더를 추가하기 전에 프레임 루프를 확인할 수 있습니다. +tutorial.frame.details: "렌더링 콜백은 프레임을 그릴 때 Silk.NET이 호출하는 코드입니다. 이 콜백은 이벤트의 경과 시간 인수가 필요하지 않으므로 {value}로 지정됩니다. {emphasis}에 등록합니다:" +tutorial.frame.details.emphasis: "{windowRun} 앞" +tutorial.frame.target.description: "{graphicsQueueCommandBuffer}는 기록이 이미 시작된 명령 버퍼를 가져옵니다. 기록은 GPU에 대한 작업을 설명하는 것이며 해당 작업을 즉시 실행하지는 않습니다." +tutorial.frame.target.details: 첫 번째 {transition}은 색상 어태치먼트 접근을 위해 출력 텍스처를 준비합니다. {default}는 밉 레벨 0과 배열 레이어 0을 선택합니다. 전체 이미지를 지우고 이전 내용을 버릴 것이므로 이전 레이아웃으로 {undefined}를 사용합니다. 기존 내용을 보존해야 하는 패스는 대신 실제 이전 레이아웃을 사용해야 합니다. +tutorial.frame.target.guidance: 각 프레임마다 스왑 체인의 현재 출력 텍스처를 사용하세요. 프레젠테이션으로 인해 사용 가능한 이미지가 변경될 수 있으므로 이전 프레임에서 저장된 텍스처는 영구적인 윈도우 렌더 타깃이 아닙니다. +tutorial.frame.target.title: 출력 텍스처 준비 +tutorial.frame.title: 배경색 표시 +tutorial.geometry.data.description: 이 배열을 {emphasis}에 추가합니다. 다음 리소스 생성 단계도 표시된 순서대로 해당 콜백 앞에 배치됩니다. +tutorial.geometry.data.description.emphasis: "{windowRender} 앞" +tutorial.geometry.data.details: 각 배열 항목은 {vertex}를 생성합니다. 두 개의 내부 {new} 표현식은 해당 {vector3} 위치와 {vector4} 색상을 생성합니다. 정점은 위쪽, 오른쪽 아래, 왼쪽 아래 모서리를 설명합니다. 정점 셰이더는 네 번째 위치 좌표인 {w}를 제공합니다. w가 1이면 x와 y는 정규화된 장치 좌표를 직접 설명합니다. -1과 +1은 이미지 가장자리이고 0은 중심입니다. 이러한 좌표는 윈도우의 픽셀 크기에 의존하지 않습니다. +tutorial.geometry.data.guidance: 각 색상에는 빨강, 초록, 파랑 및 알파 구성 요소가 포함되어 있습니다. 알파는 세 모서리 모두에서 1입니다. 세 위치 모두 z = 0이므로 동일한 평면에 배치됩니다. 이러한 위치는 렌더링하려는 좌표를 이미 설명하고 있으므로 카메라나 변환 행렬이 필요하지 않습니다. 이 단일 평면 삼각형의 경우 블렌딩 및 깊이 테스트도 비활성화하고 깊이 버퍼를 생략합니다. +tutorial.geometry.data.title: 모서리 선택 +tutorial.geometry.description: 정점은 그리는 데 사용되는 데이터와 함께 제공되는 점입니다. 우리의 삼각형에는 각 모서리마다 하나씩 세 개의 정점이 있습니다. 각각에는 위치와 색상이 포함되어 있습니다. GPU는 색상을 보간하여 삼각형 전체에 걸쳐 중간 값을 계산합니다. +tutorial.geometry.format.description: "이 선언을 {emphasis}에 추가합니다:" +tutorial.geometry.format.description.emphasis: "{programCs} 끝부분, 정리 문 뒤" +tutorial.geometry.format.details: "{file}은 이 형식을 {programCs}로 제한하며, 생성자는 위치 및 색상 필드를 초기화합니다. {layoutKindSequential}은 필드를 선언 순서대로 유지합니다. {position}에는 32비트 부동소수점 3개가 포함되고 {color}에는 4개가 포함됩니다. 이 구조체에서 위치는 바이트 0에서 시작하고 색상은 바이트 12에서 시작하며 완전한 정점은 28바이트를 차지합니다. 그래픽스 파이프라인에 동일한 레이아웃을 설명할 것입니다." +tutorial.geometry.format.title: 정점 정의 +tutorial.geometry.title: GPU에 정점 세 개 제공 +tutorial.geometry.upload.context: "{fixed}는 주소가 사용되는 동안 가비지 수집기가 배열을 이동하지 못하도록 방지합니다. 이 CPU 쓰기 가능 버퍼의 경우 {upload}는 반환하기 전에 메모리를 매핑, 복사 및 매핑 해제하므로 나중에 배열을 고정된 상태로 유지할 필요가 없습니다. 버퍼는 렌더링 내내 유지되어야 하며 정점이 변경되지 않으므로 업로드는 한 번만 수행하면 됩니다." +tutorial.geometry.upload.description: "관리되는 배열은 CPU 데이터입니다. {buffer}는 GPU가 정점을 읽을 수 있는 스토리지를 제공합니다. 배열 뒤에 다음을 추가합니다:" +tutorial.geometry.upload.details: "총 크기는 {sizeofVertexVerticesLength}입니다. 정점당 28바이트, 3개의 정점, 총 84바이트입니다. {bufferUsagesVertex}는 정점 입력 접근을 허용합니다. {cpuWriteOnly}를 사용하면 CPU가 이 작은 버퍼를 직접 초기화할 수 있습니다. 설명자의 스트라이드는 요소 크기를 기록합니다. 아래에서 생성할 입력 레이아웃은 개별 속성을 읽는 방법을 정점 가져오기에 알려줍니다." +tutorial.geometry.upload.guidance: 버퍼를 생성해도 채워지지는 않습니다. {upload}는 대상 바이트 오프셋 0부터 시작하여 해당 할당에 배열을 복사합니다. 소스 설명은 포인터와 복사할 바이트 수를 제공합니다. +tutorial.geometry.upload.notes: "{programCs} 하단의 정리에서 {swapChainDispose} 바로 앞에 {vertexBufferDispose}를 추가하세요. 더 큰 정적 지오메트리의 경우 {link}에서 GPU 전용 메모리와 전송 업로드를 대신 선택해야 하는 시점을 설명합니다." +tutorial.geometry.upload.notes.link: 리소스 관리 +tutorial.geometry.upload.title: 버퍼 할당 및 배열 업로드 +tutorial.input.description: "정점 바이트와 셰이더가 준비되었습니다. 다음으로 GPU가 각 정점을 읽는 방법을 설명합니다. 속성은 위치나 색상과 같은 단일 값입니다. 입력 레이아웃은 각 속성에 형식과 바이트 오프셋을 제공합니다. 스트라이드는 한 정점에서 다음 정점까지의 바이트 단위 거리를 제공합니다. 셰이더 생성 후 이 초기화 블록을 추가합니다:" +tutorial.input.details: "{inputLayoutAdd}는 현재 스트라이드에 요소를 추가하고 해당 스트라이드를 요소 크기만큼 늘립니다. C# 구조체를 검사하지는 않습니다. 여기서는 CPU 메모리와 셰이더 입력 간에 다음과 같은 일치 관계를 생성합니다:" +tutorial.input.guidance: "이 설명을 업데이트하지 않고 C# 필드 순서나 패딩을 변경하면 GPU가 잘못된 바이트를 읽게 됩니다. 기본 {semanticIndex}는 0이며 {pOSITION0} 및 {cOLOR0}과 일치합니다. 두 요소 모두 동일한 버퍼에 속하므로 파이프라인에는 하나의 입력 레이아웃이 포함되며 해당 버퍼를 슬롯 0에 바인딩합니다." +tutorial.input.table.headings.byteOffset: 바이트 오프셋 +tutorial.input.table.headings.cField: "C# 필드" +tutorial.input.table.headings.format: 형식 +tutorial.input.table.headings.shaderInput: 셰이더 입력 +tutorial.input.table.nextVertex.cField: 다음 정점 +tutorial.input.table.nextVertex.format: "총 스트라이드: 28바이트" +tutorial.input.table.nextVertex.shaderInput: 다음 입력 레코드 +tutorial.input.table.vertexColor.format: "{float4} (16바이트)" +tutorial.input.table.vertexPosition.format: "{float3} (12바이트)" +tutorial.input.title: 정점 입력 레이아웃 설명 +tutorial.lifecycle.description: "완성된 애플리케이션은 이 시퀀스를 반복합니다:" +tutorial.lifecycle.details: "윈도우를 닫으면 {run}에서 반환됩니다. 렌더링된 각 프레임은 이미 GPU 작업이 완료될 때까지 기다렸으므로 이제 사용된 리소스를 안전하게 해제할 수 있습니다. {windowRun} 이후의 정리는 다음과 같아야 합니다:" +tutorial.lifecycle.guidance: "네이티브 윈도우보다 먼저 스왑 체인을 해제하고, 모든 리소스를 해제한 후 컨텍스트를 해제하세요. 제출된 명령 버퍼는 큐가 소유하고 재활용하며, 출력 텍스처는 스왑 체인이 소유합니다. 따라서 이 애플리케이션에서는 해당 명령 버퍼와 출력 텍스처에 별도의 {dispose} 호출이 필요하지 않습니다." +tutorial.lifecycle.title: 단일 프레임의 수명 주기 추적 +tutorial.pipeline.behavior: "입력 레이아웃 뒤에 다음을 추가합니다:" +tutorial.pipeline.context: "{cullNone}은 면의 방향을 버리지 않고 삼각형을 채웁니다. 정점의 순서에 따라 면의 감기 방향이 결정되므로 컬링을 비활성화하면 해당 순서로 인해 첫 번째 삼각형이 숨겨지는 것을 방지할 수 있습니다." +tutorial.pipeline.description: 이제 정점 데이터, 입력 레이아웃 및 두 개의 셰이더가 준비되었습니다. {graphicsPipeline}은 이들을 연결하고 GPU가 정점을 기본형(primitive)으로 조립하고 결과를 어태치먼트에 쓰는 방법을 지정합니다. +tutorial.pipeline.details: "파이프라인은 프로그래밍 가능한 셰이더 단계와 삼각형 조립, 면 컬링, 블렌딩과 같은 GPU 작업을 제어하는 고정 기능 설정을 결합합니다. 이 삼각형의 경우 다음 설정을 선택합니다:" +tutorial.pipeline.guidance: 색상 형식은 {swapChainDescFormat}에서 가져옵니다. 렌더 패스에서 사용하는 이미지와 일치해야 합니다. {count1}은 픽셀당 하나의 샘플을 의미합니다. +tutorial.pipeline.item: "{triangleList}는 연속된 세 개의 정점 그룹을 하나의 삼각형으로 조립합니다. 세 개의 정점을 제공하고 한 번 그리므로 인덱스 버퍼가 필요하지 않습니다." +tutorial.pipeline.notes: "{depthNone}은 깊이 테스트 및 쓰기를 비활성화하여 깊이 어태치먼트가 없는 패스와 일치시킵니다." +tutorial.pipeline.reference: "{opaque}는 블렌딩을 비활성화하므로 조각 셰이더의 색상이 삼각형 내부의 배경을 대체합니다." +tutorial.pipeline.title: 셰이더 및 정점 레이아웃 연결 +tutorial.pipeline.usage: "샘플 렌더러에서와 같이 파이프라인을 생성한 후 셰이더 개체를 해제할 수 있습니다. 파이프라인 자체는 이를 사용하여 그리는 모든 프레임 동안 유지하세요. 정리에서 {vertexBufferDispose} 앞에 {pipelineDispose}를 추가합니다. 파이프라인 생성은 렌더링 콜백 전 마지막 초기화 단계입니다." +tutorial.pipeline.validation: 파이프라인 설명은 어태치먼트 구성을 선언하며 다른 이미지를 생성하지 않습니다. 위치와 색상이 하나의 버퍼에 함께 저장되므로 {inputLayouts}에는 하나의 항목이 있습니다. +tutorial.presentation.title: GPU를 윈도우에 연결 +tutorial.project.context: 프로젝트의 빌드 설정에서 {emphasis}({allowUnsafeBlocks})를 사용하도록 설정하세요. 정점 데이터를 GPU에 전달하고 윈도우 도우미의 네이티브 호출에 이를 사용합니다. +tutorial.project.context.emphasis: 안전하지 않은 코드 허용 +tutorial.project.description: "프로젝트를 생성하고 해당 디렉터리로 이동합니다:" +tutorial.project.details: "패키지를 설치합니다:" +tutorial.project.guidance: "{zenithNET}은 공유 렌더링 API를 제공합니다. 세 가지 백엔드 패키지를 통해 동일한 프로그램이 해당 플랫폼에 적합한 구현을 선택할 수 있습니다. {zenithNETCompiler}는 나중에 작성할 작은 GPU 프로그램인 Slang 셰이더를 해당 구현을 위해 컴파일합니다. Silk.NET은 윈도우와 이벤트 루프를 제공합니다." +tutorial.project.title: 콘솔 프로젝트 생성 +tutorial.requirements.context: 빈 프로젝트에서 이 페이지를 따라갈 수 있습니다. {link} 및 해당 {detail}는 여기서 사용되는 렌더링 및 윈도우 API에 대한 참조로 제공됩니다. +tutorial.requirements.context.detail: 공유 호스트 +tutorial.requirements.context.link: Hello Triangle 샘플 +tutorial.requirements.description: "{emphasis}, 코드 편집기 또는 IDE, Zenith.NET 백엔드에서 지원하는 GPU 및 드라이버가 장착된 데스크톱 환경이 필요합니다. C#에 대한 기본적인 이해만 있으면 충분하며, 그래픽 개념은 사용될 때마다 설명됩니다. 이것은 일반적인 {net10} 콘솔 프로젝트입니다. 백엔드는 Zenith.NET 작업을 DirectX 12, Metal 또는 Vulkan과 같은 그래픽 API 호출로 변환합니다. 애플리케이션은 시작 시 그중 하나를 선택합니다:" +tutorial.requirements.description.emphasis: .NET 10 SDK +tutorial.requirements.details: Linux는 여기서 사용되는 윈도우 경로에 대해 X11 호환 윈도우 세션이 필요합니다. 이 삼각형을 그리는 데 선택적 레이 트레이싱 및 메시 셰이딩 기능은 필요하지 않습니다. +tutorial.requirements.guidance: Zenith.NET은 애플리케이션에서 제공하는 서피스에 렌더링합니다. Silk.NET.Windowing이 데스크톱 윈도우를 생성하고 해당 이벤트를 처리합니다. macOS에서 프레젠테이션 대상은 Metal 레이어({cAMetalLayerCs})입니다. 튜토리얼의 윈도우 도우미가 해당 레이어를 연결해 줍니다. +tutorial.requirements.table.headings.graphicsBackend: 그래픽 백엔드 +tutorial.requirements.table.headings.platform: 플랫폼 +tutorial.requirements.table.headings.windowSurface: 윈도우 서피스 +tutorial.requirements.table.linux.graphicsBackend: Vulkan 1.4 +tutorial.requirements.table.linux.platform: Linux +tutorial.requirements.table.linux.windowSurface: X11 윈도우 및 디스플레이 (XWayland도 적합) +tutorial.requirements.table.macOS.graphicsBackend: Metal 4 +tutorial.requirements.table.macOS.platform: macOS +tutorial.requirements.table.macOS.windowSurface: 윈도우에 연결된 Metal 레이어 +tutorial.requirements.table.windows.graphicsBackend: DirectX 12 +tutorial.requirements.table.windows.platform: Windows +tutorial.requirements.table.windows.windowSurface: Win32 윈도우 핸들 +tutorial.requirements.title: 시작하기 전에 +tutorial.resize.context: "{dotnetRun}을 다시 실행합니다. 이제 윈도우에는 크기를 조정한 후에도 계속 채워지는 균일한 어두운 배경이 있어야 합니다. 이 콜백을 유지하세요. 삼각형은 기존 렌더 패스 내에 그려집니다." +tutorial.resize.description: "스왑 체인의 이미지는 프레임버퍼 치수를 따라야 합니다. 디스플레이 배율로 인한 변경 사항을 포함하여 픽셀 크기 변경에 응답하려면 {framebufferResize}를 사용하세요. 렌더링 콜백 뒤, 여전히 {windowRun} 앞에 다음을 추가합니다:" +tutorial.resize.details: Silk.NET은 윈도우 크기 변경과 {link}를 구분합니다. 스왑 체인은 픽셀을 저장하므로 후자가 필요합니다. 최소화된 윈도우는 크기가 0인 프레임버퍼를 가질 수 있습니다. 두 콜백 모두 해당 경우 GPU 작업을 건너뜁니다. 크기 조정 후 렌더 패스는 뷰포트 및 시저에 새 어태치먼트 치수를 사용합니다. +tutorial.resize.details.link: 프레임버퍼 크기 변경 +tutorial.resize.guidance: 제출할 때마다 기다리므로 크기 조정 핸들러가 이미지를 바꿀 때 이전 프레임이 여전히 해당 이미지를 사용하고 있지 않습니다. 현재 {present} 구현도 그래픽 큐에서 대기합니다. 이 간단한 루프는 다음 프레임이 시작되기 전에 한 프레임의 작업이 완료된 상태를 유지합니다. {link}에서 고급 일정 관리를 다룹니다. +tutorial.resize.guidance.link: 동기화 +tutorial.resize.title: 크기 조정에 대응 +tutorial.shaders.compilation.context: 컴파일은 초기화 중에 한 번 수행됩니다. {appContextBaseDirectory}는 현재 작업 디렉터리와 관계없이 실행 파일 옆에 복사된 셰이더를 찾습니다. 이러한 셰이더는 정점 입력만 사용하므로 바인딩할 상수 버퍼, 텍스처 또는 리소스 핸들이 아직 없습니다. +tutorial.shaders.compilation.description: "{triangleSlang}의 파일 속성에서 {emphasis}를 {detail}로 설정합니다. 이렇게 하면 실행 파일 옆에서 셰이더를 사용할 수 있습니다." +tutorial.shaders.compilation.description.detail: 변경된 내용만 복사 +tutorial.shaders.compilation.description.emphasis: 출력 디렉터리에 복사 +tutorial.shaders.compilation.details: "{programCs}로 돌아갑니다. 정점 업로드 후, 렌더링 콜백 앞에 다음 초기화 문을 추가합니다:" +tutorial.shaders.compilation.guidance: "{zenithCompiler}는 요청된 그래픽 API용 코드가 포함된 셰이더 설명을 반환합니다. {createShader}는 해당 백엔드 개체를 생성합니다. 그래픽 API와 진입점 이름이 모두 중요합니다. {contextGraphicsApi}를 사용하고 {vSMain} 및 {fSMain}을 Slang 파일과 정확히 동일한 철자로 작성하세요." +tutorial.shaders.compilation.title: 선택한 백엔드용으로 컴파일 +tutorial.shaders.context: "{fSInput}은 정점 셰이더의 출력을 조각 셰이더의 입력에 연결합니다. 정점 셰이더가 쓰는 {sVPOSITION}은 클립 공간 위치를 제공하며, GPU는 이 네 좌표로 가시 영역 안에 있는 내용을 판단합니다. {cOLOR0}은 정점 사이에서 보간할 색상을 전달합니다. 두 단계에서 사용하는 형식과 시맨틱이 일치해야 합니다." +tutorial.shaders.description: 셰이더는 GPU가 실행하는 프로그램입니다. 이 드로잉에는 정점을 배치하기 위한 정점 셰이더와 삼각형 내부의 색상을 생성하기 위한 조각 셰이더가 필요합니다. 우리는 셰이더 언어인 Slang으로 이를 작성하고 동일한 파일에서 두 개의 진입점을 컴파일할 것입니다. 진입점은 셰이더 단계가 실행되기 시작하는 함수입니다. +tutorial.shaders.details: "이 두 구조체로 시작하여 {triangleSlang}을 생성합니다:" +tutorial.shaders.fragment.description: "동일한 파일에 조각 진입점을 추가합니다:" +tutorial.shaders.fragment.details: 래스터화는 삼각형이 포함하는 이미지 위치를 결정합니다. 덮인 영역 전체에 걸쳐 정점 색상이 보간되어 조각 셰이더가 처리하는 데이터인 조각(fragment)을 생성합니다. {fSMain}은 첫 번째 색상 어태치먼트를 식별하는 {sVTARGET}을 통해 이 보간된 색상을 반환합니다. +tutorial.shaders.fragment.guidance: 정점 색상 보간은 어태치먼트 블렌딩과 별개입니다. 블렌딩은 조각의 출력과 어태치먼트에 이미 저장된 색상을 결합합니다. 불투명 블렌드 상태는 해당 결합을 비활성화하므로 보간된 색상이 삼각형 내부의 배경을 대체합니다. +tutorial.shaders.fragment.title: 조각 색상 지정 +tutorial.shaders.guidance: "{vSInput}은 정점 셰이더가 정점 버퍼로부터 수신하는 내용을 설명합니다. 의미 체계 {pOSITION0} 및 {cOLOR0}이 입력을 식별합니다. C# 필드 이름만으로는 해당 매핑이 설정되지 않습니다." +tutorial.shaders.title: 두 셰이더 단계 작성 +tutorial.shaders.vertex.description: "정점 진입점을 {triangleSlang}에 추가합니다:" +tutorial.shaders.vertex.details: GPU는 각 입력 정점에 대해 이 진입점을 호출합니다. 위치에 동차 좌표 {w}를 추가하고 색상을 전달합니다. 정점 단계 후에 위치는 w로 나누어집니다. 여기서는 해당 나눗셈으로 x, y, z가 변경되지 않은 상태로 유지됩니다. 이것이 위에서 선택한 위치를 정규화된 장치 좌표로 직접 이해할 수 있는 이유입니다. +tutorial.shaders.vertex.title: 각 정점 위치 지정 +tutorial.surface.description: "컨텍스트는 출력을 표시할 위치도 알아야 합니다. {emphasis}에 다음을 추가합니다:" +tutorial.surface.description.emphasis: "{windowCenter} 뒤, {windowRun} 앞" +tutorial.surface.details: "{surface}는 네이티브 프레젠테이션 대상 및 픽셀 크기를 설명합니다. 프레임버퍼는 윈도우와 연결된 픽셀 이미지입니다. {framebufferSize}는 픽셀 단위 크기를 제공합니다. 디스플레이 배율이 활성화된 경우 윈도우의 논리적 크기와 다를 수 있습니다." +tutorial.surface.guidance: 서피스는 위에서 선택한 백엔드와 일치합니다. Windows는 윈도우 핸들을 제공하고, Linux는 X11 디스플레이 및 윈도우를 제공하며, macOS 도우미는 연결된 Metal 레이어를 제공합니다. 이것이 윈도우를 렌더링에 연결하는 유일한 플랫폼별 부분입니다. +tutorial.surface.title: 네이티브 서피스 설명 +tutorial.swapChain.context: "스왑 체인은 컨텍스트와 네이티브 윈도우를 모두 사용합니다. {programCs} 하단의 {windowDispose} 줄을 다음 정리 순서로 바꿉니다:" +tutorial.swapChain.description: "서피스 설명을 사용하여 표시될 이미지를 생성합니다. 서피스 블록 바로 뒤에 다음을 추가합니다:" +tutorial.swapChain.details: "{swapChain}은 윈도우에 표시되는 이미지를 관리합니다. 각 프레임에서 {drawable}은 현재 이미지를 이미지 데이터용 API 형식인 {texture}로 제공합니다. 드로잉 후 {present}는 결과 표시를 요청하고 다음 drawable로 이동합니다." +tutorial.swapChain.guidance: "{b8G8R8A8UNorm}은 파란색, 녹색, 빨간색 및 알파 순서로 4개의 8비트 색상 채널을 저장합니다. {uNorm}은 0부터 255까지의 정수 값이 0부터 1까지의 값을 나타냄을 의미합니다. 셰이더는 여전히 논리적 RGBA 값을 반환하지만, 이 형식은 해당 채널이 이미지에 저장되는 방식을 결정합니다. 나중에 그래픽스 파이프라인은 {swapChainDescFormat}을 사용하여 이 어태치먼트와 일치시킵니다." +tutorial.swapChain.title: 스왑 체인 생성 +tutorial.title: 첫 번째 삼각형 +tutorial.troubleshooting.description: "먼저 콘솔에서 오류를 읽은 다음 이전 체크포인트를 사용하여 실패한 단계를 식별하세요:" +tutorial.troubleshooting.details: "{link} 및 {detail}를 사용하여 정점 데이터, 입력 레이아웃 및 드로잉 작업을 비교하세요. 해당 샘플은 윈도우 처리 및 제출을 공유 호스트에 배치하지만, 이 튜토리얼은 애플리케이션 흐름을 {programCs}에 유지합니다. 인덱스 드로잉, 변환 및 깊이 테스트를 배우려면 {context}로 계속 진행하세요." +tutorial.troubleshooting.details.context: 회전하는 큐브 +tutorial.troubleshooting.details.detail: Slang 셰이더 +tutorial.troubleshooting.details.link: 샘플 렌더러 +tutorial.troubleshooting.table.backend.check: 선택한 백엔드가 장치 및 설치된 그래픽 드라이버에서 지원되는지 확인합니다. +tutorial.troubleshooting.table.backend.symptom: 백엔드 생성 실패 +tutorial.troubleshooting.table.drawing.check: 업로드 크기, 입력 레이아웃, 파이프라인 선택 및 렌더 패스 내부의 드로잉 명령 배치를 확인합니다. +tutorial.troubleshooting.table.drawing.symptom: 배경은 나타나지만 삼각형은 나타나지 않음 +tutorial.troubleshooting.table.headings.check: 확인 사항 +tutorial.troubleshooting.table.headings.symptom: 증상 +tutorial.troubleshooting.table.input.check: "28바이트 스트라이드와 0 및 12의 위치/색상 오프셋을 확인합니다." +tutorial.troubleshooting.table.input.symptom: 정점 위치 또는 색상이 손상됨 +tutorial.troubleshooting.table.shaders.check: 복사된 {triangleSlang}, 진입점 철자 및 컴파일러에서 보고된 진단을 확인합니다. +tutorial.troubleshooting.table.shaders.symptom: 클리어 색상 단계는 작동하지만 셰이더 로드에 실패함 +tutorial.troubleshooting.table.window.check: .NET 프로젝트가 빌드되고 윈도우 전용 단계가 데스크톱 세션에서 실행되는지 확인합니다. Linux의 경우 X11 또는 XWayland를 사용할 수 있는지 확인합니다. +tutorial.troubleshooting.table.window.symptom: 윈도우가 열리지 않음 +tutorial.troubleshooting.title: 실패한 단계 확인 +tutorial.window.context: "{usingZenithTutorials}는 도우미의 네임스페이스를 가져옵니다. 각 C# 파일은 고유한 일반 using 지시문을 사용하므로 상호 운용성 가져오기는 두 파일 모두에 필요합니다. 별칭 {buffer}는 Zenith.NET 버퍼 형식을 나타내며 {systemBuffer}와 구별합니다." +tutorial.window.description: "{cocoaHelperCs}를 네임스페이스를 유지한 상태로 프로젝트에 추가합니다. 해당 파일의 맨 위, 네임스페이스 선언 앞에 {interopUsing}을 추가합니다. 도우미는 macOS에서 윈도우에 Metal 레이어를 연결하며, 다른 플랫폼 분기에서는 이를 호출하지 않습니다." +tutorial.window.details: "생성된 {programCs}를 다음 코드로 교체합니다. 명시적인 {main} 메서드 없이 순서대로 실행되는 최상위 문을 사용합니다. 이후 섹션에서 이 동일한 파일에 코드를 추가할 위치를 안내합니다:" +tutorial.window.guidance: "{graphicsAPINone}은 Silk.NET에 자체 그래픽스 컨텍스트가 없는 윈도우를 생성하도록 요청합니다. 해당 컨텍스트는 Zenith.NET으로 생성합니다. {initialize}는 네이티브 윈도우를 생성하고 핸들을 사용할 수 있게 합니다. 핸들은 윈도우 시스템에서 제공하는 식별자입니다. {center}는 윈도우를 화면 중앙에 배치하고, {run}은 윈도우가 닫힐 때까지 이벤트를 처리합니다. 그런 다음 실행은 윈도우를 해제하는 {dispose}로 계속됩니다." +tutorial.window.notes: "{dotnetRun}을 실행합니다. 빈 윈도우가 열리고 이동, 크기 조정 및 닫기에 응답해야 합니다. 렌더링 명령을 아직 제출하지 않았으므로 해당 내용은 아직 정의되지 않았습니다. 계속하기 전에 닫으세요." +tutorial.window.title: 윈도우 열기 +ui.action.copy: 복사 +ui.action.navigate: 탐색 +ui.action.open: 열기 +ui.action.source: 소스 보기 +ui.api.browse: 네임스페이스 및 형식을 탐색합니다. +ui.api.clearTypeSearch: 형식 검색 지우기 +ui.api.findType: 형식 찾기 +ui.api.loadError: 형식을 로드할 수 없습니다. 이 페이지를 새로 고쳐 다시 시도하세요. +ui.api.loadingNamespaces: 네임스페이스 로드 중… +ui.api.loadingTypes: 형식 로드 중… +ui.api.matchingTypes: 일치하는 형식 +ui.api.namespace: 네임스페이스 +ui.api.namespaces: 네임스페이스 +ui.api.noNamespaceTypes: 이 네임스페이스에는 형식이 없습니다. +ui.api.noTypes: 일치하는 형식이 없습니다. +ui.api.types: 형식 +ui.content.reference: 참조 +ui.content.source: 소스 코드 +ui.content.tutorial: 튜토리얼 +ui.contents.close: 목차 닫기 +ui.contents.open: 목차 열기 +ui.contents.title: 목차 +ui.footer.caption: .NET을 위한 모던 RHI. +ui.footer.label: 바닥글 +ui.language.label: 언어 +ui.language.unavailable: 번역되지 않음 +ui.members.clear: 멤버 검색 지우기 +ui.members.close: 멤버 검색기 닫기 +ui.members.empty: 일치하는 멤버가 없습니다. +ui.members.open: 멤버로 이동 +ui.members.placeholder: 이름 또는 시그니처… +ui.members.search: 멤버 검색 +ui.members.title: 멤버 찾기 +ui.members.undeclared: 이 형식에는 선언된 멤버가 없습니다. +ui.navigation.api: API +ui.navigation.concepts: 개념 +ui.navigation.home: 홈 +ui.navigation.label: 기본 탐색 +ui.navigation.toggle: 탐색 전환 +ui.outline.title: 이 페이지의 내용 +ui.reference.assembly: 어셈블리 +ui.reference.classes: 클래스 +ui.reference.constructors: 생성자 +ui.reference.declaration: "C# 형식 선언" +ui.reference.delegates: 대리자 +ui.reference.derived: 파생 형식 +ui.reference.enums: 열거형 +ui.reference.events: 이벤트 +ui.reference.examples: 예제 +ui.reference.exceptions: 예외 +ui.reference.extensionMethods: 확장 메서드 +ui.reference.fields: 필드 +ui.reference.implementations: 명시적 인터페이스 구현 +ui.reference.implements: 구현 +ui.reference.inheritance: 상속 +ui.reference.inheritedMembers: 상속된 멤버 +ui.reference.interfaces: 인터페이스 +ui.reference.metadata: 형식 메타데이터 +ui.reference.methods: 메서드 +ui.reference.namespace: 네임스페이스 +ui.reference.open: "{name} 참조 열기" +ui.reference.operators: 연산자 +ui.reference.parameters: 매개 변수 +ui.reference.properties: 속성 +ui.reference.related: 참고 항목 +ui.reference.relationships: 상속 및 메타데이터 +ui.reference.remarks: 설명 +ui.reference.returns: 반환 값 +ui.reference.structs: 구조체 +ui.reference.typeParameters: 형식 매개 변수 +ui.reference.value: 값 +ui.reference.values: 값 +ui.search.close: 검색 닫기 +ui.search.empty: “{query}”에 대한 결과가 없습니다. +ui.search.hint: 튜토리얼, 개념, 예제 및 API 참조를 검색합니다. +ui.search.loading: 검색 로드 중… +ui.search.more: 결과 더 보기 +ui.search.pending: 검색 중… +ui.search.placeholder: 무엇을 찾으시나요? +ui.search.resultCount: "결과: {count}개" +ui.search.title: 문서 검색 +ui.search.unavailable: 검색을 사용할 수 없습니다. 아래 페이지를 계속 열 수 있습니다. diff --git a/documents/locales/pt-BR/strings.yml b/documents/locales/pt-BR/strings.yml new file mode 100644 index 00000000..9309f2f9 --- /dev/null +++ b/documents/locales/pt-BR/strings.yml @@ -0,0 +1,604 @@ +### YamlMime:Resources +concepts.execution.context.description: Um {graphicsContext} representa um dispositivo de backend e fornece suas filas de gráficos, computação e transferência. Crie os buffers, texturas, shaders e pipelines para uma carga de trabalho por meio do mesmo contexto. Um recurso ou handle criado por outro contexto não pode ser simplesmente vinculado aos buffers de comandos deste. +concepts.execution.context.details: Escolha o backend para a plataforma e a superfície de apresentação. A API permanece compartilhada, mas o suporte ao dispositivo ainda é importante. {capabilities} expõe o nome do dispositivo e os sinalizadores {rayTracingSupported} e {meshShadingSupported}. Verifique o sinalizador correspondente antes de criar uma carga de trabalho opcional, como fazem os exemplos {link} e {detail}. Esses sinalizadores não são uma lista completa de restrições de formato, memória ou plataforma. +concepts.execution.context.details.detail: sombreamento de malhas +concepts.execution.context.details.link: traçado de raios +concepts.execution.context.title: O contexto conecta recursos e filas +concepts.execution.description: Uma aplicação Zenith.NET cria recursos de GPU, grava comandos que os utilizam e envia esses comandos para uma fila. A CPU pode continuar enquanto a GPU executa o envio. Mantenha os recursos válidos até que esse trabalho seja concluído, mesmo após as chamadas de gravação terem retornado. +concepts.execution.ownership.description: "Aqui, propriedade significa responsabilidade de descarte. Uma referência C# mantém um objeto gerenciado acessível; ela não impede que um {dispose} explícito destrua o recurso nativo. Da mesma forma, enviar um comando que usa um buffer não transfere a propriedade desse buffer para a fila." +concepts.execution.ownership.details: No desligamento, pare de enviar novos trabalhos, aguarde os últimos usos em cada fila envolvida, libere os recursos da aplicação e, em seguida, descarte o contexto. O descarte do contexto libera suas próprias filas e auxiliares internos; ele não espera todo o trabalho da aplicação nem descarta todos os recursos criados por ela. +concepts.execution.ownership.guidance: Aplique as mesmas regras de tempo de vida durante a renderização. Guarde o valor de conclusão do último uso de um recurso para saber quando seus bytes podem ser sobrescritos ou quando o recurso pode ser substituído. Consulte {link} para visualizações e tempos de vida de recursos de suporte. +concepts.execution.ownership.guidance.link: Gerenciamento de recursos +concepts.execution.ownership.table.applicationResources.object: Recursos criados pela aplicação +concepts.execution.ownership.table.applicationResources.ownership: A aplicação os descarta após seu último uso na GPU. +concepts.execution.ownership.table.commandBuffers.object: Buffers de comandos emprestados +concepts.execution.ownership.table.commandBuffers.ownership: A fila os gerencia e recicla. +concepts.execution.ownership.table.headings.object: Objeto +concepts.execution.ownership.table.headings.ownership: Quem o libera? +concepts.execution.ownership.table.queues.object: Filas do contexto e suas linhas do tempo +concepts.execution.ownership.table.queues.ownership: O contexto e as filas os gerenciam. +concepts.execution.ownership.table.swapChainDrawable.ownership: A cadeia de troca o gerencia. +concepts.execution.ownership.title: Manter a propriedade separada da conclusão na GPU +concepts.execution.pipelines.description: Uma pipeline gráfica combina shaders, o layout de entrada de vértices, a regra para montar vértices em primitivas, formatos de anexo e estado de renderização. Defina-a antes de vincular dados de vértices, índices ou constantes e emitir comandos de desenho. Seus formatos de anexo e contagem de amostras devem corresponder aos anexos da passagem de renderização. +concepts.execution.pipelines.details: Uma pipeline de computação fornece o ponto de entrada do shader para um dispatch, que inicializa grupos de threads de GPU. Defina-a e defina suas constantes antes do dispatch. Dispatches de computação pertencem ao exterior das passagens de renderização gráfica. Mudar a pipeline é uma mudança em como os comandos subsequentes interpretam suas entradas; vincule os dados necessários para a pipeline selecionada antes de usá-la. +concepts.execution.pipelines.guidance: O {link} mostra a sequência gráfica completa. O {detail} grava um dispatch seguido por uma passagem gráfica que exibe o resultado. +concepts.execution.pipelines.guidance.detail: exemplo de computação +concepts.execution.pipelines.guidance.link: callback de renderização do triângulo +concepts.execution.pipelines.title: Uma pipeline determina como os comandos interpretam os dados +concepts.execution.queues.description: Comece com {graphicsQueue} quando um quadro combinar desenho, computação e cópias. Manter o trabalho dependente em uma única fila torna sua ordenação mais fácil de acompanhar. +concepts.execution.queues.details: Uma fila aceita lotes de comandos para execução. Filas separadas não correspondem necessariamente a mecanismos de hardware separados, portanto seus trabalhos podem não ser executados simultaneamente. Use outra fila quando a carga de trabalho puder se beneficiar da sobreposição e adicione uma dependência explícita quando uma fila consumir os resultados de outra fila. +concepts.execution.queues.guidance: Quando comandos posteriores dependem de gravações anteriores, a aplicação também deve garantir que essas gravações estejam disponíveis para os comandos posteriores. Enviar ambos os buffers de comandos para a mesma fila não estabelece automaticamente todas as dependências desse tipo. Comandos podem usar diferentes estágios de GPU, e acessos posteriores podem precisar de uma barreira ou transição de textura. {link} explica a distinção entre ordem de envio e visibilidade de recursos. +concepts.execution.queues.guidance.link: Sincronização +concepts.execution.queues.table.computeQueue.workToRecord: Dispatches de computação e trabalho de transferência compatível, sem passagens de renderização gráfica. +concepts.execution.queues.table.graphicsQueue.workToRecord: Passagens de renderização e desenho, além de operações de computação e transferência usadas pelo quadro. +concepts.execution.queues.table.headings.queue: Fila +concepts.execution.queues.table.headings.workToRecord: Trabalho a gravar +concepts.execution.queues.table.transferQueue.workToRecord: Trabalho de envio, download e cópia, sem desenho ou dispatches de computação. +concepts.execution.queues.title: Escolher uma fila para o trabalho que ela executará +concepts.execution.recording.context: A fila faz a sondagem de conclusão e recicla buffers de comandos finalizados. Chame {queueCommandBuffer} para cada nova gravação; ele pode retornar uma instância reciclada. Não descarte um buffer de comandos emprestado, não o envie duas vezes nem continue gravando nele após o envio. Grave um determinado buffer de comandos a partir de uma única thread por vez; o bloqueio interno da fila não protege contra edições simultâneas em um buffer de comandos. +concepts.execution.recording.description: "{queueCommandBuffer} retorna um {commandBuffer} com a gravação já iniciada. Grave os comandos e suas dependências, depois chame {submit} uma vez. O envio encerra a gravação e retorna um {timelineValue} identificando um ponto de conclusão nessa fila." +concepts.execution.recording.details: "Por exemplo, após gravar um quadro em {commandBuffer}, o triângulo o envia e aguarda a conclusão com:" +concepts.execution.recording.guidance: "{submit} agenda o trabalho; {wait} impede que a CPU continue até que esse envio seja concluído. Gravar um desenho, encerrar uma passagem de renderização e enviar um buffer de comandos são operações separadas. Nem gravar o desenho nem encerrar a passagem aguardam a GPU." +concepts.execution.recording.title: A gravação não executa comandos +concepts.execution.title: Modelo de execução +concepts.platforms.description: Escolha se sua aplicação possui a janela nativa e o loop de quadros ou se utiliza um controle de renderização de interface. Essa escolha determina quem obtém a textura de saída, envia comandos e apresenta o resultado. A textura de saída é a textura usada como saída do quadro atual. Tarefas gráficas e de computação fora da tela não precisam de janela ou cadeia de troca. +concepts.platforms.frame.context: Adicione suas vinculações de pipeline e comandos de desenho dentro dessa passagem. Encerre a passagem antes de retornar. Não envie o buffer de comandos fornecido nem apresente de forma independente, e não descarte o buffer de comandos ou a textura de saída. Se o seu manipulador usar a textura de saída em outro layout, retorne-a para {colorAttachment} para a transição final do controle. +concepts.platforms.frame.description: As integrações implementam {iZenithView}. A aplicação fornece seu {graphicsContext}, atualiza dados de cena em {updateRequested} e grava a renderização em {renderRequested} usando {renderEventArgs}. +concepts.platforms.frame.details: "O controle gerencia o ciclo completo de cada quadro. Ele obtém a textura de saída e o buffer de comandos, faz a transição da textura para {colorAttachment}, chama os manipuladores e executa o envio e a apresentação exigidos pelo framework." +concepts.platforms.frame.guidance: "Para uma {iZenithView} inicializada chamada {view}, com um contexto atribuído, este manipulador grava uma passagem de limpeza completa. Requer {usingZenithNET}:" +concepts.platforms.frame.notes: Os controles transitam de {undefined} no início de cada quadro, portanto as aplicações não podem confiar na preservação do conteúdo anterior da textura de saída. Limpe ou renderize a imagem necessária a cada quadro. Mantenha acumulação persistente ou renderização em cache em uma textura de propriedade da aplicação e, em seguida, exiba essa textura por meio da visualização. +concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat} fornece o formato de cor padrão das integrações. Verifique a textura de saída real do evento ao fazer a correspondência de formatos de anexos, contagens de amostras e dimensões." +concepts.platforms.frame.title: Gravar no quadro fornecido por um controle de interface +concepts.platforms.integration.context: WinForms, WPF e o caminho WinUI do Windows exigem Windows. Aplicações MAUI precisam da carga de trabalho de sua plataforma de destino e devem registrar o manipulador de controle com {useZenithView}; consulte {extensionsCs}. O suporte ao framework e o suporte ao backend devem ser atendidos. +concepts.platforms.integration.description: "Os controles compartilham a interface de eventos, mas nem todos apresentam da mesma maneira:" +concepts.platforms.integration.details: A leitura de bitmap (bitmap readback) copia os pixels renderizados para a memória da CPU antes que a interface os exiba. A interoperabilidade por textura compartilhada evita essa leitura, mas ainda pode exigir cópias e sincronização na GPU. A interface compartilhada {renderRequested}, portanto, não implica custos de apresentação idênticos ou requisitos de interoperabilidade nativa idênticos. +concepts.platforms.integration.guidance: "Use o pacote para o framework da aplicação; por exemplo:" +concepts.platforms.integration.table.avalonia.integration: Avalonia +concepts.platforms.integration.table.avalonia.presentation: Renderiza em uma textura e faz download dos pixels em um {writeableBitmap}. Consulte {zenithViewCs} e {surfaceCs}. +concepts.platforms.integration.table.headings.integration: Integração +concepts.platforms.integration.table.headings.presentation: Como sua imagem chega à interface +concepts.platforms.integration.table.maui.integration: .NET MAUI +concepts.platforms.integration.table.maui.presentation: Usa superfícies nativas no Android, iOS e Mac Catalyst, e composição de textura compartilhada no Windows. Consulte as {link}. +concepts.platforms.integration.table.maui.presentation.link: implementações de plataforma +concepts.platforms.integration.table.uno.integration: Caminho Uno +concepts.platforms.integration.table.uno.presentation: Faz download dos pixels em um {writeableBitmap}. Consulte {zenithViewUnoCs}. +concepts.platforms.integration.table.winForms.integration: WinForms +concepts.platforms.integration.table.winForms.presentation: Cria uma cadeia de troca do Zenith.NET para o {hWND} do controle. Consulte {zenithViewCs}. +concepts.platforms.integration.table.winUI.integration: WinUI no Windows +concepts.platforms.integration.table.winUI.presentation: Renderiza em uma textura Direct3D 11 compartilhada importada e depois copia para uma cadeia de troca de composição conectada a {swapChainPanel}. Consulte {zenithViewWinUICs}. +concepts.platforms.integration.table.wpf.integration: WPF +concepts.platforms.integration.table.wpf.presentation: Importa uma textura Direct3D 11 compartilhada e depois copia por meio da interoperabilidade Direct3D para uma superfície exibida por {d3DImage}. Consulte {surfaceCs}. +concepts.platforms.integration.title: Escolher o caminho de apresentação bem como o framework +concepts.platforms.lifecycle.context: Para uma visualização de interface, use {descWidth}, {descHeight}, {descFormat} e {descSampleCount} da textura de saída do evento ao criar recursos de renderização correspondentes. O controle determina a resolução dessa textura de saída; não presuma que suas dimensões lógicas ou escala de tela sejam sempre iguais às dimensões da textura. +concepts.platforms.lifecycle.description: Para uma cadeia de troca nativa, passe as dimensões do framebuffer em pixels. Os tamanhos de janela expressos em unidades lógicas podem ser diferentes quando o dimensionamento de tela está ativado. Ignore framebuffers de tamanho zero, redimensione a cadeia de troca quando o tamanho em pixels mudar e obtenha {swapChainDrawable} para cada quadro. A textura de saída pertence à cadeia de troca e pode mudar após a apresentação ou o redimensionamento. +concepts.platforms.lifecycle.details: "{swapChainResize} altera as dimensões da superfície existente. {swapChainRefresh} substitui a descrição da superfície, incluindo seus handles nativos. Antes de qualquer operação, conclua os usos pendentes dos recursos afetados. Descarte a cadeia de troca antes de destruir seu destino de apresentação nativo." +concepts.platforms.lifecycle.guidance: Recrie texturas de profundidade ou fora da tela de propriedade da aplicação cujo tamanho segue a janela e atualize constantes contendo seus handles. Uma pipeline pode permanecer em uso durante uma mudança de tamanho quando seus formatos de anexos e contagem de amostras permanecerem compatíveis. O {link} mantém sua pipeline enquanto substitui sua textura de profundidade. +concepts.platforms.lifecycle.guidance.link: renderizador de cubo giratório +concepts.platforms.lifecycle.title: Manter o tamanho e o tempo de vida da textura de saída com seu host +concepts.platforms.ownership.description: A aplicação é proprietária do contexto que atribui e dos recursos que cria para renderização. O controle é proprietário de seus próprios recursos de apresentação. Alterar a propriedade {graphicsContext} da visualização faz com que o agendador recrie os recursos do controle; isso não recria as pipelines, buffers ou texturas da aplicação para o novo contexto. +concepts.platforms.ownership.details: Coordene a substituição de recursos com o ciclo de vida do quadro da visualização. Interrompa a atividade de quadros da visualização e conclua os usos pendentes da GPU antes de descartar recursos da aplicação ou o contexto atribuído. Remover uma visualização não transfere a propriedade do contexto para o controle. +concepts.platforms.ownership.guidance: O {frameSchedulerCs} compartilhado distribui o trabalho de quadros por meio do despachante de interface da visualização. Mantenha os manipuladores de quadro focados na atualização e gravação do quadro; trabalho prolongado da CPU ali também atrasa a interface. +concepts.platforms.ownership.title: Manter os recursos da aplicação fora da propriedade do controle +concepts.platforms.surface.context: Uma biblioteca de janelas ou framework de interface suportar um sistema operacional não garante que o backend de GPU selecionado esteja disponível nele. Recursos de dispositivo, drivers e suporte a superfícies nativas ainda devem corresponder. Verifique o traçado de raios e o sombreamento de malhas opcionais por meio de {contextCapabilities} antes de criar essas cargas de trabalho. +concepts.platforms.surface.description: O {link} usa o Silk.NET para criar uma janela e processar eventos. O Zenith.NET se conecta a essa janela por meio de uma descrição de {surface} e uma {swapChain}. Uma superfície contém handles e dimensões nativas; construir a descrição não cria nem possui a janela do sistema operacional. +concepts.platforms.surface.description.link: triângulo +concepts.platforms.surface.details: "O handle deve corresponder ao backend selecionado:" +concepts.platforms.surface.guidance: O arquivo {appCs} do tutorial mostra as opções do Windows, macOS e X11. Seu host Linux fornece handles Xlib; usá-lo em uma sessão Wayland requer o XWayland. Uma aplicação nativa Wayland forneceria handles diferentes por meio de {surfaceWayland}. +concepts.platforms.surface.table.android.backend: Vulkan no Android. +concepts.platforms.surface.table.apple.backend: Metal nas plataformas Apple. +concepts.platforms.surface.table.headings.backend: Caminho do backend +concepts.platforms.surface.table.headings.factory: Fábrica de superfícies +concepts.platforms.surface.table.headings.handles: Handles fornecidos pelo host +concepts.platforms.surface.table.wayland.backend: Vulkan com um host nativo Wayland. +concepts.platforms.surface.table.wayland.handles: Display e superfície Wayland +concepts.platforms.surface.table.win32.backend: DirectX 12 ou Vulkan no Windows. +concepts.platforms.surface.table.xlib.backend: Vulkan no Linux com X11 ou XWayland. +concepts.platforms.surface.table.xlib.handles: Display e janela X11 +concepts.platforms.surface.title: Fornecer uma superfície nativa quando a aplicação possui a apresentação +concepts.platforms.title: Integração de plataforma +concepts.resources.allocation.context: "Comece com recursos criados pelo contexto, a menos que precise de um alocador próprio. Ao usar um heap, aguarde a conclusão de todo o trabalho de GPU que usa seus recursos; depois libere os recursos posicionados e, por último, o próprio heap." +concepts.resources.allocation.description: "Um {heap} fornece memória na qual você posiciona recursos em deslocamentos explícitos em bytes. A aplicação escolhe esses deslocamentos e acompanha quais regiões estão em uso." +concepts.resources.allocation.details: "Antes de posicionar um recurso, use {contextGetSizeAndAlignment} com sua descrição exata de buffer ou textura. Escolha um deslocamento múltiplo do alinhamento retornado, reserve o tamanho retornado e mantenha o recurso dentro do tamanho total do heap. Alocações ainda em uso não devem se sobrepor. O armazenamento de texturas pode incluir preenchimento e alinhamento específicos do backend; multiplicar a quantidade de pixels pelos bytes por pixel não calcula o tamanho da alocação." +concepts.resources.allocation.guidance: "Para buffers posicionados, mantenha a residência do buffer consistente com a do heap. Use heaps exclusivos de GPU para as texturas de GPU comuns descritas aqui. Tamanho e alinhamento são requisitos de posicionamento, não uma garantia de que qualquer recurso possa ser colocado em qualquer heap em todos os backends." +concepts.resources.allocation.title: Posicionar recursos em um heap quando o controle de alocação for necessário +concepts.resources.bufferUsages.table.constant.role: Parâmetros de shader lidos por meio de uma vinculação de buffer de constantes. +concepts.resources.bufferUsages.table.headings.role: "Função" +concepts.resources.bufferUsages.table.headings.usage: Uso +concepts.resources.bufferUsages.table.index.role: Índices usados pelo desenho indexado. +concepts.resources.bufferUsages.table.indirect.role: "Argumentos lidos por comandos de desenho ou dispatch indiretos." +concepts.resources.bufferUsages.table.none.role: "Nenhum sinalizador de uso de buffer é declarado." +concepts.resources.bufferUsages.table.storageReadOnly.role: "Dados de buffer acessados por uma vinculação de shader somente leitura." +concepts.resources.bufferUsages.table.storageReadWrite.role: "Dados de buffer acessados por uma vinculação de shader de leitura e gravação." +concepts.resources.bufferUsages.table.transferDst.role: "Armazenamento de destino para uma cópia de GPU." +concepts.resources.bufferUsages.table.transferSrc.role: "Dados de origem para uma cópia de GPU." +concepts.resources.bufferUsages.table.vertex.role: Atributos de vértice buscados para desenho. +concepts.resources.bufferUsages.title: Usos de buffer +concepts.resources.description: "Escolha a descrição do recurso de acordo com as operações que o usarão. Uma textura que recebe renderização, é amostrada por um shader e é lida pela CPU precisa declarar os três usos e estabelecer a sincronização entre eles. O posicionamento da memória e o tempo de vida do recurso são decisões adicionais." +concepts.resources.memory.context: Para um buffer acessível pela CPU, {map} fornece um endereço à CPU. Ele não espera que a GPU pare de acessar os mesmos bytes. {unmap} da mesma forma não envia trabalho nem espera pela conclusão. Antes de sobrescrever dados graváveis pela CPU, conclua as leituras de GPU que ainda precisam do conteúdo antigo. +concepts.resources.memory.description: "Um {bufferDesc} tem um campo {residency}. Escolha-o de acordo com a forma como a CPU e a GPU acessarão os dados:" +concepts.resources.memory.details: A residência descreve o acesso pretendido da CPU à alocação. Ela não implica que cada dispositivo tenha memórias físicas separadas de CPU e GPU. O triângulo usa {cpuWriteOnly} para inicializar um pequeno buffer de vértices diretamente. Uma malha estática grande pode, em vez disso, se beneficiar de armazenamento exclusivo de GPU com um upload único. +concepts.resources.memory.guidance: "{textureDesc} não tem campo de residência. Texturas comuns criadas por contexto usam armazenamento de GPU. Sua API pública fornece operações de upload e download para transferências de dados da CPU, sem expor um método de mapeamento direto. Heaps explícitos fornecem controle de posicionamento, descrito abaixo." +concepts.resources.memory.table.cpuReadOnly.cPUAccess: "Ler a memória mapeada após a conclusão da cópia de GPU." +concepts.resources.memory.table.cpuReadOnly.typicalRole: "Dados produzidos pela GPU para leitura na CPU" +concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "Gravar na memória mapeada após o término das leituras anteriores da GPU." +concepts.resources.memory.table.cpuWriteOnly.typicalRole: "Dados fornecidos ou atualizados pela CPU" +concepts.resources.memory.table.gpuOnly.cPUAccess: "Transferir bytes por meio de um buffer de upload ou de leitura da GPU." +concepts.resources.memory.table.gpuOnly.typicalRole: "Geometria estática e dados de trabalho da GPU" +concepts.resources.memory.table.headings.cPUAccess: Acesso da CPU +concepts.resources.memory.table.headings.residency: Residência +concepts.resources.memory.table.headings.typicalRole: Função típica +concepts.resources.memory.title: "Escolher a memória conforme o acesso necessário da CPU" +concepts.resources.textureUsages.description: "Os sinalizadores de uso de transferência descrevem a direção das cópias de GPU. O acesso da CPU é uma decisão separada de posicionamento de memória, descrita abaixo." +concepts.resources.textureUsages.details: "Combinar sinalizadores de uso declara várias funções; não executa as operações nem ordena seus acessos. As texturas ainda precisam de {link} adequados, e seus formatos devem oferecer suporte aos usos solicitados no dispositivo escolhido." +concepts.resources.textureUsages.details.link: "layout e sincronização" +concepts.resources.textureUsages.table.colorAttachment.role: "Um anexo de cor em uma passagem de renderização." +concepts.resources.textureUsages.table.depthStencilAttachment.role: "Um anexo de profundidade e estêncil em uma passagem de renderização." +concepts.resources.textureUsages.table.headings.role: "Função" +concepts.resources.textureUsages.table.headings.usage: Uso +concepts.resources.textureUsages.table.none.role: "Nenhum sinalizador de uso de textura é declarado." +concepts.resources.textureUsages.table.sampled.role: "Dados de textura lidos por uma vinculação de textura amostrada." +concepts.resources.textureUsages.table.storage.role: "Dados de textura acessados por uma vinculação de textura de armazenamento para leituras ou gravações de shaders." +concepts.resources.textureUsages.table.transferDst.role: "Armazenamento da imagem de destino para uma cópia de GPU." +concepts.resources.textureUsages.table.transferSrc.role: "Dados da imagem de origem para uma cópia de GPU." +concepts.resources.textureUsages.title: Usos de textura +concepts.resources.title: Gerenciamento de recursos +concepts.resources.transfers.context: Um download grava uma cópia de GPU no armazenamento interno de leitura. A biblioteca copia esses bytes para o destino de CPU fornecido quando redefine o buffer de comandos concluído para reutilização. Mantenha o destino alocado e mantenha a memória gerenciada fixada até que o {wait} do valor de envio retorne. +concepts.resources.transfers.description: "Um upload copia dados da CPU para um recurso de GPU; um download copia dados do recurso de volta para a memória da CPU. Os métodos do próprio recurso concluem essa transferência antes de retornar:" +concepts.resources.transfers.details: "Essas esperas cobrem apenas a transferência enviada pelos métodos. Elas não descobrem dependências de outra fila que já estivesse lendo ou gravando o recurso. Estabeleça essas dependências antes de chamar o método do recurso. Uma cópia direta por memória mapeada também depende de quem chama para garantir a conclusão do trabalho de GPU correspondente." +concepts.resources.transfers.guidance: "Use {commandBufferUpload} ou {commandBufferDownload} quando as cópias precisarem ser gravadas com outros trabalhos. O tempo de vida de seus ponteiros difere:" +concepts.resources.transfers.item: "Um upload copia a origem da CPU para um buffer interno de upload, também chamado de memória de staging, durante a chamada. O ponteiro de origem só precisa permanecer válido durante essa chamada." +concepts.resources.transfers.notes: "Para uma textura, o passo de linha é a distância em bytes entre linhas consecutivas dos dados da CPU, e o passo de fatia é a distância em bytes entre fatias de profundidade consecutivas. Eles não representam o layout interno da textura na memória da GPU. Consulte {link} para distinguir a conclusão da GPU da disponibilidade dos dados lidos." +concepts.resources.transfers.notes.link: Sincronização +concepts.resources.transfers.table.bufferDownload.transfer: Cópia direta da CPU para {cpuReadOnly}; caso contrário, envia um download na fila de transferência e aguarda. +concepts.resources.transfers.table.bufferUpload.transfer: Cópia direta da CPU para {cpuWriteOnly}; caso contrário, envia um upload na fila de transferência e aguarda. +concepts.resources.transfers.table.headings.method: Método +concepts.resources.transfers.table.headings.transfer: "Como os dados são transferidos" +concepts.resources.transfers.table.textureTransfers.method: "{textureUpload} / {textureDownload}" +concepts.resources.transfers.table.textureTransfers.transfer: "Usa a fila gráfica, faz a transição do sub-recurso escolhido para o layout de cópia, depois para o layout final solicitado, e aguarda a conclusão da transferência." +concepts.resources.transfers.title: "Escolher entre transferências imediatas e transferências gravadas" +concepts.resources.usages.description: "{bufferUsages} e {textureUsages} são enumerações de sinalizadores que declaram as funções pretendidas de um recurso. Elas são atribuídas a {bufferDescUsages} e {textureDescUsages}, respectivamente. Uma enumeração de sinalizadores permite que vários membros sejam combinados com {value} quando um recurso tem mais de uma função." +concepts.resources.usages.title: Declarar os usos necessários antes de criar um recurso +concepts.resources.views.description: Uma {bufferView} descreve uma região de buffer e sua interpretação. Uma {textureView} seleciona um tipo de textura compatível, formato e intervalo de sub-recursos. Uma visualização compartilha o armazenamento subjacente; ela não copia os dados nem adiciona usos que faltavam quando o recurso foi criado. Seu intervalo também não é uma garantia portátil de verificação de limites no shader. +concepts.resources.views.details: "Use o handle do próprio recurso para sua visualização padrão ou crie uma visualização quando precisar de outra região ou interpretação compatível. Mantenha referências C# à visualização e ao recurso subjacente enquanto o trabalho de GPU puder usá-los; um handle de recurso sozinho não mantém nenhum dos objetos vivo. Libere-os somente após seu último uso na GPU. Ao substituir qualquer um deles, atualize as constantes que contêm seu antigo {link}." +concepts.resources.views.details.link: "handle de recurso" +concepts.resources.views.guidance: O {link} mostra uma textura de profundidade substituída no redimensionamento. O {detail} mostra uma textura de entrada mantida separada de sua saída gravável. Ambos fazem o tempo de vida do recurso acompanhar o trabalho que realmente o utiliza. +concepts.resources.views.guidance.detail: exemplo de computação +concepts.resources.views.guidance.link: renderizador de cubo giratório +concepts.resources.views.title: "Manter visualizações e seus recursos subjacentes utilizáveis juntos" +concepts.shaders.binding.context: "No exemplo de computação, {input} é preenchido com {inputTextureSampledHandle} e {output} com {outputTextureStorageHandle}. O {descriptorHandle} tipado do Slang informa ao shader como acessar cada recurso:" +concepts.shaders.binding.description: "{setConstantBuffer} vincula um buffer e um deslocamento de bytes para os dados de constantes da pipeline atual. Ele vincula armazenamento visível pela GPU existente; não faz upload de um valor C#. Preencha o buffer primeiro e garanta que os leitores anteriores da GPU tenham terminado antes de sobrescrever seus bytes." +concepts.shaders.binding.details: "Defina a pipeline antes de seu buffer de constantes. Para uma carga de trabalho de computação com recursos já criados e carregados, a gravação usa esta ordem:" +concepts.shaders.binding.guidance: Este fragmento assume um {commandBuffer} em gravação, uma {computePipeline}, um {constantBuffer} carregado com uso {bufferUsagesConstant} e as contagens de grupos de threads para a carga de trabalho. O deslocamento 0 vincula o início do buffer. Se vários registros de dados de constantes compartilharem um buffer, o deslocamento inicial de cada registro deverá atender ao alinhamento de vinculação do backend. Esse requisito é independente do layout dos campos dentro do registro. +concepts.shaders.binding.notes: "{resourceHandle} armazena dois campos de 32 bits, mas sua interpretação pertence ao backend. Não o trate como um índice de descritor universal, endereço ou valor que possa ser transferido entre contextos. Um handle não cria um recurso, não adiciona um uso ausente nem realiza sincronização." +concepts.shaders.binding.reference: Mantenha referências ao recurso e a qualquer visualização usada para obter seu handle, e descarte-os apenas após a conclusão do último uso do shader. Ao substituir uma textura ou visualização, atualize as constantes que contêm seu handle antigo. O {link} explica essa relação de tempo de vida. +concepts.shaders.binding.reference.link: Gerenciamento de recursos +concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: Ler elementos estruturados do tipo de shader {t}. +concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: Ler ou gravar elementos estruturados do tipo de shader {t}. +concepts.shaders.binding.table.headings.access: Acesso pretendido +concepts.shaders.binding.table.headings.cHandle: "Handle C#" +concepts.shaders.binding.table.headings.slangFieldType: Tipo de campo Slang +concepts.shaders.binding.table.samplerHandle.access: Fornecer estado de amostragem de textura. +concepts.shaders.binding.table.textureSampledHandle.access: Ler uma textura. +concepts.shaders.binding.table.textureStorageHandle.access: Ler ou gravar uma textura de armazenamento. +concepts.shaders.binding.title: Vincular o buffer de constantes e os recursos que ele descreve +concepts.shaders.compilation.description: "O {zenithCompiler} compila um ponto de entrada nomeado do Slang e retorna uma {shaderDesc}. Use o {graphicsApi} do contexto para que o resultado seja direcionado ao backend que criará o shader: DXIL para DirectX 12, uma biblioteca Metal para Metal ou SPIR-V para Vulkan." +concepts.shaders.compilation.details: "Por exemplo, com um {context} existente e o shader do triângulo copiado ao lado do executável:" +concepts.shaders.compilation.guidance: "{vSMain} deve corresponder exatamente ao nome do ponto de entrada no arquivo de shader. Mantenha os objetos de shader válidos enquanto cria a pipeline e, em seguida, descarte-os após a criação da pipeline, como mostrado em {link}. Execute essa inicialização uma vez em vez de recompilar a cada quadro." +concepts.shaders.compilation.guidance.link: Primeiro triângulo +concepts.shaders.compilation.title: Compilar um ponto de entrada para o contexto selecionado +concepts.shaders.description: "Um shader recebe dados fornecidos pela aplicação. Atributos de vértice descrevem vértices individuais; buffers armazenam parâmetros ou arrays; handles de recursos identificam outros recursos que o shader acessará. As declarações C# e as declarações Slang devem concordar sobre o que esses valores significam. Fazer a correspondência de um nome de campo não é suficiente: layout, acesso a recursos e vinculação precisam coincidir." +concepts.shaders.dispatch.description: "{dispatch} recebe o número de grupos de threads. O ponto de entrada {numthreads} do exemplo de computação executa 16 × 16 threads por grupo. Divida as dimensões da imagem por 16 e arredonde para cima para encontrar as contagens de grupos. Por exemplo, uma imagem de 17 × 19 precisa de 2 × 2 grupos. O shader verifica suas coordenadas de pixel em relação às dimensões da imagem porque os últimos grupos podem conter threads fora da imagem." +concepts.shaders.dispatch.details: O compilador armazena o tamanho de grupo declarado do ponto de entrada em {shaderDescThreadGroupSize}; ele não converte as dimensões em pixels fornecidas ao {dispatch} em contagens de grupos. Use o {computeShaderRendererCs} com seu shader para o exemplo completo de vinculação e dispatch, e {link} antes que outra passagem consuma a saída. +concepts.shaders.dispatch.details.link: Sincronização +concepts.shaders.dispatch.title: Despachar grupos de threads, não pixels +concepts.shaders.layout.context: "As {link} tornam seus deslocamentos explícitos. Esta declaração precisa de {systemRuntimeInteropServices} e {zenithNET} no escopo:" +concepts.shaders.layout.context.link: "constantes C# do exemplo de computação" +concepts.shaders.layout.description: "Para a entrada de vértices, o {inputLayout} da pipeline descreve formatos, deslocamentos, stride e semânticas. A posição {float3} do triângulo seguida por uma cor {float4} ocupa 28 bytes, com a cor no byte 12. {inputLayoutAdd} calcula esse layout compactado; ele não inspeciona a struct C#. Se os campos C# contiverem padding, forneça um layout correspondente em vez de presumir que os campos estão compactados." +concepts.shaders.layout.details: "Buffers de constantes contêm parâmetros de shader, enquanto buffers estruturados contêm arrays de elementos de um tipo declarado. Ambos são lidos de acordo com suas declarações Slang. Eles não usam {inputLayout}. Verifique deslocamentos de campos e tamanhos de elementos para a representação de shader compilada, incluindo padding. Um tipo C# não gerenciado é adequado para cópia como bytes, mas isso por si só não prova que ele corresponda a um tipo de shader. Em particular, não aplique o layout {float3} compactado de um vértice a todos os buffers de shader." +concepts.shaders.layout.guidance: Um handle de recurso é um valor pequeno que faz referência a um recurso existente. Copiar o handle para um buffer de constantes não copia o conteúdo do recurso. +concepts.shaders.layout.notes: "A declaração correspondente em {computeShaderSlang} é:" +concepts.shaders.layout.reference: "As dimensões ocupam os primeiros oito bytes, seguidas por dois handles de recursos de oito bytes. O exemplo em C# reserva 256 bytes no total. Esse tamanho é o tamanho de armazenamento escolhido pelo exemplo, não uma regra de que todas as structs Slang ou cargas úteis de constantes devam ocupar 256 bytes. Preencher o tamanho total também não corrige um campo no deslocamento errado." +concepts.shaders.layout.title: A entrada de vértices e os dados de shaders têm regras de layout diferentes +concepts.shaders.matrices.description: "O compilador solicita armazenamento de matrizes por linhas (row-major), mantendo os elementos de cada linha contíguos. O {link} posiciona três valores {matrix4x4} nos deslocamentos 0, 64 e 128. Seu {detail} usa {mulVectorMatrix} na ordem modelo, visualização e projeção." +concepts.shaders.matrices.description.detail: shader +concepts.shaders.matrices.description.link: renderizador de cubo giratório +concepts.shaders.matrices.details: A ordem de armazenamento determina como os elementos da matriz ocupam a memória; a ordem de multiplicação determina a transformação. Mantenha ambos os lados consistentes. Adicionar uma transposição sem verificar essas duas opções pode ocultar uma inconsistência enquanto introduz outra. +concepts.shaders.matrices.title: Manter o armazenamento e a multiplicação de matrizes consistentes +concepts.shaders.title: Dados de shaders e vinculação +concepts.synchronization.backends.description: DirectX 12 e Vulkan codificam transições de textura com informações de layout e acesso. O Metal não tem nenhuma operação na implementação de {transition} do Zenith.NET. O Metal agrupa o trabalho gravado em codificadores de renderização e computação. O backend insere barreiras de visibilidade quando encerra esses grupos, disponibilizando gravações anteriores para trabalhos posteriores. Chamadas explícitas a {barrier} lidam com dependências como dispatches sucessivos de computação dentro do mesmo codificador. +concepts.synchronization.backends.details: Essa distinção é importante ao alterar uma carga de trabalho. No {link}, o dispatch é seguido por uma passagem de renderização gráfica, o que também cria um limite de codificador no Metal. Dois dispatches de computação dependentes não criam esse limite apenas alterando o layout declarado da textura. Mantenha as transições exigidas pela API compartilhada e identifique separadamente a dependência entre os comandos reais de produção e consumo. +concepts.synchronization.backends.details.link: exemplo de computação +concepts.synchronization.backends.title: Uma transição não é idêntica em todos os backends +concepts.synchronization.barriers.context: "{barrierStagesAll} é um escopo mais amplo, não um detector automático de dependências. Selecione estágios que realmente cubram o trabalho e use-os apenas em uma fila que suporte essas operações." +concepts.synchronization.barriers.description: "Considere dois dispatches de computação: o primeiro grava dados de simulação e o segundo lê esses dados para executar a etapa seguinte. Ambos usam buffers de armazenamento, portanto não há layout de textura a ser alterado. Insira isto entre os dispatches em seu buffer de comandos:" +concepts.synchronization.barriers.details: O primeiro argumento identifica o estágio produtor e o segundo o estágio consumidor. A barreira estabelece a dependência correspondente de execução e memória na GPU. O backend traduz esses estágios em suas regras de execução e acesso à memória. Esta barreira não altera o layout de uma textura nem espera por todo o trabalho no dispositivo. +concepts.synchronization.barriers.guidance: "A {link} usa esse padrão entre dispatches dependentes. Coloque a barreira onde ocorre a dependência. Uma barreira gravada depois do consumidor não pode ordenar esse consumidor após um produtor anterior." +concepts.synchronization.barriers.guidance.link: simulação FluidTank +concepts.synchronization.barriers.title: Ordenar comandos dependentes com uma barreira +concepts.synchronization.dependencies.description: Para cada recurso compartilhado, identifique a operação que o acessa primeiro, a operação seguinte e se algum dos acessos grava. Ler os mesmos dados duas vezes não requer ordenação para proteger seu conteúdo, embora alterações de layout ou apresentação possam impor outros requisitos. Uma gravação seguida por uma leitura, uma leitura seguida por uma sobrescrita ou duas gravações podem exigir uma dependência. +concepts.synchronization.dependencies.details: "Em seguida, escolha o mecanismo de acordo com onde essas operações são executadas:" +concepts.synchronization.dependencies.guidance: Esses mecanismos são relacionados, mas não intercambiáveis. Enviar comandos em ordem não substitui todas as dependências de memória. Uma espera de fila não declara um novo layout de textura, e uma barreira de comandos não aguarda na thread de CPU chamadora. +concepts.synchronization.dependencies.table.cpuAccess.mechanism: Chamar {wait} no valor de conclusão relevante. +concepts.synchronization.dependencies.table.cpuAccess.situation: A CPU deve esperar antes de acessar ou liberar dados +concepts.synchronization.dependencies.table.crossQueue.mechanism: Passar seu {timelineValue} para o {submit} do buffer de comandos consumidor. +concepts.synchronization.dependencies.table.crossQueue.situation: Um envio em outra fila produz os dados +concepts.synchronization.dependencies.table.headings.mechanism: Mecanismo +concepts.synchronization.dependencies.table.headings.situation: Situação +concepts.synchronization.dependencies.table.layoutChange.mechanism: "{commandBufferTransition} com seus layouts anterior e seguinte." +concepts.synchronization.dependencies.table.layoutChange.situation: Um sub-recurso de textura altera como é usado +concepts.synchronization.dependencies.table.pipelineStages.mechanism: "{commandBufferBarrier} com os estágios produtor e consumidor." +concepts.synchronization.dependencies.table.pipelineStages.situation: Estágios dependentes da GPU em um fluxo de comandos +concepts.synchronization.dependencies.title: Começar com o produtor e o consumidor +concepts.synchronization.description: Um comando que lê dados gravados por um comando anterior depende de que essas gravações estejam concluídas e visíveis para ele. Quem grava é o produtor; quem lê é o consumidor. A CPU também precisa de um ponto de conclusão antes de ler, sobrescrever ou liberar dados compartilhados. O Zenith.NET fornece barreiras, transições de textura e linhas do tempo para essas diferentes dependências. +concepts.synchronization.layouts.context: "{undefined} significa que o conteúdo anterior não precisa ser preservado. É adequado para uma nova imagem ou um anexo que será totalmente limpo. Não é uma forma de evitar rastrear o layout de uma imagem cujo conteúdo será carregado, amostrado ou acumulado." +concepts.synchronization.layouts.description: "Sinalizadores de uso descrevem quais funções uma textura suporta. {textureLayout} descreve como um sub-recurso específico será acessado para uma operação. Um sub-recurso é um nível mip e uma camada de array selecionados. Alterar seu layout prepara esse acesso; não converte a textura para um formato de pixel diferente. Por exemplo, o exemplo de computação grava uma textura de saída no layout {storage} e depois a amostra em uma passagem gráfica. Entre esses usos, ele grava:" +concepts.synchronization.layouts.details: Este fragmento assume que {outputTexture} foi criada com uso {sampledStorage} e que seu sub-recurso selecionado está no layout {storage}. {default} seleciona o nível mip 0 e a camada de array 0. A operação não faz a transição de cada mip ou camada de uma textura. +concepts.synchronization.layouts.guidance: A aplicação fornece o layout anterior. {transition} não mantém um rastreador de layout visível pela aplicação nem infere esse valor a partir de comandos anteriores. Rastreie o layout onde quer que um recurso passe entre estágios de renderização. +concepts.synchronization.layouts.title: Rastrear o layout de cada sub-recurso de textura +concepts.synchronization.readback.description: "{isCompleted} apenas consulta se a linha do tempo da GPU atingiu um valor. Ele não recupera buffers de comandos nem copia os dados de download armazenados temporariamente para o ponteiro de destino da aplicação." +concepts.synchronization.readback.details: "{commandBufferDownload} grava primeiro uma cópia no armazenamento interno de leitura. Ao redefinir o buffer de comandos concluído para reutilização, a CPU copia os dados para o ponteiro fornecido. Mantenha esse destino válido e a memória gerenciada fixada até que {wait} retorne para esse envio de download. Só então leia os dados ou libere a memória. Esperar por um envio posterior de outra fila não faz a sondagem da fila que gerencia o download." +concepts.synchronization.readback.guidance: É por isso que sondar {isCompleted} e ler imediatamente o destino de um download assíncrono é insuficiente. O {link} aborda os caminhos de cópia direta e transferência intermediária. +concepts.synchronization.readback.guidance.link: Gerenciamento de recursos +concepts.synchronization.readback.title: A conclusão na GPU e os dados baixados na CPU são etapas separadas +concepts.synchronization.reuse.description: Para um primeiro renderizador, uma espera imediata após cada quadro é direta. Para sobrepor o trabalho, forneça aos quadros pendentes dados mutáveis separados e guarde o valor de conclusão do uso final de cada quadro. Antes de atualizar um buffer de constantes, substituir uma textura ou descartar uma pipeline, conclua todos os acessos pendentes ao recurso afetado. +concepts.synchronization.reuse.details: No redimensionamento ou desligamento, pare novos usos antes de esperar pelos antigos. {swapChainResize}, descarte de recursos e descarte de contexto não servem como esperas gerais para o trabalho da aplicação. O triângulo pode redimensionar com segurança entre callbacks porque cada quadro precedente já concluiu seu envio. +concepts.synchronization.reuse.guidance: O {swapChainPresent} atual também sinaliza e aguarda na fila gráfica após sua operação de apresentação. Portanto, remover a espera de envio explícita do triângulo não estabelece por si só um loop de apresentação sobreposto. Uma espera na fila gráfica também não diz nada sobre trabalhos independentes ainda em execução em outra fila. +concepts.synchronization.reuse.title: Reutilizar dados somente após o seu acesso final +concepts.synchronization.timelines.context: "Antes que a CPU leia, sobrescreva ou libere esses recursos, aguarde seu uso final:" +concepts.synchronization.timelines.description: Uma linha do tempo rastreia a conclusão em uma fila usando valores crescentes. {submit} retorna um {timelineValue} contendo essa linha do tempo e o valor associado ao envio. Valores de conclusão de diferentes linhas do tempo não são comparáveis apenas por seus campos numéricos {value}. +concepts.synchronization.timelines.details: "Suponha que {producer} e {consumer} sejam buffers de comandos já gravados de duas filas do mesmo contexto. O produtor grava dados que o consumidor usa. Envie-os assim:" +concepts.synchronization.timelines.guidance: Passar o valor produzido faz com que a fila consumidora aguarde por ele na GPU. A CPU não chama {producedWait} aqui. Mantenha os recursos compartilhados válidos até que {consumed} seja concluído e grave quaisquer alterações de layout de textura exigidas pelo consumidor. +concepts.synchronization.timelines.notes: "{wait} aguarda o valor da linha do tempo e verifica a fila responsável em busca de envios concluídos. Os buffers de comandos finalizados são redefinidos para reutilização, e seus dados de download armazenados temporariamente são copiados para os destinos de CPU fornecidos. {queueTimelineSignal} também pode enfileirar um ponto de conclusão após o trabalho já enviado para essa fila. Chamar {signal} não significa que a GPU já atingiu o ponto." +concepts.synchronization.timelines.title: Usar uma linha do tempo para conclusão e transferências entre filas +concepts.synchronization.title: Sincronização +home.actions.reference: Navegar na API +home.actions.tutorial: Começar com um triângulo +home.entries.description: Um primeiro quadro. Um exemplo focado. Uma visão detalhada da API. +home.entries.label: Explorar a documentação +home.entries.reference.action: Explorar a API +home.entries.reference.category: Referência +home.entries.reference.description: Encontre os tipos, assinaturas e membros que sustentam sua aplicação. +home.entries.reference.title: Referência da API +home.entries.samples.action: Procurar exemplos +home.entries.samples.category: Exemplos +home.entries.samples.description: Explore técnicas focadas de renderização e computação por meio do código-fonte. +home.entries.samples.title: Exemplos +home.entries.title: Comece a construir. +home.entries.tutorial.action: Iniciar tutorial +home.entries.tutorial.category: Tutorial +home.entries.tutorial.description: Crie uma aplicação de renderização completa, desde a configuração até o primeiro quadro. +home.entries.tutorial.title: Primeiro triângulo +home.introduction.accent: "Em C#." +home.introduction.description: Crie recursos, grave comandos e envie tarefas gráficas ou de computação por meio de uma única API .NET. +home.introduction.title: Crie seu renderizador. +home.meta.description: "Uma API C# consistente para computação e gráficos no DirectX, Metal e Vulkan." +home.scene.description: Estudo de geometria rotativa. Arraste ou use as teclas de direção para ajustar a visualização. +home.scene.label: Exibição de geometria +home.scene.surface: Superfície +home.scene.wireframe: Wireframe +home.title: RHI moderno para .NET +learning.concepts.description: Entenda como comandos, recursos, dados de shader e sincronização se encaixam antes de combinar passagens de renderização. +learning.concepts.execution.description: Grave tarefas na GPU, envie-as e mantenha seus recursos ativos. +learning.concepts.platforms.description: Conecte uma janela nativa ou um controle de renderização de interface. +learning.concepts.resources.description: Escolha usos de recursos, alocação de memória e visualizações. +learning.concepts.shaders.description: "Faça a correspondência de layouts C# e handles de recursos com Slang." +learning.concepts.synchronization.description: Ordene acessos dependentes e saiba quando o trabalho é concluído. +learning.concepts.title: Conceitos fundamentais +learning.description: Comece com um tutorial completo de triângulo. Em seguida, utilize os exemplos focados e os guias conceituais para compreender os recursos, dados e dependências por trás de um renderizador maior. +learning.entries.samples.action: Procurar exemplos +learning.entries.samples.description: "Encontre exemplos em C# e Slang para geometria, computação, consultas de raios e sombreamento de malhas." +learning.entries.tutorial.action: Abrir tutorial +learning.entries.tutorial.description: Crie uma aplicação de console, abra uma janela e desenhe um triângulo. +learning.meta.description: Primeiros passos com o Zenith.NET e exploração do seu modelo de programação. +learning.title: Aprender +reference.description: Consulte tipos de recursos, assinaturas de comandos e integrações de plataforma. +reference.entries.commands.description: Grave comandos de gráficos, computação e transferência. +reference.entries.commands.label: Gravar trabalho +reference.entries.context.description: Crie recursos de GPU para o backend selecionado. +reference.entries.context.label: Comece aqui +reference.meta.description: Explore os tipos e membros no Zenith.NET. +reference.navigation.core: Navegar na API principal. +reference.title: Referência da API +samples.computeShader.description: Converte uma imagem para escala de cinza com um dispatch de computação e exibe a textura resultante. Demonstra handles de recursos para uma textura de entrada amostrada e uma textura de saída gravável, contagens de grupos de threads arredondadas para cima e uma verificação de limites no shader. Mantenha o recurso {assetsTexturesShokoPng} incluído; o renderizador o processa uma vez e apresenta o resultado nos quadros subsequentes. +samples.computeShader.details: "{computeShaderRendererCs} · {computeShaderSlang}" +samples.computeShader.title: Shader de computação +samples.cube.description: Adiciona desenho indexado, matrizes de modelo, visualização e projeção em um buffer de constantes e teste de profundidade. A textura de profundidade é recriada no redimensionamento. Use ao passar de geometria em espaço de recorte para um objeto transformado; o renderizador usa um anexo de profundidade/estêncil {d32FloatS8UInt}. +samples.cube.details: "{spinningCubeRendererCs} · {spinningCubeSlang}" +samples.cube.title: Cubo giratório +samples.description: "Escolha um exemplo focado para o recurso que deseja estudar. Cada exemplo faz link com o renderizador em C# e seu respectivo shader em Slang. Comece com {link} se desejar uma aplicação completa explicada a partir de um projeto vazio." +samples.description.link: Primeiro triângulo +samples.execution.description: "{link} contém seis renderizadores independentes em uma única aplicação de desktop. Use o SDK do .NET 10 e um backend de desktop suportado, conforme descrito abaixo. Compile e execute a aplicação e, em seguida, escolha um exemplo no menu do console:" +samples.execution.description.link: ZenithTutorials +samples.execution.details: O host seleciona o DirectX 12 no Windows, Metal no macOS e Vulkan no Linux. Use um dispositivo, driver e ambiente de compilador de shader suportados pelo backend selecionado. O caminho de janelas do Linux requer X11 ou XWayland. O {link} declara as dependências de pacotes e copia os recursos de shader e textura necessários em tempo de execução. +samples.execution.details.link: arquivo de projeto +samples.execution.guidance: Os exemplos compartilham código de janelas e apresentação. Você pode escolher qualquer exemplo de forma independente com base no recurso que deseja estudar. +samples.execution.title: Executar os exemplos do tutorial +samples.host.description: "{appCs} cria o contexto, a janela e a cadeia de troca. Ele obtém um buffer de comandos, chama o renderizador selecionado, envia o quadro e o apresenta. {iRendererCs} define os métodos de atualização, renderização, redimensionamento e descarte do renderizador." +samples.host.details: Computação e traçado de raios produzem texturas fora da tela. {texturePresenterCs} e {presentTextureSlang} desenham essas texturas na textura de saída do quadro atual da janela. O host continua sendo o proprietário do envio e da apresentação da cadeia de troca. +samples.host.title: Host e apresentação compartilhados +samples.indirectDrawing.description: Desenha várias cópias de um cubo usando um buffer de argumentos indiretos indexados e dados por instância em um buffer estruturado. A CPU fornece os argumentos de desenho e atualiza as transformações. Use para compreender o layout de argumentos indiretos e o acesso de shaders a dados de instância antes de adicionar argumentos gerados pela GPU. +samples.indirectDrawing.details: "{indirectDrawingRendererCs} · {indirectDrawingSlang}" +samples.indirectDrawing.title: Desenho indireto +samples.meshShading.description: Usa um task shader para descartar instâncias de esferas e passar seus índices para um mesh shader que emite geometria. O renderizador verifica {contextCapabilitiesMeshShadingSupported} antes de criar sua pipeline. Use para rastrear handles de recursos e dados de payload através dos estágios de tarefa e malha. +samples.meshShading.details: "{meshShadingRendererCs} · {meshShadingSlang}" +samples.meshShading.title: Sombreamento de malhas +samples.rayTracing.description: Cria estruturas de aceleração de nível inferior e superior para um chão e esferas procedurais e, em seguida, executa consultas de raios em linha em um shader de computação. O renderizador verifica {contextCapabilitiesRayTracingSupported} antes de construir a carga de trabalho. Use este exemplo para entradas de estrutura de aceleração e travessia de raios no lado do shader. +samples.rayTracing.details: "{rayTracingRendererCs} · {rayTracingSlang}" +samples.rayTracing.title: Traçado de raios +samples.title: Exemplos +samples.triangle.description: Cria um buffer de vértices e um layout de entrada correspondente e, em seguida, desenha três vértices por meio de uma pipeline gráfica. Use para conectar a criação de recursos com os comandos em uma passagem de renderização. +samples.triangle.details: "{helloTriangleRendererCs} · {helloTriangleSlang} · {link}" +samples.triangle.details.link: Tutorial completo +samples.triangle.title: Olá triângulo +samples.workloads.description: "O {link} do repositório principal contém aplicações que combinam vários recursos. Seus projetos fazem referência ao código-fonte da biblioteca. A partir de um clone do Zenith.NET, execute o projeto escolhido, por exemplo:" +samples.workloads.description.link: diretório Experiments +samples.workloads.details: Os experimentos com janelas usam as mesmas opções de host para Windows, macOS e Linux/X11. Para desenhar dentro de Avalonia, WinForms, WPF, WinUI/Uno ou MAUI, consulte {link} para obter informações sobre o ciclo de vida do quadro do controle e links de implementação. +samples.workloads.details.link: Integração de plataforma +samples.workloads.table.cornellBox.example: "{link}" +samples.workloads.table.cornellBox.example.link: CornellBox +samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: Traçado de caminhos, redução de ruído, mapeamento de tons, upscaling e controles ImGui. Requer suporte a traçado de raios e o ambiente de compilação de shaders para seu backend de desktop. +samples.workloads.table.fluidTank.example: "{link}" +samples.workloads.table.fluidTank.example.link: FluidTank +samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: Simulação de fluidos por computação, dependências entre estágios de simulação e renderização de superfície em várias passagens. Requer seu backend de desktop e o ambiente de compilação de shaders. +samples.workloads.table.headings.example: Exemplo +samples.workloads.table.headings.whatItDemonstratesAndRequires: O que demonstra e o que requer +samples.workloads.table.inkCanvas.example: "{link}" +samples.workloads.table.inkCanvas.example.link: InkCanvas +samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: Desenho com Skia e tratamento de entrada em uma janela nativa. Requer o backend e a biblioteca nativa do Skia para a plataforma de destino. +samples.workloads.table.platformDetection.example: "{link}" +samples.workloads.table.platformDetection.example.link: PlatformDetection +samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: Tenta a criação de contexto para cada backend e relata os recursos do dispositivo. Se a criação do contexto falhar, ela será relatada como não suportada; esse resultado também pode indicar um driver ausente ou dependência de tempo de execução não atendida. +samples.workloads.title: Explorar cargas de trabalho maiores +tutorial.context.description: A janela agora pode abrir, mas ainda não criamos os objetos de GPU que renderizarão nela. Um {graphicsContext} fornece acesso ao backend gráfico selecionado e às suas filas de comandos. +tutorial.context.details: "Insira este bloco {emphasis}:" +tutorial.context.details.emphasis: após as diretivas using, antes de {iWindowWindow} +tutorial.context.guidance: Os branches selecionam DirectX 12 no Windows, Metal no macOS e Vulkan no Linux. O código de renderização a seguir usa a API compartilhada do Zenith.NET. Solicitamos validação durante o desenvolvimento e exibimos as mensagens relatadas por meio de {validationMessage}. Os diagnósticos dependem do backend e dos componentes de validação disponíveis na máquina. +tutorial.context.title: Criar o contexto gráfico +tutorial.description: Crie uma aplicação de console .NET que abre uma janela e desenha um triângulo com um gradiente de cor suave. Você aprenderá como dados de vértices, shaders e estado de pipeline funcionam juntos e, em seguida, gravará e enviará os comandos que produzem a imagem. +tutorial.details: Siga as seções em ordem. Primeiro você abrirá uma janela vazia, depois exibirá uma cor de fundo e, finalmente, desenhará o triângulo. Cada ponto de verificação confirma uma parte da aplicação antes de você adicionar a próxima. A inicialização é executada uma vez; o callback de renderização grava um novo quadro a cada chamada. +tutorial.draw.context: "Os argumentos para {draw} são:" +tutorial.draw.description: "No callback {windowRender}, substitua {addTheTriangleDrawCommandsHereLater} por estes três comandos, entre {beginRenderPass} e {endRenderPass}:" +tutorial.draw.details: "{setPipeline} seleciona os shaders e o estado que acabamos de criar. Defina-o antes de vincular dados de vértices: o backend usa o layout de entrada da pipeline para interpretar a vinculação." +tutorial.draw.guidance: "{setVertexBufferVertexBuffer} vincula o buffer a partir do deslocamento de byte 0 ao slot de entrada 0. Esse slot corresponde à entrada única em {inputLayouts}. Ele não copia nem envia os dados novamente." +tutorial.draw.notes: Os comandos continuam sendo apenas gravados neste ponto. As chamadas {submitWait} e {present} já presentes no final do callback de renderização executam o trabalho e exibem o resultado. A limpeza continua necessária porque o triângulo cobre apenas parte da imagem; o fundo também deve receber uma cor definida a cada quadro. +tutorial.draw.table.firstInstance.meaning: Iniciar a numeração de instâncias em zero. +tutorial.draw.table.firstVertex.meaning: Começar com o primeiro vértice no buffer. +tutorial.draw.table.headings.argument: Argumento +tutorial.draw.table.headings.description: Valor +tutorial.draw.table.headings.meaning: Significado +tutorial.draw.table.instanceCount.meaning: Desenhar uma cópia do triângulo. +tutorial.draw.table.vertexCount.meaning: Ler três vértices. +tutorial.draw.title: Desenhar o triângulo dentro da passagem +tutorial.execution.description: "Compile e execute a partir do diretório {firstTriangle}:" +tutorial.execution.details: A janela deve exibir um triângulo com um canto superior vermelho, um canto inferior direito verde e um canto inferior esquerdo azul contra um fundo escuro. O interior deve exibir um gradiente suave entre essas cores. +tutorial.execution.guidance: Redimensione a janela. O callback de redimensionamento atualiza as dimensões do framebuffer e redimensiona a cadeia de troca. A passagem de renderização estabelece uma viewport que corresponde a essa imagem. Como as posições dos vértices permanecem em coordenadas normalizadas, o triângulo mantém a mesma fração da largura e altura da janela; alterar a proporção da tela pode esticar sua forma. Preservar a proporção de um objeto requer uma política de projeção ou viewport, o que está além deste primeiro desenho. +tutorial.execution.title: Executar, redimensionar e fechar +tutorial.frame.commands.context: Após {endRenderPass}, a segunda transição prepara a imagem para apresentação. {submit} conclui a gravação e envia o buffer de comandos; {wait} aguarda a GPU concluir esse envio. {present} então solicita a exibição da imagem renderizada. +tutorial.frame.commands.description: Uma passagem de renderização agrupa operações de desenho que usam os mesmos anexos. Aqui, o anexo de cor é a textura de saída da cadeia de troca, a imagem que recebe nosso desenho. {colorAttachmentClear} cria uma descrição instruindo a passagem a limpar para a cor RGBA especificada e manter o resultado quando a passagem terminar. {beginRenderPass} grava essas instruções; a GPU realiza a limpeza após o envio dos comandos. +tutorial.frame.commands.details: Os colchetes contêm nosso único anexo de cor. O argumento {null} significa que não há anexo de profundidade/estêncil, que armazenaria valores de profundidade e máscaras de estêncil para testes de profundidade e estêncil. +tutorial.frame.commands.guidance: "{beginRenderPass} define uma viewport e um retângulo de recorte (scissor) que cobrem o anexo. A viewport mapeia as coordenadas renderizadas para pixels, e o retângulo de recorte limita quais pixels podem ser gravados. Esses padrões cobrem toda a textura de saída, como necessário para este triângulo." +tutorial.frame.commands.title: Limpar, enviar e apresentar +tutorial.frame.description: Primeiro preencha a imagem com uma única cor de fundo. Essa operação é chamada de limpeza (clear). Se essa cor aparecer na janela, a superfície, o envio de comandos e o caminho de apresentação estão funcionando juntos. Esse ponto de verificação permite testar o loop de quadros antes de adicionar geometria e shaders. +tutorial.frame.details: "Um callback de renderização é um código que o Silk.NET chama quando é hora de desenhar um quadro. Esse callback não precisa do argumento de tempo decorrido do evento, portanto é chamado de {value}. Registre-o {emphasis}:" +tutorial.frame.details.emphasis: antes de {windowRun} +tutorial.frame.target.description: "{graphicsQueueCommandBuffer} obtém um buffer de comandos com a gravação já iniciada. A gravação descreve o trabalho para a GPU; ela não executa esse trabalho imediatamente." +tutorial.frame.target.details: A primeira {transition} prepara a textura de saída para acesso como anexo de cor. {default} seleciona o nível mip 0 e a camada de array 0. Usamos {undefined} como layout anterior porque limparemos toda a imagem e descartaremos seu conteúdo anterior. Uma passagem que precisa preservar o conteúdo existente deve usar seu layout anterior real. +tutorial.frame.target.guidance: Use a textura de saída atual da cadeia de troca a cada quadro. A apresentação pode alterar qual imagem está disponível, portanto uma textura salva de um quadro anterior não é um destino de renderização permanente da janela. +tutorial.frame.target.title: Preparar a textura de saída +tutorial.frame.title: Exibir uma cor de fundo +tutorial.geometry.data.description: Adicione este array {emphasis}. As seguintes etapas de criação de recursos também pertencem ao trecho anterior a esse callback, na ordem mostrada. +tutorial.geometry.data.description.emphasis: antes de {windowRender} +tutorial.geometry.data.details: "Cada entrada do array cria um {vertex}. As duas expressões {new} internas criam sua posição {vector3} e sua cor {vector4}. Os vértices descrevem os cantos superior, inferior direito e inferior esquerdo. O vertex shader fornecerá uma quarta coordenada de posição, {w}. Com w igual a 1, x e y descrevem diretamente coordenadas normalizadas do dispositivo: -1 e +1 são as bordas da imagem, e 0 é o centro. Essas coordenadas não dependem das dimensões em pixels da janela." +tutorial.geometry.data.guidance: Cada cor contém componentes vermelho, verde, azul e alfa. Alfa é 1 em todos os três cantos. Todas as três posições têm z = 0, colocando-as no mesmo plano. Essas posições não precisam de câmera ou matriz de transformação porque já descrevem as coordenadas que queremos renderizar. Para este triângulo plano único, também desativaremos a mesclagem e o teste de profundidade e omitiremos um buffer de profundidade. +tutorial.geometry.data.title: Escolher os cantos +tutorial.geometry.description: Um vértice é um ponto acompanhado dos dados usados para desenhá-lo. Nosso triângulo tem três vértices, um para cada canto. Cada um contém uma posição e uma cor. A GPU interpolará as cores, calculando valores intermediários ao longo do triângulo. +tutorial.geometry.format.description: "Anexe esta declaração {emphasis}:" +tutorial.geometry.format.description.emphasis: no final de {programCs}, após as instruções de limpeza +tutorial.geometry.format.details: "{file} limita este tipo a {programCs}, e o construtor inicializa seus campos de posição e cor. {layoutKindSequential} mantém os campos na ordem de declaração. {position} contém três floats de 32 bits e {color} contém quatro. Nesta struct, a posição começa no byte 0, a cor começa no byte 12 e o vértice completo ocupa 28 bytes. Descreveremos esse mesmo layout para a pipeline gráfica." +tutorial.geometry.format.title: Definir um vértice +tutorial.geometry.title: Fornecer três vértices à GPU +tutorial.geometry.upload.context: "{fixed} impede que o coletor de lixo mova o array enquanto seu endereço está sendo usado. Para este buffer gravável pela CPU, {upload} mapeia, copia e desmapeia a memória antes de retornar, para que o array não precise permanecer fixado posteriormente. O buffer deve permanecer ativo durante toda a renderização, e o envio só precisa ocorrer uma vez porque os vértices não mudam." +tutorial.geometry.upload.description: "O array gerenciado é dado da CPU. Um {buffer} fornece à GPU armazenamento do qual ela pode ler os vértices. Após o array, adicione:" +tutorial.geometry.upload.details: "O tamanho total é {sizeofVertexVerticesLength}: 28 bytes por vértice, três vértices, 84 bytes no total. {bufferUsagesVertex} permite o acesso de entrada de vértices. {cpuWriteOnly} permite que a CPU inicialize esse pequeno buffer diretamente. O stride do descritor registra o tamanho do elemento; o layout de entrada que criaremos a seguir informará ao fetch de vértices como ler os atributos individuais." +tutorial.geometry.upload.guidance: Criar um buffer não o preenche. {upload} copia o array para essa alocação a partir do deslocamento de byte de destino 0. Sua descrição de origem fornece um ponteiro e o número de bytes a serem copiados. +tutorial.geometry.upload.notes: Adicione {vertexBufferDispose} imediatamente antes de {swapChainDispose} na limpeza na parte inferior de {programCs}. Para geometrias estáticas maiores, {link} explica quando escolher armazenamento exclusivo de GPU e transferências de upload. +tutorial.geometry.upload.notes.link: Gerenciamento de recursos +tutorial.geometry.upload.title: Alocar um buffer e enviar o array +tutorial.input.description: "Os bytes dos vértices e os shaders estão prontos. A seguir, descreva como a GPU deve ler cada vértice. Um atributo é um valor único, como posição ou cor. O layout de entrada fornece a cada atributo um formato e um deslocamento de bytes; o stride fornece a distância em bytes de um vértice ao próximo. Adicione este bloco de inicialização após a criação do shader:" +tutorial.input.details: "{inputLayoutAdd} anexa um elemento no stride atual e aumenta esse stride pelo tamanho do elemento. Ele não inspeciona a struct C#. Aqui ele produz a seguinte correspondência entre a memória da CPU e as entradas do shader:" +tutorial.input.guidance: "Alterar a ordem dos campos C# ou o padding sem atualizar esta descrição faria com que a GPU lesse os bytes errados. O {semanticIndex} padrão é zero, correspondendo a {pOSITION0} e {cOLOR0}. Ambos os elementos pertencem ao mesmo buffer, portanto a pipeline conterá um layout de entrada e vincularemos esse buffer ao slot 0." +tutorial.input.table.headings.byteOffset: Deslocamento de bytes +tutorial.input.table.headings.cField: "Campo C#" +tutorial.input.table.headings.format: Formato +tutorial.input.table.headings.shaderInput: Entrada do shader +tutorial.input.table.nextVertex.cField: Próximo vértice +tutorial.input.table.nextVertex.format: "Stride total: 28 bytes" +tutorial.input.table.nextVertex.shaderInput: Próximo registro de entrada +tutorial.input.table.vertexColor.format: "{float4} (16 bytes)" +tutorial.input.table.vertexPosition.format: "{float3} (12 bytes)" +tutorial.input.title: Descrever o layout de entrada de vértices +tutorial.lifecycle.description: "A aplicação concluída repete esta sequência:" +tutorial.lifecycle.details: "Fechar a janela retorna de {run}. Cada quadro renderizado já aguardou a conclusão de seu trabalho de GPU, portanto agora podemos descartar os recursos usados. A limpeza após {windowRun} deve ser:" +tutorial.lifecycle.guidance: "Libere a cadeia de troca antes da janela nativa e o contexto depois de todos os seus recursos. A fila possui e recicla os buffers de comandos enviados; a cadeia de troca possui sua textura de saída. Esses buffers de comandos e essa textura não precisam de uma chamada {dispose} separada nesta aplicação." +tutorial.lifecycle.title: Acompanhar o ciclo de vida de um quadro +tutorial.pipeline.behavior: "Após o layout de entrada, adicione:" +tutorial.pipeline.context: "{cullNone} preenche o triângulo sem descartar nenhuma orientação de face. A ordem de seus vértices determina a orientação da face, portanto desativar o descarte impede que essa ordem oculte nosso primeiro triângulo." +tutorial.pipeline.description: Agora temos dados de vértices, um layout de entrada e dois shaders. A {graphicsPipeline} os conecta e especifica como a GPU monta os vértices em primitivas e grava o resultado em um anexo. +tutorial.pipeline.details: "Uma pipeline combina estágios de shader programáveis com configurações de função fixa, que controlam operações de GPU como montagem de triângulos, descarte de faces (culling) e mesclagem. Para este triângulo, escolha estas configurações:" +tutorial.pipeline.guidance: O formato de cor vem de {swapChainDescFormat}. Ele deve corresponder à imagem usada pela passagem de renderização. {count1} significa uma amostra por pixel. +tutorial.pipeline.item: "{triangleList} monta cada grupo consecutivo de três vértices em um triângulo. Forneceremos três vértices e desenharemos uma vez, portanto nenhum buffer de índices é necessário." +tutorial.pipeline.notes: "{depthNone} desativa os testes e a gravação de profundidade, correspondendo à passagem sem anexo de profundidade." +tutorial.pipeline.reference: "{opaque} desativa a mesclagem, portanto a cor do fragment shader substitui o fundo dentro do triângulo." +tutorial.pipeline.title: Conectar os shaders e o layout de vértices +tutorial.pipeline.usage: Os objetos de shader podem ser descartados após a criação da pipeline, como feito no renderizador de exemplo. Mantenha a pipeline em si ativa para cada quadro desenhado com ela. Adicione {pipelineDispose} antes de {vertexBufferDispose} na limpeza. A criação da pipeline é a etapa final de inicialização antes do callback de renderização. +tutorial.pipeline.validation: A descrição da pipeline declara a configuração do anexo; ela não cria outra imagem. {inputLayouts} tem uma entrada porque a posição e a cor são armazenadas juntas em um único buffer. +tutorial.presentation.title: Conectar a GPU à janela +tutorial.project.context: Habilite {emphasis} ({allowUnsafeBlocks}) nas configurações de compilação do projeto. Nós o usaremos para passar dados de vértices para a GPU e para as chamadas nativas do assistente de janela. +tutorial.project.context.emphasis: Permitir código não seguro +tutorial.project.description: "Crie o projeto e entre no diretório:" +tutorial.project.details: "Instale os pacotes:" +tutorial.project.guidance: O {zenithNET} fornece a API de renderização compartilhada. Os três pacotes de backend permitem que o mesmo programa selecione a implementação para sua plataforma. O {zenithNETCompiler} compila shaders Slang, os pequenos programas de GPU que escreveremos mais tarde, para essa implementação. O Silk.NET fornece a janela e o loop de eventos. +tutorial.project.title: Criar um projeto de console +tutorial.requirements.context: Você pode acompanhar esta página a partir de um projeto vazio. O {link} e seu {detail} estão disponíveis como referência para as APIs de renderização e janelas usadas aqui. +tutorial.requirements.context.detail: host compartilhado +tutorial.requirements.context.link: exemplo Olá triângulo +tutorial.requirements.description: "Você precisa do {emphasis}, de um editor de código ou IDE e de um desktop com uma GPU e driver suportados por um backend do Zenith.NET. Familiaridade básica com C# é suficiente; os conceitos gráficos são introduzidos conforme são usados. Este é um projeto de console {net10} comum. Um backend traduz as operações do Zenith.NET em chamadas a uma API gráfica, como DirectX 12, Metal ou Vulkan. A aplicação escolhe uma na inicialização:" +tutorial.requirements.description.emphasis: SDK do .NET 10 +tutorial.requirements.details: O Linux precisa de uma sessão de janelas compatível com X11 para o caminho de janelas usado aqui. Recursos opcionais de traçado de raios e sombreamento de malhas não são necessários para este triângulo. +tutorial.requirements.guidance: O Zenith.NET renderiza em uma superfície fornecida pela aplicação. O Silk.NET.Windowing criará a janela de desktop e processará seus eventos. No macOS, o destino de apresentação é uma camada Metal ({cAMetalLayerCs}); o assistente de janela do tutorial anexa essa camada para nós. +tutorial.requirements.table.headings.graphicsBackend: Backend gráfico +tutorial.requirements.table.headings.platform: Plataforma +tutorial.requirements.table.headings.windowSurface: Superfície da janela +tutorial.requirements.table.linux.graphicsBackend: Vulkan 1.4 +tutorial.requirements.table.linux.platform: Linux +tutorial.requirements.table.linux.windowSurface: Janela e display X11; XWayland também é adequado +tutorial.requirements.table.macOS.graphicsBackend: Metal 4 +tutorial.requirements.table.macOS.platform: macOS +tutorial.requirements.table.macOS.windowSurface: Camada Metal anexada à janela +tutorial.requirements.table.windows.graphicsBackend: DirectX 12 +tutorial.requirements.table.windows.platform: Windows +tutorial.requirements.table.windows.windowSurface: Handle de janela Win32 +tutorial.requirements.title: Antes de começar +tutorial.resize.context: "Execute {dotnetRun} novamente. A janela agora deve ter um fundo escuro uniforme que continua a preenchê-la após o redimensionamento. Mantenha este callback: o triângulo será desenhado dentro de sua passagem de renderização existente." +tutorial.resize.description: "As imagens da cadeia de troca devem seguir as dimensões do framebuffer. Use {framebufferResize} para responder a alterações no tamanho em pixels, incluindo alterações causadas por dimensionamento de tela. Após o callback de renderização, ainda antes de {windowRun}, adicione:" +tutorial.resize.details: "O Silk.NET distingue mudanças no tamanho da janela de {link}. Precisamos destas últimas porque a cadeia de troca armazena pixels. Uma janela minimizada pode ter um framebuffer de tamanho zero. Nesse caso, ambos os callbacks pulam o trabalho de GPU. Após o redimensionamento, a passagem de renderização usa as novas dimensões do anexo para a viewport e o retângulo de recorte." +tutorial.resize.details.link: alterações no tamanho do framebuffer +tutorial.resize.guidance: Aguardamos após cada envio, portanto nenhum quadro anterior continua usando as imagens quando o manipulador de redimensionamento as substitui. A implementação atual de {present} também aguarda na fila gráfica. Esse loop simples mantém o trabalho de um quadro concluído antes que o próximo comece; {link} aborda um agendamento mais avançado. +tutorial.resize.guidance.link: Sincronização +tutorial.resize.title: Responder ao redimensionamento +tutorial.shaders.compilation.context: A compilação ocorre uma vez durante a inicialização. {appContextBaseDirectory} localiza o shader copiado ao lado do executável, independentemente do diretório de trabalho atual. Esses shaders consomem apenas entrada de vértices, portanto ainda não há buffers de constantes, texturas ou handles de recursos para vincular. +tutorial.shaders.compilation.description: Nas propriedades de arquivo de {triangleSlang}, defina {emphasis} como {detail}. Isso torna o shader disponível ao lado do executável. +tutorial.shaders.compilation.description.detail: Copiar se mais recente +tutorial.shaders.compilation.description.emphasis: Copiar para o Diretório de Saída +tutorial.shaders.compilation.details: "Retorne a {programCs}. Após o envio de vértices, adicione estas instruções de inicialização antes do callback de renderização:" +tutorial.shaders.compilation.guidance: "{zenithCompiler} retorna uma descrição de shader contendo código para a API gráfica solicitada. {createShader} cria o objeto de backend correspondente. Tanto a API gráfica quanto os nomes dos pontos de entrada são importantes: use {contextGraphicsApi} e escreva {vSMain} e {fSMain} exatamente como no arquivo Slang." +tutorial.shaders.compilation.title: Compilar para o backend selecionado +tutorial.shaders.context: "{fSInput} conecta a saída do vertex shader à entrada do fragment shader. Quando gravado pelo vertex shader, {sVPOSITION} fornece uma posição no espaço de recorte: as quatro coordenadas que a GPU usa para determinar o que fica dentro da imagem visível. {cOLOR0} carrega a cor a ser interpolada entre os vértices. Os dois estágios devem concordar quanto ao tipo e semântica." +tutorial.shaders.description: Um shader é um programa executado pela GPU. Este desenho precisa de um vertex shader para posicionar os vértices e de um fragment shader para produzir as cores dentro do triângulo. Nós os escreveremos em Slang, uma linguagem de shader, e compilaremos dois pontos de entrada a partir do mesmo arquivo. Um ponto de entrada é a função onde a execução de um estágio de shader começa. +tutorial.shaders.details: "Crie {triangleSlang}, começando com estas duas estruturas:" +tutorial.shaders.fragment.description: "Anexe o ponto de entrada de fragmento ao mesmo arquivo:" +tutorial.shaders.fragment.details: A rasterização determina quais posições da imagem o triângulo cobre. Ela produz fragmentos (os dados processados pelo fragment shader) com cores de vértices interpoladas pela área coberta. {fSMain} retorna essa cor interpolada por meio de {sVTARGET}, que identifica o primeiro anexo de cor. +tutorial.shaders.fragment.guidance: A interpolação de cor dos vértices é separada da mesclagem de anexos. A mesclagem combina a saída de um fragmento com a cor já armazenada no anexo. Nosso estado de mesclagem opaco desativa essa combinação, de modo que a cor interpolada substitui o fundo dentro do triângulo. +tutorial.shaders.fragment.title: Colorir os fragmentos +tutorial.shaders.guidance: "{vSInput} descreve o que o vertex shader recebe do buffer de vértices. As semânticas {pOSITION0} e {cOLOR0} identificam as entradas; os nomes dos campos C# sozinhos não estabelecem esse mapeamento." +tutorial.shaders.title: Escrever os dois estágios de shader +tutorial.shaders.vertex.description: "Anexe o ponto de entrada de vértice a {triangleSlang}:" +tutorial.shaders.vertex.details: A GPU invoca este ponto de entrada para cada vértice de entrada. Ele adiciona a coordenada homogênea {w} à posição e encaminha a cor. Após o estágio de vértice, a posição é dividida por w; aqui, essa divisão mantém x, y e z inalterados. É por isso que as posições escolhidas acima podem ser compreendidas diretamente em coordenadas normalizadas do dispositivo. +tutorial.shaders.vertex.title: Posicionar cada vértice +tutorial.surface.description: "O contexto também precisa saber onde exibir sua saída. Adicione o seguinte {emphasis}:" +tutorial.surface.description.emphasis: após {windowCenter} e antes de {windowRun} +tutorial.surface.details: "{surface} descreve um destino de apresentação nativo e suas dimensões em pixels. O framebuffer é a imagem de pixels associada à janela. {framebufferSize} fornece suas dimensões em pixels; as dimensões lógicas da janela podem ser diferentes quando o dimensionamento de tela está ativado." +tutorial.surface.guidance: A superfície corresponde ao backend selecionado acima. O Windows fornece um handle de janela, o Linux fornece um display e janela X11, e o assistente do macOS fornece a camada Metal anexada. Esta é a única parte específica da plataforma para conectar nossa janela à renderização. +tutorial.surface.title: Descrever a superfície nativa +tutorial.swapChain.context: "A cadeia de troca usa tanto o contexto quanto a janela nativa. Substitua a linha {windowDispose} na parte inferior de {programCs} por esta ordem de limpeza:" +tutorial.swapChain.description: "Use a descrição da superfície para criar as imagens que serão apresentadas. Imediatamente após o bloco da superfície, adicione:" +tutorial.swapChain.details: A {swapChain} gerencia as imagens exibidas na janela. A cada quadro, {drawable} nos fornece a imagem atual como uma {texture}, o tipo de API para dados de imagem. Após o desenho, {present} solicita a exibição do resultado e avança para o próximo drawable. +tutorial.swapChain.guidance: "{b8G8R8A8UNorm} armazena quatro canais de cor de 8 bits na ordem azul, verde, vermelho e alfa. {uNorm} significa que valores inteiros de 0 a 255 representam valores de 0 a 1. O shader continuará retornando um valor RGBA lógico; esse formato determina como esses canais são armazenados na imagem. Mais tarde, a pipeline gráfica usará {swapChainDescFormat} para corresponder a esse anexo." +tutorial.swapChain.title: Criar a cadeia de troca +tutorial.title: Primeiro triângulo +tutorial.troubleshooting.description: "Leia primeiro qualquer erro no console e, em seguida, use os pontos de verificação anteriores para identificar o estágio que falhou:" +tutorial.troubleshooting.details: Use o {link} e o {detail} para comparar os dados dos vértices, o layout de entrada e a operação de desenho. Aquele exemplo coloca as janelas e o envio em um host compartilhado; este tutorial mantém o fluxo da aplicação em {programCs}. Continue com {context} para aprender sobre desenho indexado, transformações e testes de profundidade. +tutorial.troubleshooting.details.context: Cubo giratório +tutorial.troubleshooting.details.detail: shader Slang +tutorial.troubleshooting.details.link: renderizador de exemplo +tutorial.troubleshooting.table.backend.check: Verifique se o backend selecionado é suportado pelo dispositivo e pelo driver gráfico instalado. +tutorial.troubleshooting.table.backend.symptom: Falha na criação do backend +tutorial.troubleshooting.table.drawing.check: Verifique o tamanho do upload, o layout de entrada, a seleção de pipeline e o posicionamento dos comandos de desenho dentro da passagem de renderização. +tutorial.troubleshooting.table.drawing.symptom: O fundo aparece, mas o triângulo não +tutorial.troubleshooting.table.headings.check: Verificação +tutorial.troubleshooting.table.headings.symptom: Sintoma +tutorial.troubleshooting.table.input.check: Verifique o stride de 28 bytes e os deslocamentos de posição/cor de 0 e 12. +tutorial.troubleshooting.table.input.symptom: Posições ou cores dos vértices estão corrompidas +tutorial.troubleshooting.table.shaders.check: Verifique o {triangleSlang} copiado, a ortografia do ponto de entrada e o diagnóstico relatado pelo compilador. +tutorial.troubleshooting.table.shaders.symptom: A etapa de cor de limpeza funciona, mas o carregamento do shader falha +tutorial.troubleshooting.table.window.check: Confirme se o projeto .NET compila e se a etapa somente de janela é executada em uma sessão de desktop. No Linux, verifique se o X11 ou XWayland está disponível. +tutorial.troubleshooting.table.window.symptom: Nenhuma janela se abre +tutorial.troubleshooting.title: Verificar o estágio que falhou +tutorial.window.context: "{usingZenithTutorials} importa o namespace do assistente. Cada arquivo C# usa suas próprias diretivas using comuns, portanto a importação de interoperabilidade é necessária em ambos os arquivos. O alias {buffer} refere-se ao tipo de buffer do Zenith.NET e o distingue de {systemBuffer}." +tutorial.window.description: Adicione {cocoaHelperCs} ao projeto, mantendo seu namespace. Adicione {interopUsing} no topo desse arquivo, antes de sua declaração de namespace. O assistente anexa uma camada Metal à janela no macOS; os outros branches de plataforma não o chamam. +tutorial.window.details: "Substitua o arquivo {programCs} gerado pelo seguinte código. Ele usa instruções de nível superior, que são executadas em ordem sem um método {main} explícito. Seções posteriores indicarão onde adicionar código a este mesmo arquivo:" +tutorial.window.guidance: "{graphicsAPINone} solicita ao Silk.NET que crie uma janela sem seu próprio contexto gráfico. Criaremos esse contexto com o Zenith.NET. {initialize} cria a janela nativa e disponibiliza seus handles. Um handle é um identificador fornecido pelo sistema de janelas. {center} centraliza a janela e {run} processa eventos até que ela seja fechada. A execução continua então para {dispose}, que libera a janela." +tutorial.window.notes: Execute {dotnetRun}. Uma janela vazia deve abrir e responder a movimentação, redimensionamento e fechamento. Seu conteúdo ainda não está definido porque não enviamos comandos de renderização. Feche-a antes de continuar. +tutorial.window.title: Abrir uma janela +ui.action.copy: Copiar +ui.action.navigate: Navegar +ui.action.open: Abrir +ui.action.source: Ver código-fonte +ui.api.browse: Navegar por namespaces e tipos. +ui.api.clearTypeSearch: Limpar busca de tipos +ui.api.findType: Localizar um tipo +ui.api.loadError: Não foi possível carregar os tipos. Recarregue esta página para tentar novamente. +ui.api.loadingNamespaces: Carregando namespaces… +ui.api.loadingTypes: Carregando tipos… +ui.api.matchingTypes: Tipos correspondentes +ui.api.namespace: Namespace +ui.api.namespaces: Namespaces +ui.api.noNamespaceTypes: Nenhum tipo neste namespace. +ui.api.noTypes: Nenhum tipo correspondente. +ui.api.types: Tipos +ui.content.reference: Referência +ui.content.source: Código-fonte +ui.content.tutorial: Tutorial +ui.contents.close: "Fechar sumário" +ui.contents.open: "Abrir sumário" +ui.contents.title: "Sumário" +ui.footer.caption: RHI moderno para .NET. +ui.footer.label: Rodapé +ui.language.label: Idioma +ui.language.unavailable: Não traduzido +ui.members.clear: Limpar busca de membros +ui.members.close: Fechar localizador de membros +ui.members.empty: Nenhum membro correspondente. +ui.members.open: Ir para o membro +ui.members.placeholder: Nome ou assinatura… +ui.members.search: Buscar membros +ui.members.title: Localizar um membro +ui.members.undeclared: Este tipo não possui membros declarados. +ui.navigation.api: API +ui.navigation.concepts: Conceitos +ui.navigation.home: Início +ui.navigation.label: Navegação principal +ui.navigation.toggle: Alternar navegação +ui.outline.title: Nesta página +ui.reference.assembly: Assembly +ui.reference.classes: Classes +ui.reference.constructors: Construtores +ui.reference.declaration: "Declaração de tipo C#" +ui.reference.delegates: "Delegados" +ui.reference.derived: Tipos derivados +ui.reference.enums: Enumerações +ui.reference.events: Eventos +ui.reference.examples: Exemplos +ui.reference.exceptions: Exceções +ui.reference.extensionMethods: Métodos de extensão +ui.reference.fields: Campos +ui.reference.implementations: Implementações explícitas de interface +ui.reference.implements: Implementa +ui.reference.inheritance: Herança +ui.reference.inheritedMembers: Membros herdados +ui.reference.interfaces: Interfaces +ui.reference.metadata: Metadados do tipo +ui.reference.methods: Métodos +ui.reference.namespace: Namespace +ui.reference.open: Abrir referência para {name} +ui.reference.operators: Operadores +ui.reference.parameters: Parâmetros +ui.reference.properties: Propriedades +ui.reference.related: Consulte também +ui.reference.relationships: Herança e metadados +ui.reference.remarks: Comentários +ui.reference.returns: Retornos +ui.reference.structs: Estruturas +ui.reference.typeParameters: Parâmetros de tipo +ui.reference.value: Valor +ui.reference.values: Valores +ui.search.close: Fechar busca +ui.search.empty: Nenhum resultado para “{query}”. +ui.search.hint: Pesquise tutoriais, conceitos, exemplos e a referência da API. +ui.search.loading: Carregando busca… +ui.search.more: Mostrar mais resultados +ui.search.pending: Buscando… +ui.search.placeholder: O que você está procurando? +ui.search.resultCount: "Resultados: {count}" +ui.search.title: Pesquisar documentação +ui.search.unavailable: A busca não está disponível. Você ainda pode abrir as páginas abaixo. diff --git a/documents/locales/ru-RU/strings.yml b/documents/locales/ru-RU/strings.yml new file mode 100644 index 00000000..246d4416 --- /dev/null +++ b/documents/locales/ru-RU/strings.yml @@ -0,0 +1,604 @@ +### YamlMime:Resources +concepts.execution.context.description: Объект {graphicsContext} представляет устройство бэкенда и предоставляет его очереди графики, вычислений и передачи данных. Создавайте буферы, текстуры, шейдеры и конвейеры для рабочей нагрузки через один и тот же контекст. Ресурс или дескриптор, созданный другим контекстом, нельзя просто привязать к командным буферам текущего контекста. +concepts.execution.context.details: Выберите бэкенд для платформы и поверхности презентации. API остаётся общим, но возможности устройства имеют решающее значение. Объект {capabilities} предоставляет имя устройства и флаги {rayTracingSupported} и {meshShadingSupported}. Проверяйте соответствующий флаг перед созданием опциональной рабочей нагрузки, как это сделано в примерах {link} и {detail}. Эти флаги не представляют собой исчерпывающий список ограничений форматов, памяти или платформы. +concepts.execution.context.details.detail: mesh shading +concepts.execution.context.details.link: трассировки лучей +concepts.execution.context.title: Контекст объединяет ресурсы и очереди +concepts.execution.description: Приложение Zenith.NET создаёт ресурсы GPU, записывает команды, использующие их, и отправляет эти команды в очередь. CPU может продолжать работу, пока GPU выполняет отправленные задачи. Сохраняйте ресурсы активными до завершения этой работы, даже после того, как вызовы записи команд завершились. +concepts.execution.ownership.description: "Здесь владение означает ответственность за освобождение ресурса. Ссылка C# удерживает управляемый объект от сборки мусора; она не препятствует уничтожению нативного ресурса при явном вызове {dispose}. Аналогично, отправка команды, использующей буфер, не передаёт владение этим буфером очереди." +concepts.execution.ownership.details: При завершении работы прекратите отправку новых задач, дождитесь окончания последних операций во всех задействованных очередях, освободите ресурсы приложения и затем освободите контекст. Освобождение контекста очищает его собственные очереди и внутренние вспомогательные структуры; оно не ожидает все задачи приложения и не освобождает каждый ресурс, созданный приложением. +concepts.execution.ownership.guidance: Применяйте те же правила времени жизни и во время рендеринга. Сохраняйте значение завершения для последнего использования ресурса, чтобы знать, когда его байты можно перезаписать или когда ресурс можно заменить. О времени жизни представлений и базовых ресурсов см. в разделе {link}. +concepts.execution.ownership.guidance.link: Управление ресурсами +concepts.execution.ownership.table.applicationResources.object: Ресурсы, созданные приложением +concepts.execution.ownership.table.applicationResources.ownership: Приложение освобождает их после последнего использования на GPU. +concepts.execution.ownership.table.commandBuffers.object: Заимствованные командные буферы +concepts.execution.ownership.table.commandBuffers.ownership: Очередь управляет ими и повторно использует их. +concepts.execution.ownership.table.headings.object: Объект +concepts.execution.ownership.table.headings.ownership: Кто освобождает? +concepts.execution.ownership.table.queues.object: Очереди контекста и их временные шкалы +concepts.execution.ownership.table.queues.ownership: Контекст и очереди управляют ими. +concepts.execution.ownership.table.swapChainDrawable.ownership: Цепочка обмена управляет ею. +concepts.execution.ownership.title: Разделение владения и завершения на GPU +concepts.execution.pipelines.description: Графический конвейер объединяет шейдеры, разметку входных вершин, правила сборки вершин в примитивы, форматы вложений и состояние рендеринга. Установите его перед привязкой данных вершин, индексов или констант и перед вызовом команд отрисовки. Форматы его вложений и число сэмплов должны совпадать со свойствами вложений прохода рендеринга. +concepts.execution.pipelines.details: Вычислительный конвейер предоставляет точку входа шейдера для диспатча, запускающего группы потоков GPU. Установите его и его константы перед вызовом диспатча. Вычислительные диспатчи должны находиться вне графических проходов рендеринга. Смена конвейера меняет то, как последующие команды интерпретируют свои входные данные; привязывайте данные, требуемые выбранным конвейером, перед его использованием. +concepts.execution.pipelines.guidance: В разделе {link} показана полная последовательность графических операций. В {detail} записывается диспатч с последующим графическим проходом, отображающим результат. +concepts.execution.pipelines.guidance.detail: примере вычислений +concepts.execution.pipelines.guidance.link: обратный вызов рендеринга треугольника +concepts.execution.pipelines.title: Конвейер определяет, как команды интерпретируют данные +concepts.execution.queues.description: Начинайте с {graphicsQueue}, если кадр сочетает отрисовку, вычисления и копирование. Размещение зависимых задач в одной очереди упрощает контроль за их очерёдностью. +concepts.execution.queues.details: Очередь принимает пакеты команд для выполнения. Раздельные очереди не обязательно соответствуют отдельным аппаратным движкам, поэтому их работа может не выполняться параллельно. Используйте другую очередь, когда нагрузка может выиграть от перекрытия выполнения, и добавляйте явную зависимость, если одна очередь использует результаты другой. +concepts.execution.queues.guidance: Когда последующие команды зависят от предыдущих записей, приложение должно гарантировать, что эти записи доступны последующим командам. Отправка обоих командных буферов в одну и ту же очередь не устанавливает автоматически каждую такую зависимость. Команды могут выполняться на разных стадиях GPU, и последующим обращениям может потребоваться барьер или переход текстуры. В разделе {link} объясняется различие между порядком отправки и видимостью ресурсов. +concepts.execution.queues.guidance.link: Синхронизация +concepts.execution.queues.table.computeQueue.workToRecord: Вычислительные диспатчи и совместимые операции передачи данных без графических проходов рендеринга. +concepts.execution.queues.table.graphicsQueue.workToRecord: Проходы рендеринга и отрисовка, а также операции вычислений и передачи данных, используемые кадром. +concepts.execution.queues.table.headings.queue: Очередь +concepts.execution.queues.table.headings.workToRecord: Записываемая работа +concepts.execution.queues.table.transferQueue.workToRecord: Операции загрузки, скачивания и копирования данных без отрисовки и вычислительных диспатчей. +concepts.execution.queues.title: Выбор очереди для выполняемой работы +concepts.execution.recording.context: Очередь опрашивает статус завершения и повторно использует завершённые командные буферы. Вызывайте {queueCommandBuffer} для каждой новой записи; метод может вернуть повторно используемый экземпляр. Не освобождайте полученный командный буфер вручную, не отправляйте его дважды и не продолжайте запись в него после отправки. Записывайте данный командный буфер только из одного потока одновременно; внутренние блокировки очереди не защищают от одновременных изменений командного буфера. +concepts.execution.recording.description: Метод {queueCommandBuffer} возвращает {commandBuffer} с уже начатой записью. Запишите команды и их зависимости, затем вызовите {submit} один раз. Отправка завершает запись и возвращает {timelineValue}, определяющий точку завершения на этой очереди. +concepts.execution.recording.details: "Например, после записи кадра в {commandBuffer} учебник отправляет его и ожидает завершения следующим образом:" +concepts.execution.recording.guidance: Метод {submit} ставит работу в расписание; {wait} удерживает CPU от продолжения до завершения этой отправки. Запись отрисовки, завершение прохода рендеринга и отправка командного буфера — это независимые операции. Ни запись отрисовки, ни завершение прохода не ожидают GPU. +concepts.execution.recording.title: Запись не выполняет команды +concepts.execution.title: Модель выполнения +concepts.platforms.description: Выберите, владеет ли ваше приложение нативным окном и циклом кадров самостоятельно или использует элемент управления рендерингом UI. Этот выбор определяет, кто получает выходную текстуру, отправляет команды и выводит результат на экран. Выходная текстура — это текстура, используемая для вывода текущего кадра. Закадровая графика и вычисления не требуют наличия окна или цепочки обмена. +concepts.platforms.frame.context: Добавьте привязки конвейера и команды отрисовки внутри этого прохода. Завершите проход до возврата управления. Не отправляйте предоставленный командный буфер и не вызывайте презентацию самостоятельно, а также не освобождайте командный буфер или выходную текстуру. Если обработчик использует выходную текстуру в другом layout, верните её в состояние {colorAttachment} перед завершающим переходом элемента управления. +concepts.platforms.frame.description: Интеграции реализуют интерфейс {iZenithView}. Приложение предоставляет свой {graphicsContext}, обновляет данные сцены в {updateRequested} и записывает команды рендеринга в {renderRequested} с использованием {renderEventArgs}. +concepts.platforms.frame.details: "Элемент управления отвечает за полный цикл обработки кадра. Он получает выходную текстуру и командный буфер, переводит текстуру в состояние {colorAttachment}, вызывает обработчики, а затем выполняет отправку команд и презентацию, требуемые фреймворком." +concepts.platforms.frame.guidance: "Для инициализированного представления {iZenithView} с именем {view} и назначенным контекстом данный обработчик записывает полный проход очистки. Для него требуется директива {usingZenithNET}:" +concepts.platforms.frame.notes: Элементы управления выполняют переход из {undefined} в начале каждого кадра, поэтому приложения не могут рассчитывать на сохранение предыдущего содержимого выходной текстуры. Очищайте или заново отрисовывайте требуемое изображение в каждом кадре. Храните постоянные накопленные данные или кэшированный рендеринг в текстуре, принадлежащей приложению, и выводите эту текстуру через элемент управления. +concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat} задаёт формат цвета по умолчанию для интеграций. При согласовании форматов вложений, числа сэмплов и размеров проверяйте фактическую выходную текстуру события." +concepts.platforms.frame.title: Запись команд в кадр, предоставляемый элементом управления UI +concepts.platforms.integration.context: Для WinForms, WPF и варианта WinUI требуется Windows. Приложениям MAUI требуется рабочая нагрузка целевой платформы и регистрация обработчика через {useZenithView}; см. {extensionsCs}. Должны поддерживаться как фреймворк, так и графический бэкенд. +concepts.platforms.integration.description: "Элементы управления используют общий интерфейс событий, но способ вывода изображения у них различается:" +concepts.platforms.integration.details: Считывание растровых изображений (bitmap readback) копирует отрисованные пиксели в память CPU перед их отображением в UI. Взаимодействие через разделяемые текстуры позволяет избежать этого считывания, но всё же может требовать копирования и синхронизации на GPU. Общий интерфейс {renderRequested} не означает одинаковых накладных расходов на презентацию или идентичных требований к взаимодействию. +concepts.platforms.integration.guidance: "Используйте пакет, соответствующий фреймворку приложения, например:" +concepts.platforms.integration.table.avalonia.integration: Avalonia +concepts.platforms.integration.table.avalonia.presentation: Рендерит в текстуру и считывает пиксели в {writeableBitmap}. См. {zenithViewCs} и {surfaceCs}. +concepts.platforms.integration.table.headings.integration: Интеграция +concepts.platforms.integration.table.headings.presentation: Как изображение передаётся в UI +concepts.platforms.integration.table.maui.integration: .NET MAUI +concepts.platforms.integration.table.maui.presentation: Использует нативные поверхности в Android, iOS и Mac Catalyst, а в Windows — композицию через разделяемые текстуры. См. {link}. +concepts.platforms.integration.table.maui.presentation.link: реализации для платформ +concepts.platforms.integration.table.uno.integration: Вариант Uno +concepts.platforms.integration.table.uno.presentation: Считывает пиксели в {writeableBitmap}. См. {zenithViewUnoCs}. +concepts.platforms.integration.table.winForms.integration: WinForms +concepts.platforms.integration.table.winForms.presentation: Создаёт цепочку обмена Zenith.NET для дескриптора {hWND} элемента управления. См. {zenithViewCs}. +concepts.platforms.integration.table.winUI.integration: WinUI в Windows +concepts.platforms.integration.table.winUI.presentation: Рендерит в импортированную разделяемую текстуру Direct3D 11, затем копирует в композиционную цепочку обмена, подключённую к {swapChainPanel}. См. {zenithViewWinUICs}. +concepts.platforms.integration.table.wpf.integration: WPF +concepts.platforms.integration.table.wpf.presentation: Импортирует разделяемую текстуру Direct3D 11, затем копирует через Direct3D interop в поверхность, отображаемую {d3DImage}. См. {surfaceCs}. +concepts.platforms.integration.title: Выбор пути презентации и фреймворка +concepts.platforms.lifecycle.context: "При создании ресурсов для элемента управления UI используйте значения {descWidth}, {descHeight}, {descFormat} и {descSampleCount} выходной текстуры события. Элемент управления определяет разрешение этой текстуры; не предполагайте, что его логические размеры или масштаб экрана всегда соответствуют размерам текстуры." +concepts.platforms.lifecycle.description: Для нативной цепочки обмена передавайте размеры фреймбуфера в пикселях. Размеры окна в логических единицах могут отличаться при включённом масштабировании экрана. Пропускайте фреймбуферы нулевого размера, изменяйте размер цепочки обмена при изменении её пиксельного размера и получайте {swapChainDrawable} для каждого кадра. Выходная текстура принадлежит цепочке обмена и может меняться после вывода на экран или изменения размера. +concepts.platforms.lifecycle.details: Метод {swapChainResize} изменяет размеры существующей поверхности. Метод {swapChainRefresh} заменяет описание поверхности, включая её нативные дескрипторы. Перед любой из этих операций завершите незавершённые операции с затрагиваемыми ресурсами. Освобождайте цепочку обмена до уничтожения её нативного целевого объекта презентации. +concepts.platforms.lifecycle.guidance: Пересоздавайте принадлежащие приложению текстуры глубины или закадровые текстуры, размер которых привязан к окну, и обновляйте константы, содержащие их дескрипторы. Конвейер может продолжать использоваться после изменения размера, если форматы его вложений и число сэмплов остаются совместимыми. В примере {link} конвейер сохраняется при замене текстуры глубины. +concepts.platforms.lifecycle.guidance.link: рендерера вращающегося куба +concepts.platforms.lifecycle.title: Размеры и время жизни выходной текстуры определяются хостом +concepts.platforms.ownership.description: Приложение владеет назначенным им контекстом и ресурсами, созданными для рендеринга. Элемент управления владеет собственными ресурсами презентации. Изменение свойства {graphicsContext} элемента управления заставляет планировщик пересоздать ресурсы элемента управления; это не пересоздаёт конвейеры, буферы или текстуры приложения для нового контекста. +concepts.platforms.ownership.details: Координируйте замену ресурсов с жизненным циклом кадров элемента управления. Остановите формирование кадров в элементе управления и завершите активные операции на GPU перед освобождением ресурсов приложения или назначенного контекста. Удаление элемента управления не передаёт владение контекстом элементу управления. +concepts.platforms.ownership.guidance: Общий планировщик {frameSchedulerCs} отправляет задачи кадра через UI-диспетчер элемента управления. Обработчики кадров должны быть сфокусированы на обновлении и записи кадра; длительная работа CPU в них также задерживает интерфейс пользователя. +concepts.platforms.ownership.title: Ресурсы приложения не принадлежат элементу управления +concepts.platforms.surface.context: Поддержка операционной системы оконной библиотекой или UI-фреймворком не гарантирует, что выбранный бэкенд GPU доступен на ней. Возможности устройства, драйверы и поддержка нативной поверхности должны совпадать. Проверяйте поддержку трассировки лучей и mesh shading через {contextCapabilities} перед созданием соответствующих нагрузок. +concepts.platforms.surface.description: В примере {link} библиотека Silk.NET используется для создания окна и обработки событий. Zenith.NET подключается к этому окну через описание {surface} и цепочку обмена {swapChain}. Поверхность содержит нативные дескрипторы и размеры; создание этого описания не создаёт и не захватывает во владение окно операционной системы. +concepts.platforms.surface.description.link: треугольника +concepts.platforms.surface.details: "Дескриптор должен соответствовать выбранному бэкенду:" +concepts.platforms.surface.guidance: Файл {appCs} из учебника демонстрирует варианты для Windows, macOS и X11. Его хост для Linux предоставляет дескрипторы Xlib; для работы в сессии Wayland требуется XWayland. Нативное приложение Wayland предоставляло бы другие дескрипторы через {surfaceWayland}. +concepts.platforms.surface.table.android.backend: Vulkan в Android. +concepts.platforms.surface.table.apple.backend: Metal на платформах Apple. +concepts.platforms.surface.table.headings.backend: Бэкенд +concepts.platforms.surface.table.headings.factory: Фабрика поверхности +concepts.platforms.surface.table.headings.handles: Дескрипторы, предоставляемые хостом +concepts.platforms.surface.table.wayland.backend: Vulkan с нативным хостом Wayland. +concepts.platforms.surface.table.wayland.handles: Дисплей и поверхность Wayland +concepts.platforms.surface.table.win32.backend: DirectX 12 или Vulkan в Windows. +concepts.platforms.surface.table.xlib.backend: Vulkan в Linux с X11 или XWayland. +concepts.platforms.surface.table.xlib.handles: Дисплей и окно X11 +concepts.platforms.surface.title: Предоставление нативной поверхности при самостоятельном управлении презентацией +concepts.platforms.title: Интеграция с платформами +concepts.resources.allocation.context: "Начните с ресурсов, создаваемых контекстом, если вам не нужен собственный аллокатор. При использовании кучи дождитесь завершения всех задач GPU, обращающихся к её ресурсам. Затем освободите размещённые ресурсы и только после этого саму кучу." +concepts.resources.allocation.description: "Объект {heap} предоставляет память для размещения ресурсов по явно заданным смещениям в байтах. Приложение выбирает эти смещения и отслеживает занятые области." +concepts.resources.allocation.details: "Перед размещением вызовите {contextGetSizeAndAlignment} с точным описанием буфера или текстуры. Выберите смещение, кратное возвращённому выравниванию, зарезервируйте возвращённый размер и убедитесь, что ресурс не выходит за общий размер кучи в байтах. Области действующих выделений памяти не должны пересекаться. Хранилище текстуры может включать заполнение и выравнивание, зависящие от бэкенда, поэтому произведение числа пикселей на число байтов на пиксель не даёт размер выделения." +concepts.resources.allocation.guidance: "Для размещённых буферов резидентность буфера должна соответствовать резидентности кучи. Обычные текстуры GPU, описанные здесь, размещайте в кучах только для GPU. Размер и выравнивание — требования к размещению, а не гарантия того, что любой ресурс можно поместить в любую кучу на каждом бэкенде." +concepts.resources.allocation.title: Размещение ресурсов в куче при необходимости контроля выделения памяти +concepts.resources.bufferUsages.table.constant.role: Параметры шейдера, считываемые через привязку буфера констант. +concepts.resources.bufferUsages.table.headings.role: "Роль" +concepts.resources.bufferUsages.table.headings.usage: Назначение +concepts.resources.bufferUsages.table.index.role: Индексы, используемые при индексной отрисовке. +concepts.resources.bufferUsages.table.indirect.role: "Аргументы, считываемые командами косвенной отрисовки или диспатча." +concepts.resources.bufferUsages.table.none.role: "Флаги назначения буфера не объявлены." +concepts.resources.bufferUsages.table.storageReadOnly.role: "Данные буфера, доступные через привязку шейдера только для чтения." +concepts.resources.bufferUsages.table.storageReadWrite.role: "Данные буфера, доступные через привязку шейдера для чтения и записи." +concepts.resources.bufferUsages.table.transferDst.role: "Память назначения для копирования на GPU." +concepts.resources.bufferUsages.table.transferSrc.role: "Исходные данные для копирования на GPU." +concepts.resources.bufferUsages.table.vertex.role: Вершинные атрибуты, считываемые для отрисовки. +concepts.resources.bufferUsages.title: Назначения буфера +concepts.resources.description: "Выбирайте описание ресурса исходя из операций, которые будут его использовать. Для текстуры, в которую выполняется рендеринг, из которой делает выборки шейдер и данные которой считываются на CPU, нужно объявить все три назначения и обеспечить синхронизацию между ними. Размещение памяти и время жизни ресурса требуют отдельных решений." +concepts.resources.memory.context: Для буфера, доступного CPU, метод {map} возвращает адрес CPU. Он не ожидает, пока GPU прекратит доступ к тем же байтам. Метод {unmap} аналогично не отправляет задачи и не ожидает завершения. Перед перезаписью данных, доступных для записи CPU, завершите операции чтения GPU, которым всё ещё требуется старое содержимое. +concepts.resources.memory.description: "Структура {bufferDesc} содержит поле {residency}. Выбирайте его в соответствии с тем, как CPU и GPU будут обращаться к данным:" +concepts.resources.memory.details: Резидентность описывает предполагаемый доступ CPU к выделенной памяти. Она не означает, что каждое устройство имеет физически раздельные области памяти CPU и GPU. В треугольнике используется {cpuWriteOnly} для прямой инициализации небольшого буфера вершин. Большой статический меш может получить больше преимуществ от памяти только для GPU с однократной загрузкой. +concepts.resources.memory.guidance: В {textureDesc} нет поля резидентности. Обычные текстуры, создаваемые контекстом, используют память GPU. Их публичный API предоставляет операции загрузки и скачивания для передачи данных CPU без прямого метода отображения. Явные кучи обеспечивают контроль размещения, описанный ниже. +concepts.resources.memory.table.cpuReadOnly.cPUAccess: "Читать отображённую память после завершения копирования на GPU." +concepts.resources.memory.table.cpuReadOnly.typicalRole: "Данные, полученные на GPU для считывания на CPU" +concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "Записывать в отображённую память после завершения предыдущих чтений GPU." +concepts.resources.memory.table.cpuWriteOnly.typicalRole: "Данные, предоставляемые или обновляемые CPU" +concepts.resources.memory.table.gpuOnly.cPUAccess: "Передавать байты через буфер загрузки или считывания." +concepts.resources.memory.table.gpuOnly.typicalRole: "Статическая геометрия и рабочие данные GPU" +concepts.resources.memory.table.headings.cPUAccess: Доступ CPU +concepts.resources.memory.table.headings.residency: Резидентность +concepts.resources.memory.table.headings.typicalRole: Типичная роль +concepts.resources.memory.title: "Выбор памяти с учётом необходимого доступа CPU" +concepts.resources.textureUsages.description: "Флаги назначения для передачи описывают направление копирования на GPU. Доступ CPU — отдельное решение о размещении памяти, рассмотренное ниже." +concepts.resources.textureUsages.details: "Объединение флагов объявляет несколько ролей, но не выполняет операции и не упорядочивает доступ. Для текстур по-прежнему необходимо правильно выбирать {link}, а их форматы должны поддерживать запрошенные назначения на выбранном устройстве." +concepts.resources.textureUsages.details.link: "состояние доступа и синхронизацию" +concepts.resources.textureUsages.table.colorAttachment.role: "Цветовое вложение в проходе рендеринга." +concepts.resources.textureUsages.table.depthStencilAttachment.role: "Вложение глубины и трафарета в проходе рендеринга." +concepts.resources.textureUsages.table.headings.role: "Роль" +concepts.resources.textureUsages.table.headings.usage: Назначение +concepts.resources.textureUsages.table.none.role: "Флаги назначения текстуры не объявлены." +concepts.resources.textureUsages.table.sampled.role: "Данные текстуры, считываемые через привязку сэмплируемой текстуры." +concepts.resources.textureUsages.table.storage.role: "Данные текстуры, доступные через привязку текстуры хранения для чтения или записи шейдером." +concepts.resources.textureUsages.table.transferDst.role: "Память изображения назначения для копирования на GPU." +concepts.resources.textureUsages.table.transferSrc.role: "Данные исходного изображения для копирования на GPU." +concepts.resources.textureUsages.title: Назначения текстуры +concepts.resources.title: Управление ресурсами +concepts.resources.transfers.context: Скачивание данных записывает команду копирования GPU во внутреннее хранилище считывания. Библиотека копирует эти байты в предоставленный буфер CPU при сбросе завершённого командного буфера для повторного использования. Сохраняйте память назначения выделенной, а управляемую память — закреплённой, пока не завершится вызов {wait} для значения отправки. +concepts.resources.transfers.description: "Загрузка копирует данные CPU в ресурс GPU, а считывание возвращает данные ресурса в память CPU. Методы самого ресурса завершают эту передачу до возврата из вызова:" +concepts.resources.transfers.details: "Эти ожидания относятся только к передаче, отправленной данными методами. Они не обнаруживают зависимости от другой очереди, которая уже читала или записывала ресурс. Установите такие зависимости до вызова метода ресурса. При прямом копировании через отображённую память вызывающий код также обязан обеспечить завершение соответствующей работы GPU." +concepts.resources.transfers.guidance: "Используйте {commandBufferUpload} или {commandBufferDownload}, если копирование должно быть записано вместе с другими операциями. Время жизни их указателей различается:" +concepts.resources.transfers.item: "Загрузка во время вызова копирует исходные данные CPU во внутренний буфер загрузки, также называемый промежуточной памятью staging. Исходный указатель должен оставаться действительным только на время этого вызова." +concepts.resources.transfers.notes: "Для текстуры шаг строки — расстояние в байтах между соседними строками данных CPU, а шаг среза — расстояние в байтах между соседними срезами по глубине. Эти значения не описывают внутреннее размещение текстуры в памяти GPU. Различие между завершением GPU и считыванием данных описано в разделе {link}." +concepts.resources.transfers.notes.link: Синхронизация +concepts.resources.transfers.table.bufferDownload.transfer: Прямое копирование CPU для {cpuReadOnly}; иначе отправляет скачивание в очередь передачи и ожидает. +concepts.resources.transfers.table.bufferUpload.transfer: Прямое копирование CPU для {cpuWriteOnly}; иначе отправляет загрузку в очередь передачи и ожидает. +concepts.resources.transfers.table.headings.method: Метод +concepts.resources.transfers.table.headings.transfer: "Способ передачи данных" +concepts.resources.transfers.table.textureTransfers.method: "{textureUpload} / {textureDownload}" +concepts.resources.transfers.table.textureTransfers.transfer: "Использует графическую очередь, переводит выбранный подресурс в состояние для копирования, затем в запрошенное конечное состояние и ожидает завершения передачи." +concepts.resources.transfers.title: "Выбор между немедленной передачей и записью передачи в командный буфер" +concepts.resources.usages.description: "{bufferUsages} и {textureUsages} — флаговые перечисления, объявляющие предполагаемые роли ресурса. Они задаются в полях {bufferDescUsages} и {textureDescUsages} соответственно. Если у ресурса несколько ролей, члены флагового перечисления можно объединить с помощью {value}." +concepts.resources.usages.title: Объявление необходимых назначений перед созданием ресурса +concepts.resources.views.description: Объект {bufferView} описывает область буфера и её интерпретацию. Объект {textureView} выбирает совместимый тип текстуры, формат и диапазон подресурсов. Представление разделяет базовое хранилище; оно не копирует данные и не добавляет назначения, отсутствовавшие при создании ресурса. Его диапазон также не гарантирует переносимую проверку границ в шейдере. +concepts.resources.views.details: "Для представления по умолчанию используйте дескриптор самого ресурса. Если нужна другая область или иная совместимая интерпретация, создайте представление. Сохраняйте ссылки C# на представление и базовый ресурс, пока задачи GPU могут их использовать: один лишь дескриптор ресурса не поддерживает время жизни ни одного из объектов. Освобождайте их только после последнего использования GPU. Заменив любой из объектов, обновите константы, содержащие его прежний {link}." +concepts.resources.views.details.link: "дескриптор ресурса" +concepts.resources.views.guidance: "В {link} показана замена текстуры глубины при изменении размера. В {detail} входная текстура хранится отдельно от доступной для записи выходной. В обоих случаях время жизни ресурса соответствует работе, которая его фактически использует." +concepts.resources.views.guidance.detail: примере вычислений +concepts.resources.views.guidance.link: "примере вращающегося куба" +concepts.resources.views.title: "Сохранение доступности представлений и их базовых ресурсов" +concepts.shaders.binding.context: "В примере вычислений поле {input} заполняется значением {inputTextureSampledHandle}, а {output} — {outputTextureStorageHandle}. Типизированный {descriptorHandle} в Slang указывает шейдеру способ доступа к каждому ресурсу:" +concepts.shaders.binding.description: "Метод {setConstantBuffer} привязывает буфер и байтовое смещение для констант текущего конвейера. Он привязывает существующую видимую для GPU память; он не загружает значение C#. Сначала заполните буфер и убедитесь, что предыдущие читатели GPU завершили работу, прежде чем перезаписывать его байты." +concepts.shaders.binding.details: "Установите конвейер перед его буфером констант. Для вычислительной нагрузки с уже созданными и загруженными ресурсами запись выполняется в следующем порядке:" +concepts.shaders.binding.guidance: Этот фрагмент предполагает записываемый {commandBuffer}, конвейер {computePipeline}, загруженный буфер {constantBuffer} с назначением {bufferUsagesConstant} и количество групп потоков для данной задачи. Смещение 0 привязывает начало буфера. Если несколько записей данных констант делят один буфер, начальное смещение каждой записи должно соответствовать выравниванию привязки бэкенда. Это требование не зависит от разметки полей внутри самой записи. +concepts.shaders.binding.notes: Структура {resourceHandle} хранит два 32-битных поля, но их интерпретация определяется бэкендом. Не рассматривайте её как универсальный индекс дескриптора, адрес или значение, переносимое между контекстами. Дескриптор не создаёт ресурс, не добавляет отсутствующее назначение и не выполняет синхронизацию. +concepts.shaders.binding.reference: "Сохраняйте ссылки на ресурс и любое представление, использованное для получения его дескриптора. Освобождайте их только после завершения последнего использования шейдером. При замене текстуры или представления обновите константы со старым дескриптором. Эта связь времени жизни описана в разделе «{link}»." +concepts.shaders.binding.reference.link: Управление ресурсами +concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: Чтение структурированных элементов типа шейдера {t}. +concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: Чтение или запись структурированных элементов типа шейдера {t}. +concepts.shaders.binding.table.headings.access: Предполагаемый доступ +concepts.shaders.binding.table.headings.cHandle: "Дескриптор C#" +concepts.shaders.binding.table.headings.slangFieldType: Тип поля Slang +concepts.shaders.binding.table.samplerHandle.access: Предоставление состояния сэмплирования текстуры. +concepts.shaders.binding.table.textureSampledHandle.access: Чтение текстуры. +concepts.shaders.binding.table.textureStorageHandle.access: Чтение или запись текстуры хранения. +concepts.shaders.binding.title: Привязка буфера констант и описываемых им ресурсов +concepts.shaders.compilation.description: "{zenithCompiler} компилирует именованную точку входа Slang и возвращает {shaderDesc}. Используйте свойство контекста {graphicsApi}, чтобы результат предназначался бэкенду, создающему шейдер: DXIL для DirectX 12, библиотека Metal для Metal или SPIR-V для Vulkan." +concepts.shaders.compilation.details: "Например, при наличии {context} и скопированного рядом с исполняемым файлом шейдера треугольника:" +concepts.shaders.compilation.guidance: "Имя {vSMain} должно точно совпадать с именем точки входа в файле шейдера. Сохраняйте объекты шейдеров действительными при создании конвейера и освобождайте их после его создания, как показано в учебнике «{link}». Выполняйте эту инициализацию один раз, а не компилируйте шейдеры заново для каждого кадра." +concepts.shaders.compilation.guidance.link: Первый треугольник +concepts.shaders.compilation.title: Компиляция точки входа для выбранного контекста +concepts.shaders.description: "Шейдер принимает данные, предоставляемые приложением. Вершинные атрибуты описывают отдельные вершины; буферы хранят параметры или массивы; дескрипторы ресурсов идентифицируют другие ресурсы, к которым обращается шейдер. Объявления C# и объявления Slang должны согласовывать смысл этих значений. Простого совпадения имени поля недостаточно: разметка, доступ к ресурсам и привязка должны полностью совпадать." +concepts.shaders.dispatch.description: Метод {dispatch} принимает количество групп потоков. Точка входа {numthreads} в примере вычислений запускает 16 × 16 потоков на группу. Разделите размеры изображения на 16 с округлением вверх, чтобы получить количество групп. Например, изображению 17 × 19 требуется 2 × 2 группы. Шейдер проверяет пиксельные координаты относительно размеров изображения, поскольку последние группы могут содержать потоки за пределами изображения. +concepts.shaders.dispatch.details: Компилятор сохраняет объявленный размер группы точки входа в {shaderDescThreadGroupSize}; он не пересчитывает размеры в пикселях, переданные в {dispatch}, в количество групп. Полный пример привязки и запуска см. в {computeShaderRendererCs} и его шейдере, а перед чтением вывода в другом проходе используйте {link}. +concepts.shaders.dispatch.details.link: Синхронизация +concepts.shaders.dispatch.title: Запуск групп потоков, а не пикселей +concepts.shaders.layout.context: "В {link} смещения заданы явно. Для этого объявления в области видимости требуются {systemRuntimeInteropServices} и {zenithNET}:" +concepts.shaders.layout.context.link: "константах C# примера вычислений" +concepts.shaders.layout.description: "Для вершинного ввода структура {inputLayout} конвейера описывает форматы, смещения, шаг и семантику. Положение {float3} треугольника, за которым следует цвет {float4}, занимает 28 байт, причём цвет находится со смещения 12. Метод {inputLayoutAdd} рассчитывает эту упакованную разметку; он не анализирует структуру C#. Если поля C# содержат выравнивающие байты, предоставьте соответствующую разметку, а не предполагайте плотную упаковку полей." +concepts.shaders.layout.details: "Буферы констант содержат параметры шейдера, а структурированные буферы — массивы элементов объявленного типа. Оба читаются согласно объявлениям Slang и не используют {inputLayout}. Проверяйте смещения полей и размеры элементов для скомпилированного представления шейдера, включая заполняющие байты. Неуправляемый тип C# подходит для побайтового копирования, но сам по себе не гарантирует совпадения с типом шейдера. В частности, не переносите плотную разметку {float3} вершины на каждый буфер шейдера." +concepts.shaders.layout.guidance: Дескриптор ресурса — это небольшое значение, ссылающееся на существующий ресурс. Копирование дескриптора в буфер констант не копирует содержимое самого ресурса. +concepts.shaders.layout.notes: "Соответствующее объявление в {computeShaderSlang}:" +concepts.shaders.layout.reference: "Размеры занимают первые восемь байт, за ними следуют два восьмибайтовых дескриптора ресурсов. Пример на C# резервирует всего 256 байт. Этот размер выбран автором примера, а не является правилом, требующим, чтобы все структуры Slang или блоки констант занимали 256 байт. Дополнение общего размера также не исправляет поле, расположенное с неверным смещением." +concepts.shaders.layout.title: Различные правила разметки для вершинных входов и данных шейдеров +concepts.shaders.matrices.description: "Компилятор запрашивает хранение матриц по строкам (row-major), где элементы каждой строки хранятся последовательно. В примере {link} три значения {matrix4x4} размещаются со смещениями 0, 64 и 128. В {detail} используется {mulVectorMatrix} в порядке умножения: модель, вид, проекция." +concepts.shaders.matrices.description.detail: шейдере +concepts.shaders.matrices.description.link: рендерера вращающегося куба +concepts.shaders.matrices.details: Порядок хранения определяет расположение элементов матрицы в памяти; порядок умножения определяет преобразование. Обе стороны должны быть согласованы. Добавление транспонирования без проверки обоих аспектов может скрыть одно несоответствие, вызвав другое. +concepts.shaders.matrices.title: Согласованность хранения и умножения матриц +concepts.shaders.title: Данные шейдеров и привязка +concepts.synchronization.backends.description: DirectX 12 и Vulkan кодируют переходы текстур с информацией о layout и доступе. В реализации {transition} для Metal в Zenith.NET операций нет. Metal группирует записанную работу в энкодеры рендеринга и вычислений. Бэкенд вставляет барьеры видимости при завершении этих групп, делая предыдущие записи доступными для последующей работы. Явные вызовы {barrier} обрабатывают зависимости, такие как последовательные вычислительные диспатчи внутри одного энкодера. +concepts.synchronization.backends.details: Это различие важно при изменении рабочей нагрузки. В {link} за диспатчем следует графический проход рендеринга, который также создаёт границу энкодера в Metal. Два зависимых вычислительных диспатча не создают такую границу простым изменением объявленного layout текстуры. Сохраняйте переходы, требуемые общим API, и отдельно определяйте зависимость между фактическими командами производства и потребления данных. +concepts.synchronization.backends.details.link: примере вычислений +concepts.synchronization.backends.title: Переход не идентичен на каждом бэкенде +concepts.synchronization.barriers.context: Значение {barrierStagesAll} представляет собой более широкую область видимости, а не автоматический детектор зависимостей. Выбирайте стадии, которые фактически охватывают выполняемую работу, и используйте их только в очереди, поддерживающей эти операции. +concepts.synchronization.barriers.description: "Рассмотрите два вычислительных диспатча: первый записывает данные симуляции, а второй читает их для выполнения следующего шага. Оба используют буферы хранения, поэтому менять layout текстуры не требуется. Вставьте следующую инструкцию между диспатчами в их командном буфере:" +concepts.synchronization.barriers.details: Первый аргумент определяет стадию-производитель, а второй — стадию-потребитель. Барьер устанавливает соответствующую зависимость выполнения и памяти на GPU. Бэкенд транслирует эти стадии в свои правила выполнения и доступа к памяти. Этот барьер не меняет layout текстуры и не ожидает всю работу на устройстве. +concepts.synchronization.barriers.guidance: В примере {link} этот шаблон используется между зависимыми диспатчами. Размещайте барьер в месте возникновения зависимости. Барьер, расположенный после того, как потребитель уже записан, не может упорядочить этого потребителя относительно более раннего производителя. +concepts.synchronization.barriers.guidance.link: симуляции FluidTank +concepts.synchronization.barriers.title: Упорядочивание зависимых команд с помощью барьера +concepts.synchronization.dependencies.description: "Для каждого разделяемого ресурса определите первую и следующую операции доступа, а также выполняет ли какая-либо из них запись. Два чтения одних данных не требуют упорядочивания для защиты содержимого, хотя смена layout или презентация могут вводить другие требования. Запись с последующим чтением, чтение с последующей перезаписью или две записи могут требовать зависимости." +concepts.synchronization.dependencies.details: "Затем выберите механизм в зависимости от того, где эти операции выполняются:" +concepts.synchronization.dependencies.guidance: Эти механизмы взаимосвязаны, но не взаимозаменяемы. Отправка команд по порядку не заменяет все зависимости памяти. Ожидание очереди не объявляет новое состояние layout текстуры, а барьер команд не блокирует вызывающий поток CPU. +concepts.synchronization.dependencies.table.cpuAccess.mechanism: Вызов {wait} для соответствующего значения завершения. +concepts.synchronization.dependencies.table.cpuAccess.situation: CPU должен подождать перед доступом к данным или их освобождением +concepts.synchronization.dependencies.table.crossQueue.mechanism: Передача {timelineValue} в метод {submit} командного буфера-потребителя. +concepts.synchronization.dependencies.table.crossQueue.situation: Отправка в другой очереди создаёт данные +concepts.synchronization.dependencies.table.headings.mechanism: Механизм +concepts.synchronization.dependencies.table.headings.situation: Ситуация +concepts.synchronization.dependencies.table.layoutChange.mechanism: Вызов {commandBufferTransition} с предыдущим и следующим layout. +concepts.synchronization.dependencies.table.layoutChange.situation: Изменение способа использования подресурса текстуры +concepts.synchronization.dependencies.table.pipelineStages.mechanism: Вызов {commandBufferBarrier} с указанием стадий производителя и потребителя. +concepts.synchronization.dependencies.table.pipelineStages.situation: Зависимые стадии GPU в потоке команд +concepts.synchronization.dependencies.title: Анализ производителей и потребителей +concepts.synchronization.description: Команда, считывающая данные, записанные предыдущей командой, зависит от завершения этих записей и их видимости для неё. Записывающая сторона — это производитель (producer); считывающая — потребитель (consumer). Процессору (CPU) также требуется точка завершения перед чтением, перезаписью или освобождением разделяемых данных. Zenith.NET предоставляет барьеры, переходы текстур и временные шкалы для управления этими зависимостями. +concepts.synchronization.layouts.context: Значение {undefined} означает, что предыдущее содержимое сохранять не требуется. Оно подходит для нового изображения или вложения, которое будет полностью очищено. Это не способ избежать отслеживания layout для изображения, содержимое которого будет загружаться, сэмплироваться или накапливаться. +concepts.synchronization.layouts.description: "Флаги назначения описывают поддерживаемые роли текстуры. {textureLayout} описывает, как конкретный подресурс будет использоваться в операции. Подресурс — выбранный уровень mip и слой массива. Изменение layout подготавливает доступ, но не преобразует формат пикселей. Например, вычислительный пример записывает выходную текстуру в layout {storage}, а затем сэмплирует её в графическом проходе. Между этими операциями записывается:" +concepts.synchronization.layouts.details: Этот фрагмент предполагает, что текстура {outputTexture} была создана с назначением {sampledStorage}, а её выбранный подресурс находится в состоянии {storage}. Значение {default} выбирает уровень mip 0 и слой массива 0. Операция не переводит каждый mip или слой текстуры. +concepts.synchronization.layouts.guidance: Приложение предоставляет предыдущий layout. Метод {transition} не ведёт видимый для приложения трекер состояний и не вычисляет это значение из предыдущих команд. Отслеживайте layout везде, где ресурс передаётся между стадиями рендеринга. +concepts.synchronization.layouts.title: Отслеживание layout каждого подресурса текстуры +concepts.synchronization.readback.description: Свойство {isCompleted} лишь опрашивает, достигла ли временная шкала GPU определённого значения. Оно само по себе не возвращает командные буферы и не копирует промежуточные скачанные данные по целевому указателю приложения. +concepts.synchronization.readback.details: "{commandBufferDownload} сначала записывает копирование во внутреннее хранилище считывания. При сбросе завершённого командного буфера для повторного использования CPU копирует данные по предоставленному указателю. Сохраняйте целевую память выделенной, а управляемую память закреплённой до возврата из {wait} для этой отправки считывания. Читать данные или освобождать память можно только после этого. Ожидание более поздней отправки другой очереди само по себе не опрашивает очередь, управляющую считыванием." +concepts.synchronization.readback.guidance: "Поэтому недостаточно опрашивать {isCompleted} и сразу читать данные по адресу назначения асинхронного считывания. В разделе «{link}» рассматриваются прямое копирование и передача через промежуточное хранилище." +concepts.synchronization.readback.guidance.link: Управление ресурсами +concepts.synchronization.readback.title: Завершение работы GPU и скачанные данные CPU — это разные шаги +concepts.synchronization.reuse.description: Для простого рендерера немедленное ожидание после каждого кадра наиболее прозрачно. Для перекрытия работы выделите для незавершённых кадров раздельные изменяемые данные и сохраняйте значение завершения для последнего использования в каждом кадре. Перед обновлением буфера констант, заменой текстуры или освобождением конвейера завершите все ожидающие обращения к затронутому ресурсу. +concepts.synchronization.reuse.details: При изменении размера или выключении остановите новые операции перед ожиданием старых. Вызовы {swapChainResize}, освобождение ресурсов и освобождение контекста не служат общими операциями ожидания для задач приложения. В учебнике с треугольником размер можно безопасно менять между обратными вызовами, поскольку каждый предыдущий кадр уже завершил свою отправку. +concepts.synchronization.reuse.guidance: Текущий метод {swapChainPresent} также отправляет сигнал и ожидает завершения в графической очереди после операции вывода. Поэтому удаление явного ожидания отправки в примере с треугольником само по себе не создаёт перекрывающийся цикл вывода. Ожидание в очереди графики также ничего не говорит о независимой работе, всё ещё выполняющейся в другой очереди. +concepts.synchronization.reuse.title: Повторное использование данных только после последнего обращения +concepts.synchronization.timelines.context: "Перед тем как CPU прочитает, перезапишет или освободит эти ресурсы, дождитесь их окончательного использования:" +concepts.synchronization.timelines.description: Временная шкала отслеживает завершение операций в очереди с помощью монотонно возрастающих значений. Метод {submit} возвращает {timelineValue}, содержащий эту шкалу и значение, связанное с отправкой. Значения завершения из разных временных шкал нельзя сравнивать только по их числовому полю {value}. +concepts.synchronization.timelines.details: "Предположим, что {producer} и {consumer} — это уже записанные командные буферы из двух очередей одного контекста. Производитель записывает данные, которые использует потребитель. Отправьте их следующим образом:" +concepts.synchronization.timelines.guidance: Передача полученного значения заставляет очередь-потребитель ожидать его на GPU. Процессор в данном случае не вызывает {producedWait}. Поддерживайте разделяемые ресурсы активными до завершения {consumed} и записывайте любые изменения layout текстуры, требуемые потребителем. +concepts.synchronization.timelines.notes: Метод {wait} ожидает достижения этого значения временной шкалы, а затем проверяет завершённые отправки в ответственной очереди. Завершённые командные буферы сбрасываются для повторного использования, а их промежуточные скачанные данные копируются в предоставленные буферы CPU. Метод {queueTimelineSignal} также может поставить в очередь точку завершения после задач, уже отправленных в эту очередь. Вызов {signal} не означает, что GPU уже достиг этой точки. +concepts.synchronization.timelines.title: Использование временной шкалы для завершения и передачи между очередями +concepts.synchronization.title: Синхронизация +home.actions.reference: Справочник API +home.actions.tutorial: Начать с треугольника +home.entries.description: Первый кадр. Наглядный пример. Подробный обзор API. +home.entries.label: Обзор документации +home.entries.reference.action: Изучить API +home.entries.reference.category: Справочник +home.entries.reference.description: Найдите типы, сигнатуры и члены, на которых строится ваше приложение. +home.entries.reference.title: Справочник API +home.entries.samples.action: Обзор примеров +home.entries.samples.category: Примеры +home.entries.samples.description: Изучите специализированные методы рендеринга и вычислений на примерах исходного кода. +home.entries.samples.title: Примеры +home.entries.title: Начните разработку. +home.entries.tutorial.action: Начать учебник +home.entries.tutorial.category: Учебник +home.entries.tutorial.description: "Создайте полноценное приложение рендеринга: от настройки проекта до первого кадра." +home.entries.tutorial.title: Первый треугольник +home.introduction.accent: "На C#." +home.introduction.description: Создавайте ресурсы, записывайте команды и отправляйте задачи графики и вычислений через единый .NET API. +home.introduction.title: Создайте свой рендерер. +home.meta.description: "Единый C# API для графики и вычислений на DirectX, Metal и Vulkan." +home.scene.description: Демонстрация вращающейся геометрии. Перетаскивайте мышью или используйте клавиши со стрелками для изменения ракурса. +home.scene.label: Отображение геометрии +home.scene.surface: Поверхность +home.scene.wireframe: Каркас +home.title: Современный RHI для .NET +learning.concepts.description: Поймите, как взаимодействуют команды, ресурсы, данные шейдеров и синхронизация, прежде чем объединять проходы рендеринга. +learning.concepts.execution.description: Записывайте задачи для GPU, отправляйте их и поддерживайте ресурсы активными. +learning.concepts.platforms.description: Подключите нативное окно или элемент управления рендерингом интерфейса. +learning.concepts.resources.description: Выбирайте назначение ресурсов, размещение в памяти и представления. +learning.concepts.shaders.description: "Согласуйте структуру данных C# и дескрипторы ресурсов с кодом на Slang." +learning.concepts.synchronization.description: Упорядочивайте зависимые обращения и отслеживайте завершение операций. +learning.concepts.title: Основные концепции +learning.description: Начните с пошагового учебника по отрисовке треугольника. Затем используйте наглядные примеры и руководства по концепциям, чтобы освоить ресурсы, структуры данных и зависимости более сложного рендерера. +learning.entries.samples.action: Обзор примеров +learning.entries.samples.description: "Примеры на C# и Slang для геометрии, вычислений, запросов лучей и mesh shading." +learning.entries.tutorial.action: Открыть учебник +learning.entries.tutorial.description: Создайте консольное приложение, откройте окно и нарисуйте треугольник. +learning.meta.description: Начало работы с Zenith.NET и знакомство с моделью программирования. +learning.title: Обучение +reference.description: Справочник по типам ресурсов, сигнатурам команд и интеграции с платформами. +reference.entries.commands.description: Записывайте команды графики, вычислений и передачи данных. +reference.entries.commands.label: Запись команд +reference.entries.context.description: Создавайте ресурсы GPU для выбранного бэкенда. +reference.entries.context.label: Начало работы +reference.meta.description: Изучите типы и члены библиотеки Zenith.NET. +reference.navigation.core: Обзор основного API. +reference.title: Справочник API +samples.computeShader.description: "Преобразует изображение в оттенки серого с помощью вычислительного диспатча и отображает полученную текстуру. Демонстрирует дескрипторы ресурсов для сэмплируемой входной текстуры и записываемой выходной текстуры, округление количества групп потоков в большую сторону и проверку границ в шейдере. Сохраняйте включённый ресурс {assetsTexturesShokoPng}: рендерер обрабатывает его один раз и выводит результат в последующих кадрах." +samples.computeShader.details: "{computeShaderRendererCs} · {computeShaderSlang}" +samples.computeShader.title: Вычислительный шейдер +samples.cube.description: Добавляет индексную отрисовку, матрицы модели, вида и проекции в буфере констант, а также тест глубины. Текстура глубины пересоздаётся при изменении размера. Используйте этот пример при переходе от геометрии в пространстве отсечения к трансформированному объекту; рендерер использует вложение глубины и трафарета формата {d32FloatS8UInt}. +samples.cube.details: "{spinningCubeRendererCs} · {spinningCubeSlang}" +samples.cube.title: Вращающийся куб +samples.description: "Выберите пример для интересующей вас возможности. Каждый пример содержит ссылки на рендерер C# и его шейдер Slang. Если нужно пошаговое объяснение приложения с пустого проекта, начните с учебника «{link}»." +samples.description.link: Первый треугольник +samples.execution.description: "{link} содержит шесть независимых рендереров в одном настольном приложении. Используйте .NET 10 SDK и поддерживаемый бэкенд для настольных систем, как описано ниже. Соберите и запустите приложение, затем выберите пример в меню консоли:" +samples.execution.description.link: ZenithTutorials +samples.execution.details: "Хост выбирает DirectX 12 в Windows, Metal в macOS и Vulkan в Linux. Используйте устройство, драйвер и среду компиляции шейдеров, поддерживаемые выбранным бэкендом. Оконному пути Linux требуется X11 или XWayland. {link} объявляет зависимости пакетов и копирует шейдеры и текстуры, необходимые во время выполнения." +samples.execution.details.link: "Файл проекта" +samples.execution.guidance: Примеры используют общий код создания окна и вывода на экран. Вы можете изучать любой пример независимо в зависимости от интересующей вас темы. +samples.execution.title: Запуск примеров из учебника +samples.host.description: "{appCs} создаёт контекст, окно и цепочку обмена. Он получает командный буфер, вызывает выбранный рендерер, отправляет кадр и выводит его. Интерфейс {iRendererCs} определяет методы обновления, рендеринга, изменения размера и освобождения ресурсов." +samples.host.details: Вычисления и трассировка лучей создают закадровые текстуры. {texturePresenterCs} и {presentTextureSlang} отрисовывают эти текстуры в выходную текстуру текущего кадра окна. Хост сохраняет владение отправкой команд и выводом цепочки обмена. +samples.host.title: Общий хост и презентация +samples.indirectDrawing.description: "Отрисовывает несколько копий куба с помощью буфера аргументов косвенной индексной отрисовки и данных экземпляров в структурированном буфере. CPU предоставляет аргументы и обновляет преобразования. Пример помогает понять разметку косвенных аргументов и доступ шейдера к данным экземпляров перед добавлением аргументов, создаваемых GPU." +samples.indirectDrawing.details: "{indirectDrawingRendererCs} · {indirectDrawingSlang}" +samples.indirectDrawing.title: Косвенная отрисовка +samples.meshShading.description: Использует task-шейдер для отсечения экземпляров сфер и передачи их индексов в mesh-шейдер, который генерирует геометрию. Рендерер проверяет {contextCapabilitiesMeshShadingSupported} перед созданием конвейера. Используйте для изучения передачи дескрипторов ресурсов и полезной нагрузки между стадиями задач и мешей. +samples.meshShading.details: "{meshShadingRendererCs} · {meshShadingSlang}" +samples.meshShading.title: Mesh Shading +samples.rayTracing.description: Строит структуры ускорения нижнего и верхнего уровней для плоскости и процедурных сфер, а затем выполняет встроенные inline-запросы лучей в вычислительном шейдере. Рендерер проверяет {contextCapabilitiesRayTracingSupported} перед формированием рабочей нагрузки. Используйте для изучения структур ускорения и обхода лучей на стороне шейдера. +samples.rayTracing.details: "{rayTracingRendererCs} · {rayTracingSlang}" +samples.rayTracing.title: Трассировка лучей +samples.title: Примеры +samples.triangle.description: Создаёт буфер вершин и соответствующую разметку входных данных, затем отрисовывает три вершины через графический конвейер. Используйте для понимания связи между созданием ресурсов и командами прохода рендеринга. +samples.triangle.details: "{helloTriangleRendererCs} · {helloTriangleSlang} · {link}" +samples.triangle.details.link: Полный учебник +samples.triangle.title: Привет, треугольник +samples.workloads.description: "{link} основного репозитория содержит приложения, сочетающие несколько возможностей. Их проекты ссылаются на исходный код библиотеки. Из локальной копии Zenith.NET запустите выбранный проект, например:" +samples.workloads.description.link: "Каталог Experiments" +samples.workloads.details: Оконные эксперименты используют те же варианты хоста для Windows, macOS и Linux/X11. Сведения об отрисовке внутри Avalonia, WinForms, WPF, WinUI/Uno или MAUI, жизненном цикле кадров элемента управления и ссылки на реализации см. в разделе {link}. +samples.workloads.details.link: Интеграция с платформами +samples.workloads.table.cornellBox.example: "{link}" +samples.workloads.table.cornellBox.example.link: CornellBox +samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: Трассировка путей, шумоподавление, тональная компрессия, апскейлинг и элементы управления ImGui. Требуется поддержка трассировки лучей и среда компиляции шейдеров для бэкенда настольной платформы. +samples.workloads.table.fluidTank.example: "{link}" +samples.workloads.table.fluidTank.example.link: FluidTank +samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: Вычислительное моделирование жидкости, зависимости между стадиями симуляции и многопроходный рендеринг поверхности. Требуется бэкенд настольной платформы и среда компиляции шейдеров. +samples.workloads.table.headings.example: Пример +samples.workloads.table.headings.whatItDemonstratesAndRequires: Что демонстрирует и требования +samples.workloads.table.inkCanvas.example: "{link}" +samples.workloads.table.inkCanvas.example.link: InkCanvas +samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: Отрисовка с помощью Skia и обработка ввода в нативном окне. Требуется бэкенд и нативная библиотека Skia для целевой платформы. +samples.workloads.table.platformDetection.example: "{link}" +samples.workloads.table.platformDetection.example.link: PlatformDetection +samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: "Пытается создать контекст для каждого бэкенда и сообщает о возможностях устройства. Ошибка создания контекста отображается как отсутствие поддержки; такой результат может также указывать на отсутствующий драйвер или зависимость среды выполнения." +samples.workloads.title: Изучение более сложных нагрузок +tutorial.context.description: Теперь окно открывается, но мы ещё не создали объекты GPU, которые будут выполнять в него рендеринг. {graphicsContext} обеспечивает доступ к выбранному графическому бэкенду и его очередям команд. +tutorial.context.details: "Вставьте этот блок {emphasis}:" +tutorial.context.details.emphasis: после директив using, перед {iWindowWindow} +tutorial.context.guidance: Ветвления выбирают DirectX 12 в Windows, Metal в macOS и Vulkan в Linux. Последующий код рендеринга использует общий API Zenith.NET. Во время разработки мы запрашиваем валидацию и выводим сообщения, передаваемые через {validationMessage}. Диагностика зависит от бэкенда и компонентов валидации, доступных в системе. +tutorial.context.title: Создание графического контекста +tutorial.description: Создайте консольное приложение .NET, которое открывает окно и отрисовывает треугольник с плавным градиентным переходом цветов. Вы узнаете, как взаимодействуют данные вершин, шейдеры и состояние конвейера, а затем запишете и отправите команды, формирующие изображение. +tutorial.details: Выполняйте разделы по порядку. Сначала вы откроете пустое окно, затем отобразите цвет фона и, наконец, нарисуете треугольник. Каждый контрольный этап подтверждает правильность работы одной части приложения перед добавлением следующей. Инициализация выполняется один раз, а обратный вызов рендеринга записывает новый кадр при каждом вызове. +tutorial.draw.context: "Аргументы метода {draw}:" +tutorial.draw.description: "В обратном вызове {windowRender} замените комментарий {addTheTriangleDrawCommandsHereLater} следующими тремя командами между {beginRenderPass} и {endRenderPass}:" +tutorial.draw.details: "Команда {setPipeline} выбирает созданные шейдеры и состояние конвейера. Установите её перед привязкой данных вершин: бэкенд использует разметку входных данных конвейера для интерпретации привязки." +tutorial.draw.guidance: Команда {setVertexBufferVertexBuffer} привязывает буфер, начиная с байтового смещения 0, к входному слоту 0. Этот слот соответствует единственной записи в {inputLayouts}. Она не копирует и не загружает данные повторно. +tutorial.draw.notes: На этом этапе команды всё ещё только записаны. Вызовы {submitWait} и {present}, уже находящиеся в конце обратного вызова рендеринга, выполняют работу и выводят результат. Очистка остаётся необходимой, так как треугольник покрывает лишь часть изображения; фон также должен получать определённый цвет в каждом кадре. +tutorial.draw.table.firstInstance.meaning: Начать нумерацию экземпляров с нуля. +tutorial.draw.table.firstVertex.meaning: Начать с первой вершины в буфере. +tutorial.draw.table.headings.argument: Аргумент +tutorial.draw.table.headings.description: Значение +tutorial.draw.table.headings.meaning: Назначение +tutorial.draw.table.instanceCount.meaning: Нарисовать одну копию треугольника. +tutorial.draw.table.vertexCount.meaning: Считать три вершины. +tutorial.draw.title: Отрисовка треугольника внутри прохода +tutorial.execution.description: "Соберите и запустите приложение из каталога {firstTriangle}:" +tutorial.execution.details: В окне должен появиться треугольник с красным верхним углом, зелёным правым нижним углом и синим левым нижним углом на тёмном фоне. Внутри треугольника должен быть плавный градиент между этими цветами. +tutorial.execution.guidance: "Измените размер окна. Обратный вызов изменения размера обновляет размеры фреймбуфера и изменяет размер цепочки обмена. Проход рендеринга задаёт область просмотра для этого изображения. Позиции вершин остаются нормализованными, поэтому треугольник занимает ту же долю ширины и высоты окна; смена соотношения сторон может растянуть его форму. Для сохранения пропорций объекта нужна стратегия проекции или области просмотра, что выходит за рамки первой отрисовки." +tutorial.execution.title: Запуск, изменение размера и закрытие +tutorial.frame.commands.context: После {endRenderPass} второй переход подготавливает изображение к презентации. Метод {submit} завершает запись и отправляет командный буфер; {wait} ожидает завершения этой отправки на GPU. Затем {present} запрашивает отображение отрисованного изображения. +tutorial.frame.commands.description: Проход рендеринга группирует операции отрисовки, использующие одни и те же вложения. Здесь цветовым вложением выступает выходная текстура цепочки обмена — изображение, принимающее нашу отрисовку. Метод {colorAttachmentClear} создаёт описание, предписывающее проходу выполнить очистку заданным цветом RGBA и сохранить результат по завершении прохода. Метод {beginRenderPass} записывает эти инструкции; GPU выполняет очистку после отправки команд. +tutorial.frame.commands.details: В квадратных скобках указано наше единственное цветовое вложение. Аргумент {null} означает отсутствие вложения глубины/трафарета, которое хранило бы значения глубины и маски трафарета для соответствующих тестов. +tutorial.frame.commands.guidance: Метод {beginRenderPass} задаёт область просмотра (viewport) и область отсечения (scissor), покрывающие вложение. Область просмотра преобразует координаты рендеринга в пиксели, а область отсечения ограничивает пиксели, доступные для записи. Эти значения по умолчанию покрывают всю выходную текстуру, что и требуется для нашего треугольника. +tutorial.frame.commands.title: Очистка, отправка и презентация +tutorial.frame.description: Сначала заполните изображение одним цветом фона. Эта операция называется очисткой (clear). Если этот цвет появится в окне, значит поверхность, отправка команд и путь вывода работают корректно. Этот контрольный этап позволяет проверить цикл кадров перед добавлением геометрии и шейдеров. +tutorial.frame.details: "Обратный вызов рендеринга — это код, который Silk.NET вызывает, когда наступает время отрисовки кадра. Этому вызову не требуется аргумент прошедшего времени события, поэтому он обозначен как {value}. Зарегистрируйте его {emphasis}:" +tutorial.frame.details.emphasis: перед {windowRun} +tutorial.frame.target.description: Метод {graphicsQueueCommandBuffer} возвращает командный буфер с уже начатой записью. Запись описывает работу для GPU, но не выполняет её немедленно. +tutorial.frame.target.details: Первый переход {transition} подготавливает выходную текстуру для доступа в качестве цветового вложения. Значение {default} выбирает уровень mip 0 и слой массива 0. Мы используем {undefined} в качестве предыдущего layout, поскольку мы очистим всё изображение и отбросим его прежнее содержимое. Проход, которому необходимо сохранить существующее содержимое, должен использовать своё реальное предыдущее состояние layout. +tutorial.frame.target.guidance: В каждом кадре используйте актуальную выходную текстуру цепочки обмена. Презентация может изменить доступное изображение, поэтому текстура, сохранённая из предыдущего кадра, не является постоянной целью рендеринга окна. +tutorial.frame.target.title: Подготовка выходной текстуры +tutorial.frame.title: Отображение цвета фона +tutorial.geometry.data.description: Добавьте этот массив {emphasis}. Последующие шаги создания ресурсов также размещаются перед этим обратным вызовом в указанном порядке. +tutorial.geometry.data.description.emphasis: перед {windowRender} +tutorial.geometry.data.details: "Каждый элемент массива создаёт структуру {vertex}. Два внутренних выражения {new} задают координаты {vector3} и цвет {vector4}. Вершины описывают верхний, правый нижний и левый нижний углы. Вершинный шейдер предоставит четвёртую координату положения, {w}. При w = 1 координаты x и y напрямую соответствуют нормализованным координатам устройства: -1 и +1 соответствуют краям изображения, а 0 — центру. Эти координаты не зависят от размеров окна в пикселях." +tutorial.geometry.data.guidance: "Каждый цвет содержит компоненты: красный, зелёный, синий и альфа. Альфа-канал равен 1 во всех трёх вершинах. Все три положения имеют z = 0, располагаясь в одной плоскости. Для этих координат не требуются камера или матрица преобразования, поскольку они уже заданы в системе координат вывода. Для этого плоского треугольника мы также отключим смешивание цветов и тест глубины, отказавшись от буфера глубины." +tutorial.geometry.data.title: Выбор координат углов +tutorial.geometry.description: Вершина — это точка вместе с данными, необходимыми для её отрисовки. У нашего треугольника три вершины, по одной на каждый угол. Каждая содержит положение и цвет. GPU интерполирует цвета, вычисляя промежуточные значения по всей площади треугольника. +tutorial.geometry.format.description: "Добавьте это объявление {emphasis}:" +tutorial.geometry.format.description.emphasis: в конце {programCs}, после инструкций очистки +tutorial.geometry.format.details: "Модификатор {file} ограничивает тип файлом {programCs}, а конструктор инициализирует поля положения и цвета. {layoutKindSequential} сохраняет порядок объявления полей. {position} содержит три 32-битных числа с плавающей запятой, а {color} — четыре. Положение начинается с байта 0, цвет — с байта 12, и вся вершина занимает 28 байт. Эту же разметку мы зададим графическому конвейеру." +tutorial.geometry.format.title: Определение вершины +tutorial.geometry.title: Передача трёх вершин в GPU +tutorial.geometry.upload.context: Ключевое слово {fixed} предотвращает перемещение массива сборщиком мусора во время использования его адреса. Для этого буфера с возможностью записи CPU метод {upload} отображает, копирует и отменяет отображение памяти до возврата управления, поэтому массив не нужно удерживать закреплённым в дальнейшем. Буфер должен оставаться активным на протяжении всего рендеринга, а загрузку достаточно выполнить один раз, поскольку вершины не меняются. +tutorial.geometry.upload.description: "Управляемый массив — это данные в памяти CPU. Объект {buffer} предоставляет GPU память, из которой можно читать вершины. После массива добавьте:" +tutorial.geometry.upload.details: "Общий размер — {sizeofVertexVerticesLength}: 28 байт на вершину, три вершины, всего 84 байта. {bufferUsagesVertex} разрешает доступ для вершинного ввода. Режим {cpuWriteOnly} позволяет CPU напрямую инициализировать этот небольшой буфер. Шаг в описании буфера задаёт размер элемента; разметка входных данных ниже объяснит механизму выборки вершин, как читать отдельные атрибуты." +tutorial.geometry.upload.guidance: Создание буфера не заполняет его данными. Метод {upload} копирует массив в выделенную память, начиная с байтового смещения 0 в целевом буфере. Его описание источника предоставляет указатель и количество копируемых байт. +tutorial.geometry.upload.notes: Добавьте вызов {vertexBufferDispose} непосредственно перед {swapChainDispose} в блоке очистки в конце {programCs}. Для больших объёмов статической геометрии в руководстве {link} объясняется, когда следует выбирать память только для GPU и передачу данных через промежуточные буферы. +tutorial.geometry.upload.notes.link: Управление ресурсами +tutorial.geometry.upload.title: Выделение буфера и загрузка массива +tutorial.input.description: "Байты вершин и шейдеры готовы. Теперь опишите, как GPU должен считывать каждую вершину. Атрибут — это отдельное значение, например положение или цвет. Разметка входных данных задаёт формат и байтовое смещение каждого атрибута; шаг (stride) задаёт расстояние в байтах от одной вершины до следующей. Добавьте этот блок инициализации после создания шейдеров:" +tutorial.input.details: "Метод {inputLayoutAdd} добавляет элемент с текущим смещением шага и увеличивает шаг на размер этого элемента. Он не анализирует структуру C#. В данном случае формируется следующее соответствие между памятью CPU и входами шейдера:" +tutorial.input.guidance: "Изменение порядка полей C# или выравнивания без обновления этого описания приведёт к тому, что GPU прочитает неверные байты. Значение {semanticIndex} по умолчанию равно нулю, что соответствует {pOSITION0} и {cOLOR0}. Оба элемента принадлежат одному буферу, поэтому конвейер будет содержать одну входную разметку, и мы привяжем этот буфер к слоту 0." +tutorial.input.table.headings.byteOffset: Байтовое смещение +tutorial.input.table.headings.cField: "Поле C#" +tutorial.input.table.headings.format: Формат +tutorial.input.table.headings.shaderInput: Вход шейдера +tutorial.input.table.nextVertex.cField: Следующая вершина +tutorial.input.table.nextVertex.format: "Полный шаг: 28 байт" +tutorial.input.table.nextVertex.shaderInput: Следующая входная запись +tutorial.input.table.vertexColor.format: "{float4} (16 байт)" +tutorial.input.table.vertexPosition.format: "{float3} (12 байт)" +tutorial.input.title: Описание разметки входных вершинных данных +tutorial.lifecycle.description: "Готовое приложение повторяет следующую последовательность:" +tutorial.lifecycle.details: "Закрытие окна приводит к выходу из метода {run}. Каждый отрисованный кадр уже дождался завершения работы на GPU, поэтому мы можем освободить использованные ресурсы. Блок очистки после {windowRun} должен выглядеть так:" +tutorial.lifecycle.guidance: "Освобождайте цепочку обмена до её нативного окна, а контекст — после всех его ресурсов. Очередь владеет отправленными командными буферами и повторно использует их; выходной текстурой владеет цепочка обмена. Поэтому для этих командных буферов и выходной текстуры в данном приложении не нужен отдельный вызов {dispose}." +tutorial.lifecycle.title: Жизненный цикл одного кадра +tutorial.pipeline.behavior: "После разметки входных данных добавьте:" +tutorial.pipeline.context: "{cullNone} задаёт заполнение треугольника без отсечения по ориентации грани. Порядок вершин определяет направление обхода, поэтому отключение отсечения не позволит этому порядку скрыть наш первый треугольник." +tutorial.pipeline.description: Теперь у нас есть данные вершин, разметка входных данных и два шейдера. Объект {graphicsPipeline} объединяет их и определяет, как GPU собирает вершины в примитивы и записывает результат во вложение. +tutorial.pipeline.details: "Конвейер объединяет программируемые стадии шейдеров с настройками фиксированных функций, которые управляют такими операциями GPU, как сборка треугольников, отсечение граней и смешивание цветов. Для этого треугольника выберите следующие параметры:" +tutorial.pipeline.guidance: Формат цвета берётся из {swapChainDescFormat}. Он должен совпадать с изображением, используемым проходом рендеринга. Значение {count1} означает один сэмпл на пиксель. +tutorial.pipeline.item: "{triangleList} собирает каждую последовательную тройку вершин в один треугольник. Мы передадим три вершины и выполним одну отрисовку, поэтому индексный буфер не нужен." +tutorial.pipeline.notes: "{depthNone} отключает проверку и запись глубины, что соответствует проходу без вложения глубины." +tutorial.pipeline.reference: "{opaque} отключает смешивание, поэтому цвет фрагментного шейдера заменяет фон внутри треугольника." +tutorial.pipeline.title: Связывание шейдеров и разметки вершин +tutorial.pipeline.usage: Объекты шейдеров можно освободить после создания конвейера, как это сделано в демонстрационном рендерере. Сам конвейер должен оставаться активным для каждого кадра, где он используется для отрисовки. Добавьте {pipelineDispose} перед {vertexBufferDispose} в блоке очистки. Создание конвейера — последний шаг инициализации перед обратным вызовом рендеринга. +tutorial.pipeline.validation: Описание конвейера объявляет конфигурацию вложений; оно не создаёт дополнительного изображения. Массив {inputLayouts} содержит одну запись, так как положение и цвет хранятся вместе в одном буфере. +tutorial.presentation.title: Подключение GPU к окну +tutorial.project.context: Включите {emphasis} ({allowUnsafeBlocks}) в настройках сборки проекта. Это необходимо для передачи данных вершин в GPU и для нативных вызовов вспомогательного класса окна. +tutorial.project.context.emphasis: Разрешить небезопасный код +tutorial.project.description: "Создайте проект и перейдите в его каталог:" +tutorial.project.details: "Установите пакеты:" +tutorial.project.guidance: Пакет {zenithNET} предоставляет общий API рендеринга. Три пакета бэкендов позволяют одной и той же программе выбирать реализацию для своей платформы. {zenithNETCompiler} компилирует шейдеры Slang — небольшие программы GPU, которые мы напишем позже, — для этой реализации. Silk.NET предоставляет окно и цикл обработки событий. +tutorial.project.title: Создание консольного проекта +tutorial.requirements.context: Вы можете следовать инструкциям на этой странице с чистого проекта. Пример {link} и его {detail} доступны в качестве справочника по используемым здесь API рендеринга и окон. +tutorial.requirements.context.detail: общий хост +tutorial.requirements.context.link: Hello Triangle +tutorial.requirements.description: "Вам понадобятся {emphasis}, редактор кода или IDE, а также компьютер с GPU и драйвером, поддерживаемыми бэкендом Zenith.NET. Достаточно базовых знаний C#; графические концепции вводятся по мере их использования. Это обычный консольный проект {net10}. Бэкенд преобразует операции Zenith.NET в вызовы графического API, такого как DirectX 12, Metal или Vulkan. Приложение выбирает один из них при запуске:" +tutorial.requirements.description.emphasis: .NET 10 SDK +tutorial.requirements.details: Для Linux требуется сессия оконного менеджера, совместимая с X11, для используемого здесь оконного пути. Дополнительные возможности трассировки лучей и mesh shading для этого треугольника не требуются. +tutorial.requirements.guidance: Zenith.NET выполняет рендеринг в поверхность, предоставляемую приложением. Silk.NET.Windowing создаёт окно рабочего стола и обрабатывает его события. В macOS целевым объектом вывода является слой Metal ({cAMetalLayerCs}); вспомогательный класс окна из учебника подключает этот слой автоматически. +tutorial.requirements.table.headings.graphicsBackend: Графический бэкенд +tutorial.requirements.table.headings.platform: Платформа +tutorial.requirements.table.headings.windowSurface: Оконная поверхность +tutorial.requirements.table.linux.graphicsBackend: Vulkan 1.4 +tutorial.requirements.table.linux.platform: Linux +tutorial.requirements.table.linux.windowSurface: Окно и дисплей X11; XWayland также подходит +tutorial.requirements.table.macOS.graphicsBackend: Metal 4 +tutorial.requirements.table.macOS.platform: macOS +tutorial.requirements.table.macOS.windowSurface: Слой Metal, подключённый к окну +tutorial.requirements.table.windows.graphicsBackend: DirectX 12 +tutorial.requirements.table.windows.platform: Windows +tutorial.requirements.table.windows.windowSurface: Дескриптор окна Win32 +tutorial.requirements.title: Перед началом работы +tutorial.resize.context: "Снова запустите {dotnetRun}. Теперь окно должно иметь равномерный тёмный фон, который сохраняется и при изменении размеров окна. Оставьте этот обратный вызов: треугольник будет отрисован внутри его существующего прохода рендеринга." +tutorial.resize.description: "Изображения цепочки обмена должны соответствовать размерам фреймбуфера. Используйте {framebufferResize} для реагирования на изменения размера в пикселях, включая изменения из-за масштабирования экрана. После обратного вызова рендеринга, перед {windowRun}, добавьте:" +tutorial.resize.details: Silk.NET различает изменение размера окна и {link}. Нам требуется последнее, поскольку цепочка обмена хранит пиксели. У свёрнутого окна фреймбуфер может иметь нулевой размер. В этом случае оба обратных вызова пропускают работу с GPU. После изменения размера проход рендеринга будет использовать новые размеры вложения для области просмотра и отсечения. +tutorial.resize.details.link: изменение размера фреймбуфера +tutorial.resize.guidance: Мы выполняем ожидание после каждой отправки, поэтому ни один из предыдущих кадров не использует изображения в момент, когда обработчик изменения размера заменяет их. Текущая реализация {present} также ожидает завершения в очереди графики. Этот простой цикл гарантирует, что работа одного кадра завершена до начала следующего; в разделе {link} рассматривается более сложное планирование. +tutorial.resize.guidance.link: Синхронизация +tutorial.resize.title: Реакция на изменение размера +tutorial.shaders.compilation.context: Компиляция выполняется один раз во время инициализации. Свойство {appContextBaseDirectory} находит скопированный шейдер рядом с исполняемым файлом независимо от текущего рабочего каталога. Эти шейдеры используют только вершинный ввод, поэтому привязывать буферы констант, текстуры или дескрипторы ресурсов пока не требуется. +tutorial.shaders.compilation.description: В свойствах файла {triangleSlang} установите параметр {emphasis} в значение {detail}. Благодаря этому шейдер будет скопирован рядом с исполняемым файлом. +tutorial.shaders.compilation.description.detail: Копировать более позднюю версию +tutorial.shaders.compilation.description.emphasis: Копировать в выходной каталог +tutorial.shaders.compilation.details: "Вернитесь в {programCs}. После загрузки вершин добавьте эти инструкции инициализации перед обратным вызовом рендеринга:" +tutorial.shaders.compilation.guidance: "{zenithCompiler} возвращает описание шейдера с кодом для запрошенного графического API. {createShader} создаёт соответствующий объект бэкенда. Важны и графический API, и имена точек входа: используйте {contextGraphicsApi} и пишите {vSMain} и {fSMain} точно как в файле Slang." +tutorial.shaders.compilation.title: Компиляция для выбранного бэкенда +tutorial.shaders.context: Структура {fSInput} связывает выход вершинного шейдера со входом фрагментного шейдера. При записи вершинным шейдером семантика {sVPOSITION} задаёт координаты в пространстве отсечения — четыре координаты, по которым GPU определяет, что попадает в видимую область изображения. Семантика {cOLOR0} передаёт цвет для интерполяции между вершинами. Обе стадии должны согласовывать его тип и семантику. +tutorial.shaders.description: Шейдер — это программа, выполняемая на GPU. Для этой отрисовки требуются вершинный шейдер для позиционирования вершин и фрагментный шейдер для формирования цветов внутри треугольника. Мы напишем их на языке шейдеров Slang и скомпилируем две точки входа из одного файла. Точка входа — это функция, с которой начинается выполнение стадии шейдера. +tutorial.shaders.details: "Создайте файл {triangleSlang}, начав со следующих двух структур:" +tutorial.shaders.fragment.description: "Добавьте точку входа фрагментного шейдера в тот же файл:" +tutorial.shaders.fragment.details: Растеризация определяет, какие пиксели изображения покрывает треугольник. Она генерирует фрагменты — данные, обрабатываемые фрагментным шейдером, с цветами вершин, интерполированными по покрытой области. Функция {fSMain} возвращает этот интерполированный цвет через семантику {sVTARGET}, которая идентифицирует первое цветовое вложение. +tutorial.shaders.fragment.guidance: Интерполяция цвета вершин происходит отдельно от смешивания во вложении. Смешивание (blending) комбинирует вывод фрагмента с цветом, уже сохранённым во вложении. Наше непрозрачное состояние смешивания отключает эту комбинацию, поэтому интерполированный цвет заменяет фон внутри треугольника. +tutorial.shaders.fragment.title: Окрашивание фрагментов +tutorial.shaders.guidance: "Структура {vSInput} описывает, что вершинный шейдер получает из буфера вершин. Семантики {pOSITION0} и {cOLOR0} идентифицируют входные данные; одни лишь имена полей C# не задают это сопоставление." +tutorial.shaders.title: Написание двух стадий шейдера +tutorial.shaders.vertex.description: "Добавьте точку входа вершинного шейдера в {triangleSlang}:" +tutorial.shaders.vertex.details: GPU вызывает эту точку входа для каждой входной вершины. Она добавляет однородную координату {w} к положению и передаёт цвет дальше. После стадии вершин координаты делятся на w; в данном случае это деление оставляет x, y и z без изменений. Именно поэтому выбранные выше координаты можно трактовать непосредственно как нормализованные координаты устройства. +tutorial.shaders.vertex.title: Позиционирование каждой вершины +tutorial.surface.description: "Контексту также необходимо знать, куда выводить изображение. Добавьте следующий код {emphasis}:" +tutorial.surface.description.emphasis: после {windowCenter} и перед {windowRun} +tutorial.surface.details: Структура {surface} описывает нативный целевой объект презентации и его размеры в пикселях. Фреймбуфер — это пиксельное изображение, связанное с окном. Свойство {framebufferSize} задаёт его размеры в пикселях; логические размеры окна могут отличаться при включённом масштабировании экрана. +tutorial.surface.guidance: Поверхность соответствует бэкенду, выбранному ранее. Windows предоставляет дескриптор окна, Linux — дисплей и окно X11, а вспомогательный класс macOS — подключённый слой Metal. Это единственная платформа-зависимая часть подключения окна к рендерингу. +tutorial.surface.title: Описание нативной поверхности +tutorial.swapChain.context: "Цепочка обмена использует как контекст, так и нативное окно. Замените строку {windowDispose} в конце {programCs} следующим порядком освобождения ресурсов:" +tutorial.swapChain.description: "Используйте описание поверхности для создания изображений, которые будут выводиться на экран. Сразу после блока поверхности добавьте:" +tutorial.swapChain.details: Объект {swapChain} управляет изображениями, отображаемыми в окне. В каждом кадре {drawable} предоставляет текущее изображение как {texture} — тип API для данных изображений. После отрисовки метод {present} запрашивает отображение результата и переходит к следующему drawable. +tutorial.swapChain.guidance: "Формат {b8G8R8A8UNorm} хранит четыре 8-битных цветовых канала в порядке: синий, зелёный, красный и альфа. Значение {uNorm} означает, что целые числа от 0 до 255 представляют значения от 0 до 1. Шейдер по-прежнему будет возвращать логическое значение RGBA; этот формат определяет, как каналы сохраняются в изображении. Позже графический конвейер использует {swapChainDescFormat} для сопоставления с этим вложением." +tutorial.swapChain.title: Создание цепочки обмена +tutorial.title: Первый треугольник +tutorial.troubleshooting.description: "Сначала проверьте ошибки в консоли, а затем используйте контрольные точки, чтобы определить, на каком этапе произошёл сбой:" +tutorial.troubleshooting.details: Используйте {link} и {detail} для сравнения данных вершин, входной разметки и операций отрисовки. В том примере оконная система и отправка команд вынесены в общий хост, тогда как в этом учебнике логика приложения сохранена в {programCs}. Переходите к разделу {context}, чтобы изучить индексную отрисовку, трансформации и тест глубины. +tutorial.troubleshooting.details.context: Вращающийся куб +tutorial.troubleshooting.details.detail: шейдер Slang +tutorial.troubleshooting.details.link: демонстрационный рендерер +tutorial.troubleshooting.table.backend.check: Убедитесь, что выбранный бэкенд поддерживается устройством и установленным графическим драйвером. +tutorial.troubleshooting.table.backend.symptom: Сбой создания бэкенда +tutorial.troubleshooting.table.drawing.check: Проверьте размер загрузки данных, разметку входа, выбор конвейера и размещение команд отрисовки внутри прохода рендеринга. +tutorial.troubleshooting.table.drawing.symptom: Фон отображается, но треугольника нет +tutorial.troubleshooting.table.headings.check: Что проверить +tutorial.troubleshooting.table.headings.symptom: Симптом +tutorial.troubleshooting.table.input.check: "Проверьте шаг в 28 байт и смещения положения и цвета: 0 и 12." +tutorial.troubleshooting.table.input.symptom: Искажены координаты или цвета вершин +tutorial.troubleshooting.table.shaders.check: Проверьте скопированный файл {triangleSlang}, правильность написания точек входа и сообщения об ошибках от компилятора. +tutorial.troubleshooting.table.shaders.symptom: Очистка цветом работает, но загрузка шейдеров завершается ошибкой +tutorial.troubleshooting.table.window.check: Убедитесь, что проект .NET собирается и шаг с простым окном выполняется в сессии рабочего стола. В Linux проверьте доступность X11 или XWayland. +tutorial.troubleshooting.table.window.symptom: Окно не открывается +tutorial.troubleshooting.title: Поиск и устранение неполадок +tutorial.window.context: "Директива {usingZenithTutorials} импортирует пространство имён вспомогательного класса. Каждый файл C# использует свои обычные директивы using, поэтому импорт взаимодействия требуется в обоих файлах. Псевдоним {buffer} указывает на тип буфера Zenith.NET и отличает его от {systemBuffer}." +tutorial.window.description: Добавьте файл {cocoaHelperCs} в проект, сохранив его пространство имён. Добавьте директиву {interopUsing} в верхней части этого файла перед объявлением пространства имён. Вспомогательный класс подключает слой Metal к окну в macOS; ветки для других платформ его не вызывают. +tutorial.window.details: "Замените сгенерированный файл {programCs} следующим кодом. В нём используются операторы верхнего уровня, которые выполняются по порядку без явного метода {main}. В последующих разделах будет указано, куда добавлять код в этот файл:" +tutorial.window.guidance: "Значение {graphicsAPINone} указывает Silk.NET создать окно без собственного графического контекста. Мы создадим контекст через Zenith.NET. {initialize} создаёт нативное окно и делает его дескрипторы доступными. Дескриптор — идентификатор оконной системы. {center} центрирует окно, а {run} обрабатывает события до его закрытия. Затем выполнение переходит к {dispose}, освобождающему окно." +tutorial.window.notes: Запустите команду {dotnetRun}. Должно открыться пустое окно, реагирующее на перемещение, изменение размера и закрытие. Его содержимое пока не определено, поскольку мы ещё не отправляли команд рендеринга. Закройте его перед продолжением. +tutorial.window.title: Открытие окна +ui.action.copy: Копировать +ui.action.navigate: Перейти +ui.action.open: Открыть +ui.action.source: Исходный код +ui.api.browse: Обзор пространств имён и типов. +ui.api.clearTypeSearch: Очистить поиск типов +ui.api.findType: Найти тип +ui.api.loadError: Не удалось загрузить типы. Обновите страницу, чтобы повторить попытку. +ui.api.loadingNamespaces: Загрузка пространств имён… +ui.api.loadingTypes: Загрузка типов… +ui.api.matchingTypes: Найденные типы +ui.api.namespace: Пространство имён +ui.api.namespaces: Пространства имён +ui.api.noNamespaceTypes: В этом пространстве имён нет типов. +ui.api.noTypes: Совпадающих типов не найдено. +ui.api.types: Типы +ui.content.reference: Справочник +ui.content.source: Исходный код +ui.content.tutorial: Учебник +ui.contents.close: Закрыть оглавление +ui.contents.open: Открыть оглавление +ui.contents.title: Содержание +ui.footer.caption: Современный RHI для .NET. +ui.footer.label: Нижний колонтитул +ui.language.label: Язык +ui.language.unavailable: Не переведено +ui.members.clear: Очистить поиск членов +ui.members.close: Закрыть поиск членов +ui.members.empty: Совпадающих членов не найдено. +ui.members.open: Перейти к члену +ui.members.placeholder: Имя или сигнатура… +ui.members.search: Поиск членов +ui.members.title: Найти член +ui.members.undeclared: У этого типа нет объявленных членов. +ui.navigation.api: API +ui.navigation.concepts: Концепции +ui.navigation.home: Главная +ui.navigation.label: Основная навигация +ui.navigation.toggle: Переключить навигацию +ui.outline.title: На этой странице +ui.reference.assembly: Сборка +ui.reference.classes: Классы +ui.reference.constructors: Конструкторы +ui.reference.declaration: "Объявление типа C#" +ui.reference.delegates: Делегаты +ui.reference.derived: Производные типы +ui.reference.enums: Перечисления +ui.reference.events: События +ui.reference.examples: Примеры +ui.reference.exceptions: Исключения +ui.reference.extensionMethods: Методы расширения +ui.reference.fields: Поля +ui.reference.implementations: Явные реализации интерфейса +ui.reference.implements: Реализует +ui.reference.inheritance: Наследование +ui.reference.inheritedMembers: Унаследованные члены +ui.reference.interfaces: Интерфейсы +ui.reference.metadata: Метаданные типа +ui.reference.methods: Методы +ui.reference.namespace: Пространство имён +ui.reference.open: Открыть справку для {name} +ui.reference.operators: Операторы +ui.reference.parameters: Параметры +ui.reference.properties: Свойства +ui.reference.related: См. также +ui.reference.relationships: Наследование и метаданные +ui.reference.remarks: Примечания +ui.reference.returns: Возвращаемое значение +ui.reference.structs: Структуры +ui.reference.typeParameters: Параметры типа +ui.reference.value: Значение +ui.reference.values: Значения +ui.search.close: Закрыть поиск +ui.search.empty: По запросу «{query}» ничего не найдено. +ui.search.hint: Поиск по учебникам, концепциям, примерам и справочнику API. +ui.search.loading: Загрузка поиска… +ui.search.more: Показать больше результатов +ui.search.pending: Поиск… +ui.search.placeholder: Что вы ищете? +ui.search.resultCount: "Результатов: {count}" +ui.search.title: Поиск по документации +ui.search.unavailable: Поиск недоступен. Вы можете открыть страницы из списка ниже. diff --git a/documents/locales/zh-CN/strings.yml b/documents/locales/zh-CN/strings.yml new file mode 100644 index 00000000..703cfe08 --- /dev/null +++ b/documents/locales/zh-CN/strings.yml @@ -0,0 +1,604 @@ +### YamlMime:Resources +concepts.execution.context.description: "{graphicsContext} 代表一个后端设备,并提供其图形、计算和传输队列。同一工作负载所需的缓冲区、纹理、着色器和管线应通过同一个图形上下文创建。由另一个图形上下文创建的资源或句柄不能简单地绑定到该上下文的命令缓冲区中。" +concepts.execution.context.details: 根据平台和呈现表面选择后端。API 保持统一共享,但设备支持仍然至关重要。{capabilities} 公开了设备名称以及 {rayTracingSupported} 和 {meshShadingSupported} 标志。在创建可选工作负载之前,请像 {link} 和 {detail} 示例那样先检查对应的标志。这些标志并不构成格式、内存或平台限制的完整清单。 +concepts.execution.context.details.detail: 网格着色(mesh shading) +concepts.execution.context.details.link: 光线追踪 +concepts.execution.context.title: 图形上下文连接资源与队列 +concepts.execution.description: Zenith.NET 应用程序创建 GPU 资源,录制使用这些资源的命令,并将这些命令提交给队列。在 GPU 执行提交的工作时,CPU 可以继续运行。即便录制命令的调用已返回,也必须保持资源有效,直到该工作完成。 +concepts.execution.ownership.description: "在这里,所有权意味着释放资源的责任。C# 引用可以保持托管对象处于可达状态;但它无法阻止显式调用 {dispose} 销毁底层原生资源。同样,提交使用缓冲区的命令并不会将该缓冲区的所有权转移给队列。" +concepts.execution.ownership.details: "关闭时,停止提交新工作,等待涉及的每个队列完成对资源的最后一次使用,再释放应用程序创建的资源,最后释放图形上下文。释放上下文会释放它自身的队列和内部辅助对象;它不会等待所有应用程序工作,也不会释放应用程序创建的全部资源。" +concepts.execution.ownership.guidance: "渲染过程中也要遵循相同的生命周期规则。保留资源最后一次使用的完成值,以便判断何时可以覆盖其数据或替换资源。关于视图及其底层资源的生命周期,请参阅{link}。" +concepts.execution.ownership.guidance.link: 资源管理 +concepts.execution.ownership.table.applicationResources.object: 应用程序创建的资源 +concepts.execution.ownership.table.applicationResources.ownership: 应用程序在其最后一次 GPU 使用后释放它们。 +concepts.execution.ownership.table.commandBuffers.object: 借用的命令缓冲区 +concepts.execution.ownership.table.commandBuffers.ownership: 队列对其进行管理和回收。 +concepts.execution.ownership.table.headings.object: 对象 +concepts.execution.ownership.table.headings.ownership: 谁负责释放? +concepts.execution.ownership.table.queues.object: 图形上下文的队列及其时间线 +concepts.execution.ownership.table.queues.ownership: 图形上下文与队列对其进行管理。 +concepts.execution.ownership.table.swapChainDrawable.ownership: 交换链对其进行管理。 +concepts.execution.ownership.title: 将所有权与 GPU 完成区分开来 +concepts.execution.pipelines.description: 图形管线结合了着色器、顶点输入布局、将顶点组装为图元的规则、附件格式和渲染状态。在绑定顶点、索引或常量数据以及发出绘制命令之前设置它。其附件格式和采样数必须与渲染通道的附件匹配。 +concepts.execution.pipelines.details: 计算管线为分派提供着色器入口点,以启动 GPU 线程组。在分派之前设置它及其常量。计算分派属于图形渲染通道之外。更改管线意味着后续命令解释其输入的方式发生变化;在使用所选管线之前,请先绑定该管线所需的数据。 +concepts.execution.pipelines.guidance: "{link}展示了完整的图形执行序列。{detail}录制了一次分派,随后通过图形通道显示其结果。" +concepts.execution.pipelines.guidance.detail: 计算示例 +concepts.execution.pipelines.guidance.link: 三角形的渲染回调 +concepts.execution.pipelines.title: 管线决定了命令如何解释数据 +concepts.execution.queues.description: 当一个帧结合了绘制、计算和复制时,请从 {graphicsQueue} 开始。将存在依赖关系的工作保持在单个队列上可以让其执行顺序更容易理清。 +concepts.execution.queues.details: 队列接收成批的命令以供执行。独立的队列并不一定对应独立的硬件引擎,因此它们的工作可能无法同时并行运行。当工作负载可以从重叠执行中获益时使用其他队列,并在一个队列消费另一个队列的结果时添加显式依赖关系。 +concepts.execution.queues.guidance: 当后续命令依赖于先前的写入时,应用程序还必须确保这些写入对后续命令可见可用。将两个命令缓冲区提交到同一个队列并不会自动建立所有此类依赖。命令可以使用不同的 GPU 阶段,后续访问可能需要屏障或纹理布局转换。{link}解释了提交顺序与资源可见性之间的区别。 +concepts.execution.queues.guidance.link: 同步 +concepts.execution.queues.table.computeQueue.workToRecord: 计算分派以及兼容的传输工作,不含图形渲染通道。 +concepts.execution.queues.table.graphicsQueue.workToRecord: 渲染通道与绘制,以及帧所使用的计算和传输操作。 +concepts.execution.queues.table.headings.queue: 队列 +concepts.execution.queues.table.headings.workToRecord: 录制的工作 +concepts.execution.queues.table.transferQueue.workToRecord: 上传、回读与复制工作,不含绘制或计算分派。 +concepts.execution.queues.title: 根据所要执行的工作选择队列 +concepts.execution.recording.context: 队列会轮询完成状态并回收已完成的命令缓冲区。为每次新录制调用 {queueCommandBuffer};它可能会返回回收的实例。请勿释放借用的命令缓冲区、请勿重复提交两次,也不要在提交后继续向其中录制。一次仅从一个线程录制给定的命令缓冲区;队列的内部锁无法保护对命令缓冲区的并发修改。 +concepts.execution.recording.description: "{queueCommandBuffer} 返回一个已开始录制的 {commandBuffer}。录制命令及其依赖关系,然后调用一次 {submit}。提交操作结束录制,并返回一个标识该队列上完成点的 {timelineValue}。" +concepts.execution.recording.details: 例如,在将一帧录制到 {commandBuffer} 之后,三角形示例提交它并等待完成: +concepts.execution.recording.guidance: "{submit} 调度工作;{wait} 阻止 CPU 继续向下执行,直到该提交操作完成。录制绘制、结束渲染通道与提交命令缓冲区是互不相同的独立操作。录制绘制和结束渲染通道均不会等待 GPU。" +concepts.execution.recording.title: 录制命令并不等于执行命令 +concepts.execution.title: 执行模型 +concepts.platforms.description: 选择您的应用程序是自行拥有原生窗口和帧循环,还是使用 UI 渲染控件。该选择决定了谁来获取输出纹理、提交命令并呈现结果。输出纹理是用作当前帧输出的纹理。离屏图形和计算工作不需要窗口或交换链。 +concepts.platforms.frame.context: 在该通道内部添加您的管线绑定和绘制命令。在返回之前结束通道。不要独立提交所提供的命令缓冲区或自行呈现,也不要释放命令缓冲区或输出纹理。如果您的处理程序在其他布局中使用了输出纹理,请将其恢复为 {colorAttachment} 以供控件进行最终转换。 +concepts.platforms.frame.description: 这些集成实现了 {iZenithView}。应用程序提供其 {graphicsContext},在 {updateRequested} 中更新场景数据,并在 {renderRequested} 中使用 {renderEventArgs} 录制渲染命令。 +concepts.platforms.frame.details: "控件负责每帧的完整流程:获取输出纹理和命令缓冲区,将输出纹理转换为 {colorAttachment},调用处理程序,然后执行该框架所需的提交和呈现步骤。" +concepts.platforms.frame.guidance: 对于名为 {view} 且已分配上下文的已初始化 {iZenithView},此处理程序录制一个完整的清除通道。它需要 {usingZenithNET}: +concepts.platforms.frame.notes: 控件在每帧开始时均从 {undefined} 转换而来,因此应用程序不能依赖于输出纹理先前内容的保留。每帧都要清除或渲染所需的图像。将持久累积或缓存的渲染内容保存在应用程序自有的纹理中,然后通过视图显示该纹理。 +concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat} 提供集成的默认颜色格式。在匹配附件格式、采样数和尺寸时,请检查实际事件中的输出纹理。" +concepts.platforms.frame.title: 录制到 UI 控件提供的帧中 +concepts.platforms.integration.context: WinForms、WPF 和 Windows 的 WinUI 路径需要 Windows。MAUI 应用程序需要其目标平台的工作负载,并且必须使用 {useZenithView} 注册控件处理程序;参见 {extensionsCs}。框架支持和后端支持都必须满足。 +concepts.platforms.integration.description: 控件共享事件接口,但呈现方式并非全都相同: +concepts.platforms.integration.details: 位图回读在 UI 显示之前将渲染的像素复制到 CPU 内存中。共享纹理互操作避免了这种回读,但仍可能需要 GPU 复制和同步。因此,共享的 {renderRequested} 接口并不意味着相同的呈现开销或原生互操作要求。 +concepts.platforms.integration.guidance: 使用对应于应用程序框架的包;例如: +concepts.platforms.integration.table.avalonia.integration: Avalonia +concepts.platforms.integration.table.avalonia.presentation: "渲染到纹理,再将像素回读到 {writeableBitmap}。参见 {zenithViewCs} 和 {surfaceCs}。" +concepts.platforms.integration.table.headings.integration: 集成 +concepts.platforms.integration.table.headings.presentation: 图像如何到达 UI +concepts.platforms.integration.table.maui.integration: .NET MAUI +concepts.platforms.integration.table.maui.presentation: 在 Android、iOS 和 Mac Catalyst 上使用原生呈现目标,在 Windows 上使用共享纹理合成。参见{link}。 +concepts.platforms.integration.table.maui.presentation.link: 平台实现 +concepts.platforms.integration.table.uno.integration: Uno 路径 +concepts.platforms.integration.table.uno.presentation: "将像素回读到 {writeableBitmap}。参见 {zenithViewUnoCs}。" +concepts.platforms.integration.table.winForms.integration: WinForms +concepts.platforms.integration.table.winForms.presentation: 为控件的 {hWND} 创建 Zenith.NET 交换链。参见 {zenithViewCs}。 +concepts.platforms.integration.table.winUI.integration: Windows 上的 WinUI +concepts.platforms.integration.table.winUI.presentation: 渲染到导入的共享 Direct3D 11 纹理中,然后复制到连接至 {swapChainPanel} 的合成交换链。参见 {zenithViewWinUICs}。 +concepts.platforms.integration.table.wpf.integration: WPF +concepts.platforms.integration.table.wpf.presentation: 导入共享 Direct3D 11 纹理,然后通过 Direct3D 互操作复制到由 {d3DImage} 显示的表面。参见 {surfaceCs}。 +concepts.platforms.integration.title: 选择呈现路径以及框架 +concepts.platforms.lifecycle.context: 对于 UI 视图,在创建匹配的渲染资源时,使用事件输出纹理的 {descWidth}、{descHeight}、{descFormat} 和 {descSampleCount}。控件决定该输出纹理的分辨率;不要假定其逻辑尺寸或显示缩放比例始终等于纹理尺寸。 +concepts.platforms.lifecycle.description: 对于原生交换链,请以像素为单位传递帧缓冲区尺寸。启用显示缩放时,以逻辑单位表示的窗口大小可能会有所不同。跳过零尺寸的帧缓冲区,在像素大小变化时调整交换链大小,并为每帧获取 {swapChainDrawable}。输出纹理归交换链所有,并可能在呈现或调整大小后发生改变。 +concepts.platforms.lifecycle.details: "{swapChainResize} 更改现有呈现目标的尺寸。{swapChainRefresh} 替换呈现目标描述,包括原生句柄。在执行任一操作前,应先完成对受影响资源的所有未完成访问。销毁原生呈现目标前,应先释放交换链。" +concepts.platforms.lifecycle.guidance: 重新创建尺寸跟随窗口变化的应用程序自有深度或离屏纹理,并更新包含其句柄的常量。当附件格式和采样数保持兼容时,管线可以在尺寸变化后继续使用。{link}在替换深度纹理的同时保留了其管线。 +concepts.platforms.lifecycle.guidance.link: 旋转立方体渲染器 +concepts.platforms.lifecycle.title: 输出纹理的尺寸和生命周期由宿主决定 +concepts.platforms.ownership.description: 应用程序拥有其分配的图形上下文以及为渲染创建的资源。控件拥有其自身的呈现资源。更改视图的 {graphicsContext} 属性会使调度程序重新创建控件的资源;它不会为新上下文重新创建应用程序的管线、缓冲区或纹理。 +concepts.platforms.ownership.details: 将资源替换与视图的帧生命周期协调一致。在释放应用程序资源或分配的上下文之前,停止视图的帧活动并完成未决的 GPU 使用。移除视图不会将上下文所有权转移给控件。 +concepts.platforms.ownership.guidance: 共享的 {frameSchedulerCs} 通过视图的 UI 调度程序调度帧工作。使帧处理程序集中于更新和录制帧;在那里进行冗长的 CPU 任务也会使 UI 卡顿。 +concepts.platforms.ownership.title: 将应用程序资源保留在控件所有权之外 +concepts.platforms.surface.context: 窗口库或 UI 框架支持某种操作系统并不保证所选的 GPU 后端在其中可用。设备特性、驱动程序和原生呈现目标支持仍需匹配。在创建这些工作负载之前,通过 {contextCapabilities} 检查可选的光线追踪和网格着色(mesh shading)。 +concepts.platforms.surface.description: "{link}使用 Silk.NET 创建窗口并处理事件。Zenith.NET 通过 {surface} 描述和交换链 {swapChain} 连接到该窗口。原生呈现目标包含原生句柄和尺寸;构造该描述不会创建或拥有操作系统窗口。" +concepts.platforms.surface.description.link: 三角形教程 +concepts.platforms.surface.details: 句柄必须与所选后端匹配: +concepts.platforms.surface.guidance: 教程中的 {appCs} 显示了 Windows、macOS 和 X11 的选择。其 Linux 宿主提供 Xlib 句柄;在 Wayland 会话中使用它需要 XWayland。原生 Wayland 应用程序将通过 {surfaceWayland} 提供不同的句柄。 +concepts.platforms.surface.table.android.backend: Android 上的 Vulkan。 +concepts.platforms.surface.table.apple.backend: Apple 平台上的 Metal。 +concepts.platforms.surface.table.headings.backend: 后端路径 +concepts.platforms.surface.table.headings.factory: 呈现目标工厂 +concepts.platforms.surface.table.headings.handles: 宿主提供的句柄 +concepts.platforms.surface.table.wayland.backend: 带有原生 Wayland 宿主的 Vulkan。 +concepts.platforms.surface.table.wayland.handles: Wayland 显示与表面 +concepts.platforms.surface.table.win32.backend: Windows 上的 DirectX 12 或 Vulkan。 +concepts.platforms.surface.table.xlib.backend: Linux 上带有 X11 或 XWayland 的 Vulkan。 +concepts.platforms.surface.table.xlib.handles: X11 显示与窗口 +concepts.platforms.surface.title: 当应用程序拥有呈现所有权时提供原生呈现目标 +concepts.platforms.title: 平台集成 +concepts.resources.allocation.context: "除非需要自行实现内存分配器,否则先使用图形上下文创建的资源。使用堆时,应先等待所有使用这些资源的 GPU 工作完成,再释放堆中放置的资源,最后释放堆本身。" +concepts.resources.allocation.description: "{heap} 提供内存,供您在指定的字节偏移量处放置资源。应用程序负责选择这些偏移量,并跟踪哪些区域正在使用。" +concepts.resources.allocation.details: "放置资源前,使用准确的缓冲区或纹理描述调用 {contextGetSizeAndAlignment}。所选偏移量必须是返回的对齐值的整数倍,预留空间必须满足返回的大小,资源也必须位于堆的总字节范围内。仍在使用的分配区域不得重叠。纹理存储可能包含后端特有的填充和对齐,因此不能用像素数量乘以每像素字节数来计算分配大小。" +concepts.resources.allocation.guidance: "对于放置在堆中的缓冲区,其内存驻留设置应与堆一致。这里介绍的常规 GPU 纹理应使用仅 GPU 堆。大小和对齐是放置资源的要求,并不保证所有后端都能将任意资源放入任意堆。" +concepts.resources.allocation.title: 在需要分配控制时将资源放置在堆中 +concepts.resources.bufferUsages.table.constant.role: 通过常量缓冲区绑定读取的着色器参数。 +concepts.resources.bufferUsages.table.headings.role: "作用" +concepts.resources.bufferUsages.table.headings.usage: 用途 +concepts.resources.bufferUsages.table.index.role: 索引绘制所使用的索引。 +concepts.resources.bufferUsages.table.indirect.role: "间接绘制或分派命令读取的参数。" +concepts.resources.bufferUsages.table.none.role: "未声明任何缓冲区用途标志。" +concepts.resources.bufferUsages.table.storageReadOnly.role: "通过只读着色器绑定访问的缓冲区数据。" +concepts.resources.bufferUsages.table.storageReadWrite.role: "通过读写着色器绑定访问的缓冲区数据。" +concepts.resources.bufferUsages.table.transferDst.role: "GPU 复制操作的目标存储。" +concepts.resources.bufferUsages.table.transferSrc.role: "GPU 复制操作的源数据。" +concepts.resources.bufferUsages.table.vertex.role: 为绘制提取的顶点属性。 +concepts.resources.bufferUsages.title: 缓冲区用途 +concepts.resources.description: "根据将要使用资源的操作选择资源描述。如果一个纹理既要接收渲染结果,又要被着色器采样,还要回读到 CPU,就需要声明这三种用途,并处理这些操作之间的同步。内存放置位置和资源生命周期则是另外需要考虑的问题。" +concepts.resources.memory.context: 对于 CPU 可访问的缓冲区,{map} 为 CPU 提供内存地址。它不会等待 GPU 停止访问相同的字节。{unmap} 同样不会提交工作或等待完成。在覆盖 CPU 可写数据之前,请先完成仍需要其旧内容的 GPU 读取。 +concepts.resources.memory.description: "{bufferDesc} 具有 {residency} 字段。请根据 CPU 和 GPU 访问数据的方式进行选择:" +concepts.resources.memory.details: 内存驻留描述了 CPU 对所分配内存的预期访问方式。它并不意味着每个设备都具有物理分离的 CPU 和 GPU 内存。三角形示例使用 {cpuWriteOnly} 直接初始化较小的顶点缓冲区。大型静态网格则可以从单次上传的仅 GPU 存储中获益。 +concepts.resources.memory.guidance: "{textureDesc} 没有内存驻留字段。由图形上下文创建的常规纹理使用 GPU 存储。其公共 API 提供上传和回读操作来传输 CPU 数据,但不提供直接映射方法。显式堆提供内存放置控制,下文将介绍。" +concepts.resources.memory.table.cpuReadOnly.cPUAccess: "在 GPU 复制完成后读取映射的内存。" +concepts.resources.memory.table.cpuReadOnly.typicalRole: "GPU 生成的回读数据" +concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "在先前的 GPU 读取完成后写入映射的内存。" +concepts.resources.memory.table.cpuWriteOnly.typicalRole: "CPU 提供或更新的数据" +concepts.resources.memory.table.gpuOnly.cPUAccess: "通过上传缓冲区或回读缓冲区传输字节。" +concepts.resources.memory.table.gpuOnly.typicalRole: "静态几何体和 GPU 工作数据" +concepts.resources.memory.table.headings.cPUAccess: CPU 访问 +concepts.resources.memory.table.headings.residency: 内存驻留 +concepts.resources.memory.table.headings.typicalRole: "典型用途" +concepts.resources.memory.title: "根据所需的 CPU 访问方式选择内存" +concepts.resources.textureUsages.description: "传输用途标志描述 GPU 复制的方向。CPU 访问则是另一项内存放置选择,下文将介绍。" +concepts.resources.textureUsages.details: "组合用途标志只是声明多个作用,不会执行相应操作,也不会安排访问顺序。纹理仍然需要适当的{link},而且其格式必须在所选设备上支持请求的用途。" +concepts.resources.textureUsages.details.link: "布局与同步" +concepts.resources.textureUsages.table.colorAttachment.role: "渲染通道中的颜色附件。" +concepts.resources.textureUsages.table.depthStencilAttachment.role: "渲染通道中的深度/模板附件。" +concepts.resources.textureUsages.table.headings.role: "作用" +concepts.resources.textureUsages.table.headings.usage: 用途 +concepts.resources.textureUsages.table.none.role: "未声明任何纹理用途标志。" +concepts.resources.textureUsages.table.sampled.role: "通过采样纹理绑定读取的纹理数据。" +concepts.resources.textureUsages.table.storage.role: "通过存储纹理绑定供着色器读取或写入的纹理数据。" +concepts.resources.textureUsages.table.transferDst.role: "GPU 复制操作的目标图像存储。" +concepts.resources.textureUsages.table.transferSrc.role: "GPU 复制操作的源图像数据。" +concepts.resources.textureUsages.title: 纹理用途 +concepts.resources.title: 资源管理 +concepts.resources.transfers.context: "回读操作会录制一条将 GPU 数据复制到内部回读存储的命令。当库重置已完成的命令缓冲区以供复用时,才会将这些字节复制到提供的 CPU 目标中。在该提交完成值的 {wait} 返回之前,目标内存必须保持已分配状态,托管内存也必须保持固定。" +concepts.resources.transfers.description: "上传将 CPU 数据复制到 GPU 资源,回读将资源数据复制回 CPU 内存。资源自身提供的方法会在返回前完成该次传输:" +concepts.resources.transfers.details: "这些等待只涵盖方法自身提交的传输。它们不会发现另一个队列上已有读写操作对该资源的依赖关系。调用资源自身的传输方法前,应先建立这些依赖。直接通过映射内存复制数据时,也需要调用方确保相关 GPU 工作已经完成。" +concepts.resources.transfers.guidance: 当复制操作需要与其他工作一起录制时,请使用 {commandBufferUpload} 或 {commandBufferDownload}。它们的指针生命周期有所不同: +concepts.resources.transfers.item: "上传会在调用期间将 CPU 源数据复制到内部上传缓冲区,也称暂存内存。源指针只需在该次调用期间保持有效。" +concepts.resources.transfers.notes: "对于纹理,行步幅是 CPU 数据相邻两行之间的字节距离,切片步幅是相邻深度切片之间的字节距离。它们并不代表纹理内部的 GPU 内存布局。有关工作完成与数据回读的区别,请参阅{link}。" +concepts.resources.transfers.notes.link: 同步 +concepts.resources.transfers.table.bufferDownload.transfer: 对 {cpuReadOnly} 进行直接 CPU 复制;否则在传输队列上提交下载并等待。 +concepts.resources.transfers.table.bufferUpload.transfer: 对 {cpuWriteOnly} 进行直接 CPU 复制;否则在传输队列上提交上传并等待。 +concepts.resources.transfers.table.headings.method: 方法 +concepts.resources.transfers.table.headings.transfer: "数据传输方式" +concepts.resources.transfers.table.textureTransfers.method: "{textureUpload} / {textureDownload}" +concepts.resources.transfers.table.textureTransfers.transfer: "使用图形队列,将所选子资源转换为复制所需的布局,完成复制后转换为请求的最终布局,并等待传输完成。" +concepts.resources.transfers.title: "选择立即完成的传输或随命令录制的传输" +concepts.resources.usages.description: "{bufferUsages} 和 {textureUsages} 是声明资源预期角色的标志枚举。它们分别分配给 {bufferDescUsages} 和 {textureDescUsages}。当资源具有多个角色时,标志枚举允许使用 {value} 组合多个成员。" +concepts.resources.usages.title: 在创建资源之前声明所需的用途 +concepts.resources.views.description: "{bufferView} 描述缓冲区区域及其解释方式。{textureView} 选择兼容的纹理类型、格式和子资源范围。视图共享底层存储,不会复制数据,也不会添加创建资源时遗漏的用途。指定视图范围也不意味着各后端都会进行着色器边界检查。" +concepts.resources.views.details: "默认视图可以直接使用资源自身的句柄;如果需要不同区域或兼容的解释方式,则创建视图。在 GPU 工作可能使用视图及其底层资源期间,应保留二者的 C# 引用;仅有资源句柄并不能保持任一对象存活。只有在最后一次 GPU 使用完成后才能释放它们。替换其中任一对象后,还应更新包含其旧{link}的常量。" +concepts.resources.views.details.link: "资源句柄" +concepts.resources.views.guidance: "{link}展示了在调整大小时替换深度纹理。{detail}展示了输入纹理与其可写输出保持分离。两者都让资源的生命周期跟随实际使用它的工作。" +concepts.resources.views.guidance.detail: 计算示例 +concepts.resources.views.guidance.link: 旋转立方体渲染器 +concepts.resources.views.title: "让视图及其底层资源在使用期间保持有效" +concepts.shaders.binding.context: 在计算示例中,{input} 填充为 {inputTextureSampledHandle},{output} 填充为 {outputTextureStorageHandle}。Slang 的类型化 {descriptorHandle} 告知着色器如何访问每个资源: +concepts.shaders.binding.description: "{setConstantBuffer} 为当前管线的常量数据绑定缓冲区和字节偏移量。它绑定现有的 GPU 可见存储;它不会上传 C# 值。请先填充缓冲区,并确保先前的 GPU 读取操作已完成,然后再覆盖其字节。" +concepts.shaders.binding.details: 在设置常量缓冲区之前先设置管线。对于已创建并上传资源的计算工作负载,录制使用以下顺序: +concepts.shaders.binding.guidance: 此代码片段假定存在正在录制的 {commandBuffer}、{computePipeline}、具有 {bufferUsagesConstant} 用途的已上传 {constantBuffer},以及工作负载的线程组计数。偏移量 0 绑定缓冲区的起始位置。如果多个常量数据记录共享一个缓冲区,则每个记录的起始偏移量必须满足后端的绑定对齐要求。该要求与记录内部的字段布局相互独立。 +concepts.shaders.binding.notes: "{resourceHandle} 存储两个 32 位字段,但其解释归后端所有。不要将其视为可在上下文之间转移的通用描述符索引、地址或值。句柄不会创建资源,不会添加缺失的用途,也不会执行同步。" +concepts.shaders.binding.reference: 保留对资源及用于获取其句柄的任何视图的引用,并在着色器的最后一次使用完成后再释放它们。在替换纹理或视图时,更新包含其旧句柄的常量。{link}解释了这种生命周期关系。 +concepts.shaders.binding.reference.link: 资源管理 +concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: 读取着色器类型 {t} 的结构化元素。 +concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: 读取或写入着色器类型 {t} 的结构化元素。 +concepts.shaders.binding.table.headings.access: 预期访问 +concepts.shaders.binding.table.headings.cHandle: "C# 句柄" +concepts.shaders.binding.table.headings.slangFieldType: Slang 字段类型 +concepts.shaders.binding.table.samplerHandle.access: 提供纹理采样状态。 +concepts.shaders.binding.table.textureSampledHandle.access: 读取纹理。 +concepts.shaders.binding.table.textureStorageHandle.access: 读取或写入存储纹理。 +concepts.shaders.binding.title: 绑定常量缓冲区及其描述的资源 +concepts.shaders.compilation.description: "{zenithCompiler} 编译具名的 Slang 入口点并返回 {shaderDesc}。使用上下文的 {graphicsApi},以便编译结果针对将创建着色器的后端:针对 DirectX 12 的 DXIL、针对 Metal 的 Metal 库,或针对 Vulkan 的 SPIR-V。" +concepts.shaders.compilation.details: 例如,在已有 {context} 且三角形着色器已复制到可执行文件旁的情况下: +concepts.shaders.compilation.guidance: "{vSMain} 必须与着色器文件中的入口点名称完全匹配。在创建管线期间保持着色器对象有效,然后在管线创建完成后将其释放,如{link}所示。执行一次此初始化,而不是在每帧中重新编译。" +concepts.shaders.compilation.guidance.link: 第一个三角形 +concepts.shaders.compilation.title: 为所选上下文编译入口点 +concepts.shaders.description: "着色器接收由应用程序提供的数据。顶点属性描述单个顶点;缓冲区保存参数或数组;资源句柄标识着色器将访问的其他资源。C# 声明与 Slang 声明必须在这些值的含义上达成一致。仅仅匹配字段名是不够的:内存布局、资源访问和绑定方式都必须匹配。" +concepts.shaders.dispatch.description: "{dispatch} 接收线程组的数量。计算示例的 {numthreads} 入口点每组运行 16 × 16 个线程。将图像尺寸除以 16 并向上取整以求得组数。例如,17 × 19 的图像需要 2 × 2 组。着色器会根据图像尺寸检查其像素坐标,因为最后一组可能包含位于图像外部的线程。" +concepts.shaders.dispatch.details: 编译器将入口点声明的组大小保存在 {shaderDescThreadGroupSize} 中;它不会将提供给 {dispatch} 的像素尺寸自动转换为组数。完整的绑定和分派示例请结合使用 {computeShaderRendererCs} 及其着色器,并在另一个通道消费输出之前参阅{link}。 +concepts.shaders.dispatch.details.link: 同步 +concepts.shaders.dispatch.title: 分派线程组,而非像素 +concepts.shaders.layout.context: "{link}显式指定了它们的偏移量。此声明的作用域需要 {systemRuntimeInteropServices} 和 {zenithNET}:" +concepts.shaders.layout.context.link: "计算示例的 C# 常量" +concepts.shaders.layout.description: "对于顶点输入,管线的 {inputLayout} 描述了格式、偏移量、步幅和语义。三角形的 {float3} 位置后跟 {float4} 颜色占用 28 字节,颜色位于字节 12 处。{inputLayoutAdd} 计算这个紧凑布局;它不会检查 C# 结构体。如果 C# 字段包含填充,请提供匹配的布局,而不要假定字段是紧凑排列的。" +concepts.shaders.layout.details: "常量缓冲区保存着色器参数,而结构化缓冲区保存声明类型的元素数组。两者都根据其 Slang 声明进行读取。它们不使用 {inputLayout}。请核实编译后着色器表示形式的字段偏移量和元素大小(包括填充)。非托管 C# 类型适合按字节复制,但这本身并不能证明它与着色器类型匹配。特别是,不要将顶点的紧凑 {float3} 布局应用于每个着色器缓冲区。" +concepts.shaders.layout.guidance: 资源句柄是引用现有资源的一个较小数值。将句柄复制到常量缓冲区中并不会复制该资源的内容。 +concepts.shaders.layout.notes: "{computeShaderSlang} 中的相应声明为:" +concepts.shaders.layout.reference: "尺寸占用前 8 个字节,后跟两个 8 字节的资源句柄。C# 示例总共保留了 256 字节。该大小是示例选择的存储大小,并非所有 Slang 结构体或常量有效负载都占用 256 字节的规则。填充总大小也不会修正处于错误偏移量处的字段。" +concepts.shaders.layout.title: 顶点输入与着色器数据具有不同的布局规则 +concepts.shaders.matrices.description: 编译器请求行优先(row-major)矩阵存储,该存储将每行的元素保存在一起。{link}将三个 {matrix4x4} 值放置在偏移量 0、64 和 128 处。其{detail}按模型、视图和投影的顺序使用 {mulVectorMatrix}。 +concepts.shaders.matrices.description.detail: 着色器 +concepts.shaders.matrices.description.link: 旋转立方体渲染器 +concepts.shaders.matrices.details: 存储顺序决定了矩阵元素如何占用内存;乘法顺序决定了变换。请保持两端一致。在不检查这两个选择的情况下添加转置可能会掩盖一个不匹配,同时引入另一个不匹配。 +concepts.shaders.matrices.title: 保持矩阵存储与乘法顺序一致 +concepts.shaders.title: 着色器数据与绑定 +concepts.synchronization.backends.description: DirectX 12 和 Vulkan 对带有布局和访问信息的纹理转换进行编码。Metal 在 Zenith.NET 的 {transition} 实现中没有对应的显式操作。Metal 将录制的工作分组到渲染和计算编码器中。后端在结束这些组时插入可见性屏障,使先前的写入可供后续工作使用。显式的 {barrier} 调用处理诸如同一个编码器内连续计算分派等依赖关系。 +concepts.synchronization.backends.details: 在更改工作负载时,这种区别非常重要。在{link}中,分派之后是图形渲染通道,这在 Metal 上也会创建编码器边界。仅仅更改纹理声明的布局并不能为两个依赖的计算分派创建该边界。保持共享 API 所需的转换,并单独识别实际生产命令与消费命令之间的依赖关系。 +concepts.synchronization.backends.details.link: 计算示例 +concepts.synchronization.backends.title: 布局转换在每个后端上并非完全相同 +concepts.synchronization.barriers.context: "{barrierStagesAll} 是一个更宽的范围,而不是自动依赖项检测器。请选择实际覆盖该工作的阶段,并且仅在支持这些操作的队列上使用它们。" +concepts.synchronization.barriers.description: 考虑两个计算分派:第一个写入模拟数据,第二个读取该数据以执行下一步。两者都使用存储缓冲区,因此没有需要更改的纹理布局。在命令缓冲区中的两次分派之间插入以下内容: +concepts.synchronization.barriers.details: 第一个参数标识生产者阶段,第二个参数标识消费者阶段。屏障在 GPU 上建立对应的执行和内存依赖关系。后端将这些阶段转换为其执行和内存访问规则。该屏障不会更改纹理的布局,也不会等待设备上的所有工作。 +concepts.synchronization.barriers.guidance: "{link}在依赖的分派之间使用了这种模式。在发生依赖关系的地方放置屏障。在消费者已经录制之后放置屏障,无法将该消费者排在较早的生产者之后。" +concepts.synchronization.barriers.guidance.link: FluidTank 模拟 +concepts.synchronization.barriers.title: 使用屏障对有依赖关系的命令进行排序 +concepts.synchronization.dependencies.description: 对于每个共享资源,确定首先访问它的操作、随后的操作,以及是否有任一访问执行写入。两次读取相同的数据不需要进行排序以保护其内容,尽管布局更改或呈现可能会施加其他要求。写后读、读后覆写或两次写入可能都需要建立依赖关系。 +concepts.synchronization.dependencies.details: 然后根据这些操作执行的位置选择对应的机制: +concepts.synchronization.dependencies.guidance: 这些机制彼此相关,但不可互换。按顺序提交命令并不能取代所有的内存依赖。队列等待不会声明新的纹理布局,命令屏障也不会等待调用方的 CPU 线程。 +concepts.synchronization.dependencies.table.cpuAccess.mechanism: 对相关的完成值调用 {wait}。 +concepts.synchronization.dependencies.table.cpuAccess.situation: CPU 在访问或释放数据之前必须等待 +concepts.synchronization.dependencies.table.crossQueue.mechanism: 将其 {timelineValue} 传递给消费方命令缓冲区的 {submit}。 +concepts.synchronization.dependencies.table.crossQueue.situation: 另一个队列上的提交操作生成了数据 +concepts.synchronization.dependencies.table.headings.mechanism: 机制 +concepts.synchronization.dependencies.table.headings.situation: 情况 +concepts.synchronization.dependencies.table.layoutChange.mechanism: 带有先前和后续布局的 {commandBufferTransition}。 +concepts.synchronization.dependencies.table.layoutChange.situation: 纹理子资源更改其使用方式 +concepts.synchronization.dependencies.table.pipelineStages.mechanism: 带有生产者和消费者阶段的 {commandBufferBarrier}。 +concepts.synchronization.dependencies.table.pipelineStages.situation: 命令流中存在依赖关系的 GPU 阶段 +concepts.synchronization.dependencies.title: 从生产者和消费者开始分析 +concepts.synchronization.description: 读取先前命令写入数据的命令,依赖于这些写入操作已完成且对其可见。写入方是生产者(producer);读取方是消费者(consumer)。CPU 在读取、覆写或释放共享数据之前也需要一个完成点。Zenith.NET 针对这些不同的依赖关系提供了屏障、纹理布局转换和时间线。 +concepts.synchronization.layouts.context: "{undefined} 意味着不需要保留以前的内容。它适用于新图像或将被完全清除的附件。它不能用作避免跟踪需要加载、采样或累积内容的图像布局的手段。" +concepts.synchronization.layouts.description: 用途标志描述了纹理支持哪些角色。{textureLayout} 描述了某个特定操作将如何访问特定子资源。子资源是选定的 mip 级别和数组层。更改其布局是为此类访问做准备;它不会将纹理转换为不同的像素格式。例如,计算示例在 {storage} 布局中写入输出纹理,然后在图形通道中对其进行采样。在这些使用之间,它录制了: +concepts.synchronization.layouts.details: 此代码片段假定 {outputTexture} 是使用 {sampledStorage} 用途创建的,并且其选定的子资源处于 {storage} 布局中。{default} 选择 mip 级别 0 和数组层 0。该操作不会转换纹理的每个 mip 或层。 +concepts.synchronization.layouts.guidance: 应用程序提供先前的布局。{transition} 不会维护应用程序可见的布局跟踪器,也不会从较早的命令推断该值。只要资源在渲染阶段之间传递,就应该显式跟踪布局。 +concepts.synchronization.layouts.title: 跟踪每个纹理子资源的布局 +concepts.synchronization.readback.description: "{isCompleted} 仅查询 GPU 时间线是否已达到某个值。它本身不会回收命令缓冲区,也不会将暂存的回读数据复制到应用程序的目标指针所指向的内存中。" +concepts.synchronization.readback.details: "{commandBufferDownload} 首先录制将数据复制到内部回读存储的命令。重置已完成的命令缓冲区以供复用时,才会由 CPU 将数据复制到提供的指针所指向的内存。在该次回读提交的 {wait} 返回之前,目标内存必须保持有效,托管内存必须保持固定;返回后才能读取数据或释放内存。等待另一个队列上的后续提交,本身不会轮询回读操作所属的队列。" +concepts.synchronization.readback.guidance: "因此,仅轮询 {isCompleted} 然后立即读取异步回读的目标内存是不够的。{link}介绍了直接复制与通过暂存内存传输的路径。" +concepts.synchronization.readback.guidance.link: 资源管理 +concepts.synchronization.readback.title: GPU 完成与 CPU 下载数据是不同的步骤 +concepts.synchronization.reuse.description: 对于第一个渲染器,在每帧之后立即等待是最直观的做法。要实现重叠工作,请为未决帧分配单独的可变数据,并保留每个帧最终用途的完成值。在更新常量缓冲区、替换纹理或释放管线之前,请完成对受影响资源的所有未决访问。 +concepts.synchronization.reuse.details: 在调整大小或关闭时,在等待旧工作之前先停止新用途。{swapChainResize}、资源释放和上下文释放不能用作应用程序工作的通用等待机制。三角形示例可以在回调之间安全地调整大小,因为每个先前的帧都已经完成了其提交操作。 +concepts.synchronization.reuse.guidance: 当前的 {swapChainPresent} 在其呈现操作之后也会在图形队列上发出信号并等待。因此,仅仅移除三角形显式的提交等待并不能自动建立起重叠的呈现循环。在图形队列上的等待对于仍在另一个队列上运行的独立工作也不起作用。 +concepts.synchronization.reuse.title: 仅在最后一次访问完成后重用数据 +concepts.synchronization.timelines.context: 在 CPU 读取、覆写或释放这些资源之前,请等待其最终使用: +concepts.synchronization.timelines.description: 时间线使用递增的值跟踪队列上的完成进度。{submit} 返回包含该时间线和与提交关联的值的 {timelineValue}。来自不同时间线的完成值不能仅通过其数字 {value} 字段进行比较。 +concepts.synchronization.timelines.details: 假设 {producer} 和 {consumer} 是来自同一上下文的两个队列中已录制的命令缓冲区。生产者写入消费者使用的数据。像这样提交它们: +concepts.synchronization.timelines.guidance: 传递生成的值会使消费队列在 GPU 上等待该值。CPU 在此处不调用 {producedWait}。在 {consumed} 完成之前保持共享资源有效,并录制消费者所需的任何纹理布局更改。 +concepts.synchronization.timelines.notes: "{wait} 等待该时间线值,然后检查其所属队列中已完成的提交。完成的命令缓冲区会被重置以供复用,其中暂存的回读数据会复制到提供的 CPU 目标中。{queueTimelineSignal} 也可以在已提交到该队列的工作之后排入一个完成点。调用 {signal} 不代表 GPU 已经到达该点。" +concepts.synchronization.timelines.title: 使用时间线进行完成通知与队列交接 +concepts.synchronization.title: 同步 +home.actions.reference: 浏览 API +home.actions.tutorial: 从三角形开始 +home.entries.description: 第一帧画面。针对性的示例。深入了解 API。 +home.entries.label: 浏览文档 +home.entries.reference.action: 探索 API +home.entries.reference.category: 参考 +home.entries.reference.description: 查找支撑您应用程序的类型、签名与成员。 +home.entries.reference.title: API 参考 +home.entries.samples.action: 浏览示例 +home.entries.samples.category: 示例 +home.entries.samples.description: 通过源代码探索针对性的渲染与计算技术。 +home.entries.samples.title: 示例 +home.entries.title: 开始构建。 +home.entries.tutorial.action: 开始教程 +home.entries.tutorial.category: 教程 +home.entries.tutorial.description: 从项目搭建到第一帧画面,构建一个完整的渲染应用程序。 +home.entries.tutorial.title: 第一个三角形 +home.introduction.accent: "基于 C#。" +home.introduction.description: 通过单一的 .NET API 创建资源、录制命令并提交图形或计算工作。 +home.introduction.title: 构建您的渲染器。 +home.meta.description: "一套统一的 C# API,跨越 DirectX、Metal 与 Vulkan 提供图形与计算能力。" +home.scene.description: 旋转几何体研究。拖动或使用方向键调整视角。 +home.scene.label: 几何体显示 +home.scene.surface: 表面 +home.scene.wireframe: 线框 +home.title: 适用于 .NET 的现代 RHI +learning.concepts.description: 在组合渲染通道之前,了解命令、资源、着色器数据和同步是如何相互配合的。 +learning.concepts.execution.description: 录制 GPU 工作,提交该工作,并保持其资源处于有效状态。 +learning.concepts.platforms.description: 连接原生窗口或 UI 渲染控件。 +learning.concepts.resources.description: 选择资源用途、内存分配位置和视图。 +learning.concepts.shaders.description: "使 C# 内存布局与资源句柄同 Slang 保持一致。" +learning.concepts.synchronization.description: 对有依赖关系的访问进行排序,并掌握工作完成的时间点。 +learning.concepts.title: 核心概念 +learning.description: 从完整的三角形教程开始。然后利用针对性的示例和概念指南,理解更大型渲染器背后的资源、数据与依赖关系。 +learning.entries.samples.action: 浏览示例 +learning.entries.samples.description: "查找涵盖几何体、计算、光线查询与网格着色(mesh shading)的 C# 和 Slang 示例。" +learning.entries.tutorial.action: 打开教程 +learning.entries.tutorial.description: 创建控制台应用程序,打开窗口并绘制一个三角形。 +learning.meta.description: 开始使用 Zenith.NET 并探索其编程模型。 +learning.title: 学习 +reference.description: 查询资源类型、命令签名和平台集成。 +reference.entries.commands.description: 录制图形、计算和传输命令。 +reference.entries.commands.label: 录制工作 +reference.entries.context.description: 为所选后端创建 GPU 资源。 +reference.entries.context.label: 从这里开始 +reference.meta.description: 探索 Zenith.NET 中的类型与成员。 +reference.navigation.core: 浏览核心 API。 +reference.title: API 参考 +samples.computeShader.description: 通过计算分派将图像转换为灰度并显示结果纹理。演示了用于采样输入纹理和可写输出纹理的资源句柄、向上取整的线程组计数以及着色器内部的边界检查。请保留包含的 {assetsTexturesShokoPng} 资产;渲染器对其处理一次并在后续帧中呈现结果。 +samples.computeShader.details: "{computeShaderRendererCs} · {computeShaderSlang}" +samples.computeShader.title: 计算着色器 +samples.cube.description: 添加了索引绘制、常量缓冲区中的模型、视图和投影矩阵以及深度测试。深度纹理会在窗口大小改变时重新创建。在从裁剪空间几何体过渡到变换对象时使用此示例;渲染器使用 {d32FloatS8UInt} 深度/模板附件。 +samples.cube.details: "{spinningCubeRendererCs} · {spinningCubeSlang}" +samples.cube.title: 旋转立方体 +samples.description: "选择针对您要学习的功能的专项示例。每个示例都会链接到 C# 渲染器及其 Slang 着色器。如果您希望从空项目开始阅读完整应用程序的讲解,请从 {link} 开始。" +samples.description.link: 第一个三角形 +samples.execution.description: "{link} 在一个桌面应用程序中包含了六个独立的渲染器。请使用 .NET 10 SDK 和下述受支持的桌面后端。构建并运行该应用程序,然后从控制台菜单中选择一个示例:" +samples.execution.description.link: ZenithTutorials +samples.execution.details: 宿主程序在 Windows 上选择 DirectX 12,在 macOS 上选择 Metal,在 Linux 上选择 Vulkan。请使用所选后端支持的设备、驱动程序和着色器编译器环境。Linux 窗口路径需要 X11 或 XWayland。{link} 声明了包依赖项,并复制运行时所需的着色器和纹理资产。 +samples.execution.details.link: 项目文件 +samples.execution.guidance: 这些示例共享窗口和呈现代码。您可以根据要研究的功能独立选择任何示例。 +samples.execution.title: 运行教程示例 +samples.host.description: "{appCs} 创建图形上下文、窗口和交换链。它获取命令缓冲区,调用所选的渲染器,提交帧并进行呈现。{iRendererCs} 定义了渲染器的更新、渲染、调整大小和释放方法。" +samples.host.details: 计算与光线追踪会产生离屏纹理。{texturePresenterCs} 和 {presentTextureSlang} 将这些纹理绘制到窗口当前帧的输出纹理中。宿主程序仍然拥有提交操作和交换链呈现的所有权。 +samples.host.title: 共享宿主与呈现 +samples.indirectDrawing.description: 使用索引间接参数缓冲区和结构化缓冲区中的逐实例数据绘制立方体的多个副本。CPU 提供绘制参数并更新变换。在添加 GPU 生成的参数之前,可利用此示例了解间接参数布局以及着色器对实例数据的访问。 +samples.indirectDrawing.details: "{indirectDrawingRendererCs} · {indirectDrawingSlang}" +samples.indirectDrawing.title: 间接绘制 +samples.meshShading.description: 使用任务着色器(task shader)剔除球体实例,并将其索引传递给输出几何体的网格着色器(mesh shader)。渲染器在创建管线前会检查 {contextCapabilitiesMeshShadingSupported}。可利用此示例跟踪贯穿任务与网格阶段的资源句柄与有效负载数据。 +samples.meshShading.details: "{meshShadingRendererCs} · {meshShadingSlang}" +samples.meshShading.title: 网格着色(Mesh Shading) +samples.rayTracing.description: 为地面和程序化球体构建底层与顶层加速结构,然后在计算着色器中执行内联光线查询。渲染器在构建工作负载之前会检查 {contextCapabilitiesRayTracingSupported}。此示例适用于学习加速结构输入以及着色器端的光线遍历。 +samples.rayTracing.details: "{rayTracingRendererCs} · {rayTracingSlang}" +samples.rayTracing.title: 光线追踪 +samples.title: 示例 +samples.triangle.description: 创建顶点缓冲区及匹配的输入布局,然后通过图形管线绘制三个顶点。利用此示例将资源创建与渲染通道中的命令关联起来。 +samples.triangle.details: "{helloTriangleRendererCs} · {helloTriangleSlang} · {link}" +samples.triangle.details.link: 完整教程 +samples.triangle.title: Hello Triangle +samples.workloads.description: 主仓库的 {link} 包含组合了多项特性的应用程序。它们各自的项目直接引用库源码。在检出的 Zenith.NET 源码树中,运行所选项目即可,例如: +samples.workloads.description.link: Experiments 目录 +samples.workloads.details: 这些窗口实验项目在 Windows、macOS 和 Linux/X11 上使用相同的宿主选项。关于在 Avalonia、WinForms、WPF、WinUI/Uno 或 MAUI 中绘制,以及控件帧生命周期和实现链接,请参阅{link}。 +samples.workloads.details.link: 平台集成 +samples.workloads.table.cornellBox.example: "{link}" +samples.workloads.table.cornellBox.example.link: CornellBox +samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: "路径追踪、降噪、色调映射、分辨率放大以及 ImGui 控件。需要光线追踪支持以及对应桌面后端的着色器编译环境。" +samples.workloads.table.fluidTank.example: "{link}" +samples.workloads.table.fluidTank.example.link: FluidTank +samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: 计算流体模拟、模拟各阶段之间的依赖关系以及多通道表面渲染。需要对应桌面后端与着色器编译环境。 +samples.workloads.table.headings.example: 示例 +samples.workloads.table.headings.whatItDemonstratesAndRequires: 演示内容与运行要求 +samples.workloads.table.inkCanvas.example: "{link}" +samples.workloads.table.inkCanvas.example.link: InkCanvas +samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: 原生窗口中的 Skia 绘制与输入处理。需要对应目标平台的后端和 Skia 原生库。 +samples.workloads.table.platformDetection.example: "{link}" +samples.workloads.table.platformDetection.example.link: PlatformDetection +samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: 尝试为每个后端创建图形上下文并报告设备功能。若上下文创建失败,则报告为不支持;该结果也可能意味着缺少驱动程序或运行时依赖。 +samples.workloads.title: 探索更大型的工作负载 +tutorial.context.description: 窗口现在可以打开了,但我们尚未创建向其进行渲染的 GPU 对象。{graphicsContext} 提供对所选图形后端及其命令队列的访问。 +tutorial.context.details: 在{emphasis}插入此代码块: +tutorial.context.details.emphasis: using 指令之后、{iWindowWindow} 之前 +tutorial.context.guidance: 分支逻辑在 Windows 上选择 DirectX 12,在 macOS 上选择 Metal,在 Linux 上选择 Vulkan。接下来的渲染代码均使用共享的 Zenith.NET API。我们在开发期间请求启用验证层,并打印通过 {validationMessage} 报告的消息。诊断信息取决于后端以及机器上可用的验证组件。 +tutorial.context.title: 创建图形上下文 +tutorial.description: 构建一个 .NET 控制台应用程序,打开窗口并绘制一个具有平滑颜色渐变的三角形。您将学习顶点数据、着色器和管线状态是如何协同工作的,然后录制并提交生成该图像的命令。 +tutorial.details: 请按顺序完成各个部分。您将首先打开一个空窗口,然后显示背景颜色,最后绘制三角形。在添加下一部分之前,每个检查点都会确认应用程序当前部分的正常运行。初始化只执行一次;每次调用渲染回调时都会录制新的一帧。 +tutorial.draw.context: "{draw} 的参数如下:" +tutorial.draw.description: 在 {windowRender} 回调中,在 {beginRenderPass} 和 {endRenderPass} 之间,将 {addTheTriangleDrawCommandsHereLater} 替换为以下三个命令: +tutorial.draw.details: "{setPipeline} 选择我们刚才创建的着色器和状态。在绑定顶点数据之前设置它:后端使用管线的输入布局来解释该绑定。" +tutorial.draw.guidance: "{setVertexBufferVertexBuffer} 将从字节偏移量 0 开始的缓冲区绑定到输入槽 0。该槽对应于 {inputLayouts} 中的单个条目。它不会再次复制或上传数据。" +tutorial.draw.notes: 此时命令仍仅处于已录制状态。位于渲染回调末尾的 {submitWait} 和 {present} 调用会执行工作并显示其结果。清除操作仍然是必要的,因为三角形只覆盖图像的一部分;背景在每帧中也必须接收到已定义的颜色。 +tutorial.draw.table.firstInstance.meaning: 从零开始进行实例编号。 +tutorial.draw.table.firstVertex.meaning: 从缓冲区中的第一个顶点开始。 +tutorial.draw.table.headings.argument: 参数 +tutorial.draw.table.headings.description: 值 +tutorial.draw.table.headings.meaning: 含义 +tutorial.draw.table.instanceCount.meaning: 绘制三角形的一个副本。 +tutorial.draw.table.vertexCount.meaning: 读取三个顶点。 +tutorial.draw.title: 在通道内绘制三角形 +tutorial.execution.description: 从 {firstTriangle} 目录构建并运行: +tutorial.execution.details: 窗口中应显示一个三角形,在深色背景下具有红色的上顶点、绿色的右下角顶点和蓝色的左下角顶点。内部应显示这些颜色之间的平滑渐变。 +tutorial.execution.guidance: 调整窗口大小。调整大小的回调会更新帧缓冲区尺寸并重设交换链的大小。渲染通道建立与该图像匹配的视口。由于顶点位置保持为归一化坐标,三角形保持窗口宽度和高度的相同比例;改变纵横比可能会拉伸其形状。保持对象的纵横比需要投影或视口策略,这超出了本次基础绘制的范围。 +tutorial.execution.title: 运行、调整大小与关闭 +tutorial.frame.commands.context: 在 {endRenderPass} 之后,第二次转换准备将图像用于呈现。{submit} 结束录制并提交命令缓冲区;{wait} 等待 GPU 完成该提交。然后 {present} 请求显示渲染出的图像。 +tutorial.frame.commands.description: 渲染通道(render pass)将使用相同附件的绘制操作组合在一起。此处,颜色附件是交换链的输出纹理,即接收我们绘制内容的图像。{colorAttachmentClear} 创建一个描述,指示通道清除为给定的 RGBA 颜色,并在通道结束时保留结果。{beginRenderPass} 录制这些指令;GPU 在命令提交后执行清除。 +tutorial.frame.commands.details: 方括号中包含我们唯一的颜色附件。{null} 参数表示没有深度/模板附件,该附件通常用于存储深度值和模板掩码以进行深度与模板测试。 +tutorial.frame.commands.guidance: "{beginRenderPass} 设置覆盖附件的视口和裁剪区域。视口将渲染坐标映射到像素,裁剪区域限制可以写入的像素。这些默认设置覆盖整个输出纹理,这正是该三角形所需的。" +tutorial.frame.commands.title: 清除、提交与呈现 +tutorial.frame.description: 首先用一种背景颜色填充图像。此操作称为清除(clear)。如果该颜色出现在窗口中,则说明原生呈现目标、命令提交和呈现路径工作正常。在添加几何体和着色器之前,此检查点可让您验证帧循环。 +tutorial.frame.details: 渲染回调是 Silk.NET 在需要绘制帧时调用的代码。此回调不需要事件的流逝时间参数,因此将其命名为 {value}。在{emphasis}注册它: +tutorial.frame.details.emphasis: "{windowRun} 之前" +tutorial.frame.target.description: "{graphicsQueueCommandBuffer} 获取一个已开始录制的命令缓冲区。录制是为 GPU 描述工作;它不会立即执行该工作。" +tutorial.frame.target.details: 第一个 {transition} 为颜色附件访问准备输出纹理。{default} 选择 mip 级别 0 和数组层 0。我们使用 {undefined} 作为先前布局,因为我们将清除整个图像并丢弃其先前的内部数据。需要保留现有内容的通道必须改用其实际的先前布局。 +tutorial.frame.target.guidance: 每帧都使用交换链当前的输出纹理。呈现操作可能会改变当前可用的图像,因此从较早帧保存的纹理并不是永久性的窗口渲染目标。 +tutorial.frame.target.title: 准备输出纹理 +tutorial.frame.title: 显示背景颜色 +tutorial.geometry.data.description: 在{emphasis}添加此数组。接下来的资源创建步骤也按所示顺序位于该回调之前。 +tutorial.geometry.data.description.emphasis: "{windowRender} 之前" +tutorial.geometry.data.details: 数组的每个元素创建一个 {vertex}。内部的两个 {new} 表达式创建其 {vector3} 位置和 {vector4} 颜色。各顶点描述了顶部、右下角和左下角。顶点着色器将提供第四个位置坐标 {w}。当 w 等于 1 时,x 和 y 直接描述归一化设备坐标:-1 和 +1 是图像边缘,0 是中心。这些坐标不依赖于窗口的像素尺寸。 +tutorial.geometry.data.guidance: 每种颜色包含红、绿、蓝和阿尔法分量。三个顶点的阿尔法均为 1。所有三个位置的 z 坐标均为 0,将它们置于同一平面上。这些位置不需要相机或变换矩阵,因为它们已经直接描述了我们想要渲染的坐标。对于这个单一的平面三角形,我们还将禁用混合与深度测试,并省略深度缓冲区。 +tutorial.geometry.data.title: 选择顶点坐标 +tutorial.geometry.description: "顶点由一个位置以及绘制时使用的数据组成。我们的三角形有三个顶点,每个角一个。每个顶点都包含位置和颜色。GPU 会对颜色进行插值,计算三角形内部各处的中间值。" +tutorial.geometry.format.description: 在{emphasis}追加此声明: +tutorial.geometry.format.description.emphasis: "{programCs} 的末尾、清理语句之后" +tutorial.geometry.format.details: "{file} 将此类型限制在 {programCs} 内部,构造函数初始化其位置和颜色字段。{layoutKindSequential} 保持字段按照声明顺序排列。{position} 包含三个 32 位浮点数,{color} 包含四个。在该结构体中,位置从字节 0 开始,颜色从字节 12 开始,完整的顶点占用 28 个字节。我们将向图形管线描述这完全相同的布局。" +tutorial.geometry.format.title: 定义顶点 +tutorial.geometry.title: 向 GPU 提供三个顶点 +tutorial.geometry.upload.context: "{fixed} 防止垃圾回收器在使用数组地址时移动该数组。对于此 CPU 可写缓冲区,{upload} 在返回之前会映射、复制并取消映射内存,因此之后无需保持数组固定。缓冲区必须在整个渲染过程中保持有效,并且上传只需进行一次,因为顶点不会发生变化。" +tutorial.geometry.upload.description: 托管数组是 CPU 数据。{buffer} 为 GPU 提供存储空间,以便其可以从中读取顶点。在数组之后,添加: +tutorial.geometry.upload.details: 总大小为 {sizeofVertexVerticesLength}:每个顶点 28 字节,三个顶点,总共 84 字节。{bufferUsagesVertex} 允许顶点输入访问。{cpuWriteOnly} 允许 CPU 直接初始化这个小缓冲区。描述符的步幅(stride)记录了元素大小;我们稍后创建的输入布局将告知顶点获取机制如何读取各个属性。 +tutorial.geometry.upload.guidance: 创建缓冲区并不会填充数据。{upload} 将数组复制到该分配中,从目标字节偏移量 0 开始。其源描述提供了指针和要复制的字节数。 +tutorial.geometry.upload.notes: 在 {programCs} 底部的清理代码中,紧邻 {swapChainDispose} 之前添加 {vertexBufferDispose}。对于更大的静态几何体,{link}解释了何时应选择仅 GPU 内存并通过传输进行上传。 +tutorial.geometry.upload.notes.link: 资源管理 +tutorial.geometry.upload.title: 分配缓冲区并上传数组 +tutorial.input.description: 顶点字节和着色器均已就绪。接下来描述 GPU 应该如何读取每个顶点。属性是一个单独的值,例如位置或颜色。输入布局为每个属性赋予格式和字节偏移量;步幅(stride)给出从一个顶点到下一个顶点的字节距离。在创建着色器之后添加此初始化块: +tutorial.input.details: "{inputLayoutAdd} 在当前步幅处追加一个元素,并将该步幅增加该元素的大小。它不会检查 C# 结构体。在此处它生成了 CPU 内存与着色器输入之间的以下契约:" +tutorial.input.guidance: "更改 C# 字段顺序或填充而不更新此描述会导致 GPU 读取错误的字节。默认的 {semanticIndex} 为 0,匹配 {pOSITION0} 和 {cOLOR0}。这两个元素属于同一个缓冲区,因此管线将包含一个输入布局,并且我们将该缓冲区绑定到槽 0。" +tutorial.input.table.headings.byteOffset: 字节偏移量 +tutorial.input.table.headings.cField: "C# 字段" +tutorial.input.table.headings.format: 格式 +tutorial.input.table.headings.shaderInput: 着色器输入 +tutorial.input.table.nextVertex.cField: 下一个顶点 +tutorial.input.table.nextVertex.format: 总步幅:28 字节 +tutorial.input.table.nextVertex.shaderInput: 下一个输入记录 +tutorial.input.table.vertexColor.format: "{float4}(16 字节)" +tutorial.input.table.vertexPosition.format: "{float3}(12 字节)" +tutorial.input.title: 描述顶点输入布局 +tutorial.lifecycle.description: 完成的应用程序重复执行以下序列: +tutorial.lifecycle.details: 关闭窗口将从 {run} 返回。每个渲染的帧都已经等待其 GPU 工作完成,因此我们现在可以安全释放它所使用的资源。{windowRun} 之后的清理代码应为: +tutorial.lifecycle.guidance: "在销毁原生窗口前释放交换链,并在释放所有资源后释放图形上下文。队列拥有并回收提交的命令缓冲区,交换链拥有其输出纹理。因此,本应用程序不需要单独对这些命令缓冲区或输出纹理调用 {dispose}。" +tutorial.lifecycle.title: 跟踪一帧的生命周期 +tutorial.pipeline.behavior: 在输入布局之后,添加: +tutorial.pipeline.context: "{cullNone} 填充三角形,并且不因面的朝向而将其剔除。顶点顺序决定面的环绕方向;关闭剔除可以避免因这个顺序而使第一个三角形不可见。" +tutorial.pipeline.description: 我们现在拥有顶点数据、输入布局和两个着色器。{graphicsPipeline} 将它们连接起来,并指定 GPU 如何将顶点组装为图元并将结果写入附件。 +tutorial.pipeline.details: 管线将可编程着色器阶段与固定功能设置相结合,后者控制诸如三角形组装、面剔除和混合等 GPU 操作。对于这个三角形,选择以下设置: +tutorial.pipeline.guidance: 颜色格式取自 {swapChainDescFormat}。它必须与渲染通道使用的图像匹配。{count1} 表示每像素一个采样点。 +tutorial.pipeline.item: "{triangleList} 将每组连续的三个顶点组装成一个三角形。我们将提供三个顶点并绘制一次,因此不需要索引缓冲区。" +tutorial.pipeline.notes: "{depthNone} 禁用深度测试和写入,与没有深度附件的通道相匹配。" +tutorial.pipeline.reference: "{opaque} 禁用混合,因此片元着色器的颜色会替换三角形内部的背景。" +tutorial.pipeline.title: 连接着色器与顶点布局 +tutorial.pipeline.usage: 着色器对象在创建管线后即可释放,正如示例渲染器中所做的那样。对于使用它进行绘制的每一帧,保持管线本身处于有效状态。在清理代码中将 {pipelineDispose} 添加到 {vertexBufferDispose} 之前。管线创建是渲染回调之前的最后一步初始化。 +tutorial.pipeline.validation: 管线描述声明了附件配置;它不会创建另一个图像。{inputLayouts} 具有一个条目,因为位置和颜色一起存储在一个缓冲区中。 +tutorial.presentation.title: 将 GPU 连接到窗口 +tutorial.project.context: 在项目的构建设置中启用{emphasis}({allowUnsafeBlocks})。我们将使用它将顶点数据传递给 GPU,并用于窗口辅助类的原生调用。 +tutorial.project.context.emphasis: 允许不安全代码 +tutorial.project.description: 创建项目并进入其目录: +tutorial.project.details: 安装软件包: +tutorial.project.guidance: "{zenithNET} 提供共享的渲染 API。三个后端包允许同一个程序选择适合其平台的实现。{zenithNETCompiler} 负责为该实现编译 Slang 着色器(我们稍后将编写的小型 GPU 程序)。Silk.NET 提供窗口和事件循环。" +tutorial.project.title: 创建控制台项目 +tutorial.requirements.context: 您可以从一个空项目开始跟随本页操作。{link}及其{detail}可作为此处使用的渲染和窗口 API 的参考。 +tutorial.requirements.context.detail: 共享宿主 +tutorial.requirements.context.link: Hello Triangle 示例 +tutorial.requirements.description: "您需要 {emphasis}、代码编辑器或 IDE,以及配备了 Zenith.NET 后端支持的 GPU 和驱动程序的桌面设备。具备基本的 C# 知识即可;图形概念会在首次使用时予以介绍。这是一个普通的 {net10} 控制台项目。后端负责将 Zenith.NET 操作转换为对图形 API(例如 DirectX 12、Metal 或 Vulkan)的调用。应用程序在启动时选择其中之一:" +tutorial.requirements.description.emphasis: .NET 10 SDK +tutorial.requirements.details: 对于此处使用的窗口路径,Linux 需要与 X11 兼容的窗口会话。对于本三角形而言,不需要可选的光线追踪和网格着色(mesh shading)特性。 +tutorial.requirements.guidance: Zenith.NET 渲染到由应用程序提供的表面中。Silk.NET.Windowing 将创建桌面窗口并处理其事件。在 macOS 上,呈现目标是 Metal 图层({cAMetalLayerCs});教程中的窗口辅助类会为我们附加该图层。 +tutorial.requirements.table.headings.graphicsBackend: 图形后端 +tutorial.requirements.table.headings.platform: 平台 +tutorial.requirements.table.headings.windowSurface: 窗口表面 +tutorial.requirements.table.linux.graphicsBackend: Vulkan 1.4 +tutorial.requirements.table.linux.platform: Linux +tutorial.requirements.table.linux.windowSurface: X11 窗口与显示;XWayland 也同样适用 +tutorial.requirements.table.macOS.graphicsBackend: Metal 4 +tutorial.requirements.table.macOS.platform: macOS +tutorial.requirements.table.macOS.windowSurface: 附加到窗口的 Metal 图层 +tutorial.requirements.table.windows.graphicsBackend: DirectX 12 +tutorial.requirements.table.windows.platform: Windows +tutorial.requirements.table.windows.windowSurface: Win32 窗口句柄 +tutorial.requirements.title: 开始之前 +tutorial.resize.context: 再次运行 {dotnetRun}。窗口现在应该具有均匀的暗色背景,并且在调整大小后继续填满窗口。保留此回调:三角形将在其现有的渲染通道内绘制。 +tutorial.resize.description: 交换链的图像必须跟随帧缓冲区尺寸。使用 {framebufferResize} 响应像素大小的变化,包括由显示缩放引起的变化。在渲染回调之后、仍处于 {windowRun} 之前,添加: +tutorial.resize.details: Silk.NET 区分窗口大小变化与{link}。我们需要后者,因为交换链存储的是像素。最小化的窗口可以具有零大小的帧缓冲区。在那种情况下,两个回调都会跳过它们的 GPU 工作。调整大小后,渲染通道将为其视口和裁剪区域使用新的附件尺寸。 +tutorial.resize.details.link: 帧缓冲区大小变化 +tutorial.resize.guidance: 我们在每次提交后都会等待,因此当调整大小处理程序替换图像时,之前的帧不会继续使用这些图像。当前的 {present} 实现也会在图形队列上等待。这个简单的循环确保一帧的工作在下一帧开始前完成;{link}涵盖了更高级的调度方式。 +tutorial.resize.guidance.link: 同步 +tutorial.resize.title: 响应窗口大小调整 +tutorial.shaders.compilation.context: 编译在初始化期间执行一次。{appContextBaseDirectory} 负责在可执行文件旁定位复制的着色器,而与当前工作目录无关。这些着色器仅使用顶点输入,因此目前还没有常量缓冲区、纹理或资源句柄需要绑定。 +tutorial.shaders.compilation.description: 在 {triangleSlang} 的文件属性中,将{emphasis}设置为{detail}。这会使着色器在可执行文件旁可用。 +tutorial.shaders.compilation.description.detail: 如果较新则复制 +tutorial.shaders.compilation.description.emphasis: 复制到输出目录 +tutorial.shaders.compilation.details: 返回 {programCs}。在顶点上传之后、渲染回调之前添加这些初始化语句: +tutorial.shaders.compilation.guidance: "{zenithCompiler} 返回包含所请求图形 API 代码的着色器描述。{createShader} 创建对应的后端对象。图形 API 和入口点名称都很关键:使用 {contextGraphicsApi},并将 {vSMain} 和 {fSMain} 的拼写保持与 Slang 文件中完全一致。" +tutorial.shaders.compilation.title: 针对所选后端进行编译 +tutorial.shaders.context: "{fSInput} 将顶点着色器的输出连接到片元着色器的输入。由顶点着色器写入时,{sVPOSITION} 提供裁剪空间位置,即 GPU 用来判断哪些内容位于可见图像范围内的四个坐标。{cOLOR0} 传递需要在顶点之间插值的颜色。两个阶段使用的类型与语义必须一致。" +tutorial.shaders.description: 着色器是由 GPU 执行的程序。本次绘制需要一个顶点着色器来确定顶点位置,以及一个片元着色器来生成三角形内部的颜色。我们将使用 Slang 着色器语言编写它们,并从同一文件中编译两个入口点。入口点是着色器阶段开始执行的函数。 +tutorial.shaders.details: 创建 {triangleSlang},从以下两个结构体开始: +tutorial.shaders.fragment.description: 将片元入口点追加到同一个文件中: +tutorial.shaders.fragment.details: 光栅化确定三角形覆盖了哪些图像位置。它生成片元(由片元着色器处理的数据),并在覆盖区域内插值顶点颜色。{fSMain} 通过 {sVTARGET} 返回此插值颜色,该语义标识第一个颜色附件。 +tutorial.shaders.fragment.guidance: 顶点颜色插值与附件混合是相互独立的。混合是将片元的输出与附件中已存储的颜色相结合。我们设置的不透明混合状态禁用了该组合,因此插值得到的颜色将直接替换三角形内部的背景。 +tutorial.shaders.fragment.title: 为片元着色 +tutorial.shaders.guidance: "{vSInput} 描述顶点着色器从顶点缓冲区接收的内容。语义 {pOSITION0} 和 {cOLOR0} 标识输入;仅凭 C# 字段名称无法建立该映射。" +tutorial.shaders.title: 编写两个着色器阶段 +tutorial.shaders.vertex.description: 将顶点入口点追加到 {triangleSlang} 中: +tutorial.shaders.vertex.details: GPU 对每个输入顶点调用此入口点。它为位置添加齐次坐标 {w} 并传递颜色。在顶点阶段之后,位置会被除以 w;在此处该除法保持 x、y 和 z 不变。这就是为什么上面选择的位置可以直接理解为归一化设备坐标的原因。 +tutorial.shaders.vertex.title: 定位每个顶点 +tutorial.surface.description: 图形上下文还需要知道在何处显示其输出。在{emphasis}添加以下内容: +tutorial.surface.description.emphasis: "{windowCenter} 之后、{windowRun} 之前" +tutorial.surface.details: "{surface} 描述了原生呈现目标及其像素尺寸。帧缓冲区是与窗口关联的像素图像。{framebufferSize} 以像素为单位给出其尺寸;启用显示缩放时,窗口的逻辑尺寸可能会有所不同。" +tutorial.surface.guidance: 该表面与上面选定的后端相匹配。Windows 提供窗口句柄,Linux 提供 X11 显示与窗口,macOS 辅助类提供附加的 Metal 图层。这是将我们的窗口连接到渲染流程中唯一与平台相关的部分。 +tutorial.surface.title: 描述原生呈现目标 +tutorial.swapChain.context: 交换链同时使用了图形上下文与原生窗口。将 {programCs} 底部的 {windowDispose} 行替换为以下清理顺序: +tutorial.swapChain.description: 使用表面描述来创建将要呈现的图像。紧随表面代码块之后,添加: +tutorial.swapChain.details: "{swapChain} 管理窗口中显示的图像。在每一帧中,{drawable} 为我们提供作为 {texture}(用于图像数据的 API 类型)的当前图像。绘制完成后,{present} 请求显示结果并前进到下一个 drawable。" +tutorial.swapChain.guidance: "{b8G8R8A8UNorm} 按蓝、绿、红和阿尔法通道的顺序存储四个 8 位颜色通道。{uNorm} 表示从 0 到 255 的整数值对应从 0 到 1 的值。着色器仍将返回逻辑 RGBA 值;此格式决定这些通道在图像中的存储方式。稍后,图形管线将使用 {swapChainDescFormat} 来匹配此附件。" +tutorial.swapChain.title: 创建交换链 +tutorial.title: 第一个三角形 +tutorial.troubleshooting.description: 首先查看控制台中的任何错误,然后利用前面的检查点确定失败的阶段: +tutorial.troubleshooting.details: 使用{link}和{detail}来对比顶点数据、输入布局和绘制操作。该示例将窗口和提交逻辑放在共享宿主中;本教程将应用程序流程保留在 {programCs} 中。继续阅读{context}以学习索引绘制、变换和深度测试。 +tutorial.troubleshooting.details.context: 旋转立方体 +tutorial.troubleshooting.details.detail: Slang 着色器 +tutorial.troubleshooting.details.link: 示例渲染器 +tutorial.troubleshooting.table.backend.check: 检查所选后端是否受设备和已安装的图形驱动程序支持。 +tutorial.troubleshooting.table.backend.symptom: 后端创建失败 +tutorial.troubleshooting.table.drawing.check: 检查上传大小、输入布局、管线选择以及渲染通道内绘制命令的位置。 +tutorial.troubleshooting.table.drawing.symptom: 背景出现但三角形未出现 +tutorial.troubleshooting.table.headings.check: 检查项 +tutorial.troubleshooting.table.headings.symptom: 现象 +tutorial.troubleshooting.table.input.check: 检查 28 字节步幅以及 0 和 12 的位置/颜色偏移量。 +tutorial.troubleshooting.table.input.symptom: 顶点位置或颜色损坏 +tutorial.troubleshooting.table.shaders.check: 检查复制的 {triangleSlang}、入口点拼写以及编译器报告的诊断信息。 +tutorial.troubleshooting.table.shaders.symptom: 清除颜色步骤有效,但着色器加载失败 +tutorial.troubleshooting.table.window.check: 确认 .NET 项目能够构建成功,并且仅包含窗口的步骤可以在桌面会话中运行。在 Linux 上,检查 X11 或 XWayland 是否可用。 +tutorial.troubleshooting.table.window.symptom: 没有窗口打开 +tutorial.troubleshooting.title: 检查失败的阶段 +tutorial.window.context: "{usingZenithTutorials} 导入辅助类的命名空间。每个 C# 文件使用各自的常规 using 指令,因此互操作导入在两个文件中都是必需的。别名 {buffer} 指向 Zenith.NET 的缓冲区类型,以将其与 {systemBuffer} 区分开来。" +tutorial.window.description: 将 {cocoaHelperCs} 添加到项目中,保持其命名空间不变。在该文件顶部、其命名空间声明之前添加 {interopUsing}。该辅助类在 macOS 上为窗口附加 Metal 图层;其他平台分支不会调用它。 +tutorial.window.details: 将生成的 {programCs} 替换为以下代码。它使用顶级语句,按顺序执行而无需显式的 {main} 方法。后续部分将告诉您在该文件的何处添加代码: +tutorial.window.guidance: "{graphicsAPINone} 要求 Silk.NET 创建一个没有自身图形上下文的窗口。我们将使用 Zenith.NET 创建该上下文。{initialize} 创建原生窗口并使其句柄可用。句柄是由窗口系统提供的标识符。{center} 使窗口居中,{run} 处理事件直到窗口关闭。然后执行进入 {dispose},释放窗口。" +tutorial.window.notes: 运行 {dotnetRun}。应该会打开一个空窗口,并对移动、调整大小和关闭做出响应。由于我们尚未提交任何渲染命令,其内容尚未定义。在继续之前将其关闭。 +tutorial.window.title: 打开窗口 +ui.action.copy: 复制 +ui.action.navigate: 导航 +ui.action.open: 打开 +ui.action.source: 查看源码 +ui.api.browse: 浏览命名空间和类型。 +ui.api.clearTypeSearch: 清除类型搜索 +ui.api.findType: 查找类型 +ui.api.loadError: 无法加载类型。刷新此页面以重试。 +ui.api.loadingNamespaces: 正在加载命名空间… +ui.api.loadingTypes: 正在加载类型… +ui.api.matchingTypes: 匹配的类型 +ui.api.namespace: 命名空间 +ui.api.namespaces: 命名空间 +ui.api.noNamespaceTypes: 此命名空间中没有类型。 +ui.api.noTypes: 没有匹配的类型。 +ui.api.types: 类型 +ui.content.reference: 参考 +ui.content.source: 源代码 +ui.content.tutorial: 教程 +ui.contents.close: 关闭目录 +ui.contents.open: 打开目录 +ui.contents.title: 目录 +ui.footer.caption: 适用于 .NET 的现代 RHI。 +ui.footer.label: 页脚 +ui.language.label: 语言 +ui.language.unavailable: 未翻译 +ui.members.clear: 清除成员搜索 +ui.members.close: 关闭成员查找器 +ui.members.empty: 没有匹配的成员。 +ui.members.open: 转到成员 +ui.members.placeholder: 名称或签名… +ui.members.search: 搜索成员 +ui.members.title: 查找成员 +ui.members.undeclared: 此类型没有声明的成员。 +ui.navigation.api: API +ui.navigation.concepts: 概念 +ui.navigation.home: 首页 +ui.navigation.label: 主导航 +ui.navigation.toggle: 切换导航 +ui.outline.title: 本页导读 +ui.reference.assembly: 程序集 +ui.reference.classes: 类 +ui.reference.constructors: 构造函数 +ui.reference.declaration: "C# 类型声明" +ui.reference.delegates: 委托 +ui.reference.derived: 派生类型 +ui.reference.enums: 枚举 +ui.reference.events: 事件 +ui.reference.examples: 示例 +ui.reference.exceptions: 异常 +ui.reference.extensionMethods: 扩展方法 +ui.reference.fields: 字段 +ui.reference.implementations: 显式接口实现 +ui.reference.implements: 实现 +ui.reference.inheritance: 继承 +ui.reference.inheritedMembers: 继承的成员 +ui.reference.interfaces: 接口 +ui.reference.metadata: 类型元数据 +ui.reference.methods: 方法 +ui.reference.namespace: 命名空间 +ui.reference.open: 打开 {name} 的参考文档 +ui.reference.operators: 运算符 +ui.reference.parameters: 参数 +ui.reference.properties: 属性 +ui.reference.related: 另请参阅 +ui.reference.relationships: 继承与元数据 +ui.reference.remarks: 备注 +ui.reference.returns: 返回值 +ui.reference.structs: 结构体 +ui.reference.typeParameters: 类型参数 +ui.reference.value: 值 +ui.reference.values: 值 +ui.search.close: 关闭搜索 +ui.search.empty: 没有找到与“{query}”相关的结果。 +ui.search.hint: 搜索教程、概念、示例和 API 参考。 +ui.search.loading: 正在加载搜索… +ui.search.more: 显示更多结果 +ui.search.pending: 正在搜索… +ui.search.placeholder: 您在寻找什么? +ui.search.resultCount: 结果:{count} +ui.search.title: 搜索文档 +ui.search.unavailable: 搜索暂不可用。您仍然可以直接打开下方页面。 diff --git a/documents/locales/zh-TW/strings.yml b/documents/locales/zh-TW/strings.yml new file mode 100644 index 00000000..9c4258dc --- /dev/null +++ b/documents/locales/zh-TW/strings.yml @@ -0,0 +1,604 @@ +### YamlMime:Resources +concepts.execution.context.description: "{graphicsContext} 代表一個後端裝置,並提供其圖形、計算與傳輸佇列。相同工作負載所需的緩衝區、紋理、著色器與管線應透過同一個圖形上下文建立。由另一個圖形上下文建立的資源或控制代碼不能直接繫結至此圖形上下文的命令緩衝區。" +concepts.execution.context.details: 依據平台與呈現表面選取後端。API 保持共用,但裝置支援度仍至關重要。{capabilities} 公開裝置名稱以及 {rayTracingSupported} 與 {meshShadingSupported} 旗標。在建立選用的工作負載之前,請像 {link} 與 {detail} 範例一樣先檢查對應的旗標。這些旗標並非格式、記憶體或平台限制的完整清單。 +concepts.execution.context.details.detail: 網格著色(mesh shading) +concepts.execution.context.details.link: 光線追蹤 +concepts.execution.context.title: 圖形上下文連接資源與佇列 +concepts.execution.description: Zenith.NET 應用程式建立 GPU 資源、記錄使用這些資源的命令,並將這些命令提交至佇列。在 GPU 執行提交項目的同時,CPU 可以繼續執行。即使記錄呼叫已經返回,仍須保持資源有效,直到該工作完成。 +concepts.execution.ownership.description: "在此處,所有權代表釋放的責任。C# 參考可保持受控物件可達;但它無法防止明確的 {dispose} 終結原生資源。同樣地,提交使用緩衝區的命令不會將該緩衝區的所有權移轉給佇列。" +concepts.execution.ownership.details: "關閉時,停止提交新工作,等待涉及的每個佇列完成對資源的最後一次使用,再釋放應用程式建立的資源,最後釋放圖形上下文。釋放上下文會釋放它自身的佇列與內部輔助物件;它不會等待所有應用程式工作,也不會釋放應用程式建立的全部資源。" +concepts.execution.ownership.guidance: "渲染期間也要遵循相同的生命週期規則。保留資源最後一次使用的完成值,以判斷何時可以覆寫其資料或取代資源。有關檢視及其底層資源的生命週期,請參閱{link}。" +concepts.execution.ownership.guidance.link: 資源管理 +concepts.execution.ownership.table.applicationResources.object: 應用程式建立的資源 +concepts.execution.ownership.table.applicationResources.ownership: 應用程式在最後一次 GPU 使用後予以處置。 +concepts.execution.ownership.table.commandBuffers.object: 借用的命令緩衝區 +concepts.execution.ownership.table.commandBuffers.ownership: 佇列管理並回收它們。 +concepts.execution.ownership.table.headings.object: 物件 +concepts.execution.ownership.table.headings.ownership: 誰來釋放? +concepts.execution.ownership.table.queues.object: 圖形上下文佇列與其時間線 +concepts.execution.ownership.table.queues.ownership: 圖形上下文與佇列管理它們。 +concepts.execution.ownership.table.swapChainDrawable.ownership: 交換鏈管理它。 +concepts.execution.ownership.title: 將所有權與 GPU 完成分開處理 +concepts.execution.pipelines.description: 圖形管線結合了著色器、頂點輸入配置、將頂點組裝為基本圖元的規則、附件格式與渲染狀態。在繫結頂點、索引或常數資料以及發出繪圖命令之前設定它。其附件格式與取樣計數必須符合渲染通道的附件。 +concepts.execution.pipelines.details: 計算管線為分派提供著色器進入點,以啟動 GPU 執行緒群組。在分派之前設定它及其常數。計算分派屬於圖形渲染通道之外。變更管線即代表後續命令解譯其輸入方式的變更;在使用所選管線之前,請繫結該管線所需的資料。 +concepts.execution.pipelines.guidance: "{link}展示了完整的圖形執行序列。{detail}記錄了一次分派,隨後透過圖形通道顯示其結果。" +concepts.execution.pipelines.guidance.detail: 計算範例 +concepts.execution.pipelines.guidance.link: 三角形的渲染回呼 +concepts.execution.pipelines.title: 管線決定命令如何解譯資料 +concepts.execution.queues.description: 當單一影格結合了繪圖、計算與複製時,請從 {graphicsQueue} 開始。將相依的工作保持在單一佇列上可讓其順序更容易追蹤。 +concepts.execution.queues.details: 佇列接受批次命令以供執行。個別佇列不一定對應到個別的硬體引擎,因此它們的工作可能無法同時執行。當工作負載能從重疊執行中獲益時請使用其他佇列,並在某個佇列耗用另一個佇列的結果時新增明確的相依性。 +concepts.execution.queues.guidance: 當後續命令相依於先前的寫入時,應用程式還必須確保這些寫入對後續命令而言可用。將兩個命令緩衝區提交至相同佇列並不會自動建立所有這類相依性。命令可能會使用不同的 GPU 階段,且後續存取可能需要屏障或紋理轉換。{link}說明了提交順序與資源可見度之間的區別。 +concepts.execution.queues.guidance.link: 同步 +concepts.execution.queues.table.computeQueue.workToRecord: 計算分派與相容的傳輸工作,不包含圖形渲染通道。 +concepts.execution.queues.table.graphicsQueue.workToRecord: 渲染通道與繪圖,加上影格所使用的計算與傳輸操作。 +concepts.execution.queues.table.headings.queue: 佇列 +concepts.execution.queues.table.headings.workToRecord: 要記錄的工作 +concepts.execution.queues.table.transferQueue.workToRecord: 上傳、回讀與複製工作,不包含繪圖或計算分派。 +concepts.execution.queues.title: 依據欲執行的工作選擇佇列 +concepts.execution.recording.context: 佇列會輪詢完成狀態並回收完成的命令緩衝區。為每次新記錄呼叫 {queueCommandBuffer};它可能會傳回回收的執行個體。請勿處置借用的命令緩衝區、請勿重複提交兩次,也不要在提交後繼續向其中記錄。給定的命令緩衝區一次僅由一個執行緒進行記錄;佇列的內部鎖定無法防止對命令緩衝區的並行編輯。 +concepts.execution.recording.description: "{queueCommandBuffer} 會傳回已開始記錄的 {commandBuffer}。記錄命令及其相依性,接著呼叫 {submit} 一次。提交會結束記錄,並傳回識別該佇列上完成點的 {timelineValue}。" +concepts.execution.recording.details: 例如,在將影格記錄至 {commandBuffer} 後,三角形教學會提交它並等待完成: +concepts.execution.recording.guidance: "{submit} 排程工作;{wait} 防止 CPU 繼續執行,直到該提交完成為止。記錄繪製、結束渲染通道與提交命令緩衝區是個別分開的操作。記錄繪製與結束通道皆不會等待 GPU。" +concepts.execution.recording.title: 記錄不會執行命令 +concepts.execution.title: 執行模型 +concepts.platforms.description: 選擇您的應用程式是自行擁有原生視窗與影格迴圈,還是使用 UI 渲染控制項。該選擇決定了誰取得輸出紋理、提交命令並呈現結果。輸出紋理是用作目前影格輸出的紋理。螢幕外圖形與計算工作不需要視窗或交換鏈。 +concepts.platforms.frame.context: 在該通道內部新增您的管線繫結與繪圖命令。在返回之前結束通道。不要獨立提交提供的命令緩衝區或自行呈現,也不要處置命令緩衝區或輸出紋理。如果您的處理常式在另一種配置中使用輸出紋理,請將其恢復為 {colorAttachment} 以進行控制項的最終轉換。 +concepts.platforms.frame.description: 這些整合實作了 {iZenithView}。應用程式提供其 {graphicsContext},在 {updateRequested} 中更新場景資料,並使用 {renderEventArgs} 在 {renderRequested} 中記錄渲染。 +concepts.platforms.frame.details: "控制項負責每個影格的完整流程:取得輸出紋理與命令緩衝區,將輸出紋理轉換為 {colorAttachment},叫用處理常式,然後執行該框架所需的提交與呈現步驟。" +concepts.platforms.frame.guidance: "對於名為 {view}、已完成初始化且已指派圖形上下文的 {iZenithView},此處理常式會記錄一個完整的清除通道。它需要 {usingZenithNET}:" +concepts.platforms.frame.notes: "控制項在每個影格開始時皆從 {undefined} 轉換,因此應用程式不能依賴保留輸出紋理的先前內容。每個影格皆請清除或渲染所需的影像。將持續累加或快取的渲染內容保留在應用程式自身的紋理中,然後透過檢視顯示該紋理。" +concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat} 提供整合的預設色彩格式。在比對附件格式、取樣計數與尺寸時,請檢查實際事件中的輸出紋理。" +concepts.platforms.frame.title: 記錄至 UI 控制項提供的影格中 +concepts.platforms.integration.context: WinForms、WPF 與 Windows 的 WinUI 路徑需要 Windows。MAUI 應用程式需要其目標平台的工作負載,且必須使用 {useZenithView} 註冊控制項處理常式;請參閱 {extensionsCs}。架構支援與後端支援都必須滿足。 +concepts.platforms.integration.description: 控制項共用事件介面,但呈現方式並非全部相同: +concepts.platforms.integration.details: 點陣圖回讀(bitmap readback)在 UI 顯示之前將渲染的像素複製至 CPU 記憶體中。共用紋理互通避免了該回讀,但仍可能需要 GPU 複製與同步。因此,共用的 {renderRequested} 介面並不代表相同的呈現成本或原生互通需求。 +concepts.platforms.integration.guidance: 使用適合應用程式架構的套件;例如: +concepts.platforms.integration.table.avalonia.integration: Avalonia +concepts.platforms.integration.table.avalonia.presentation: "渲染至紋理,再將像素回讀至 {writeableBitmap}。請參閱 {zenithViewCs} 與 {surfaceCs}。" +concepts.platforms.integration.table.headings.integration: 整合 +concepts.platforms.integration.table.headings.presentation: 影像如何到達 UI +concepts.platforms.integration.table.maui.integration: .NET MAUI +concepts.platforms.integration.table.maui.presentation: 在 Android、iOS 與 Mac Catalyst 上使用原生呈現目標,在 Windows 上使用共用紋理合成。請參閱{link}。 +concepts.platforms.integration.table.maui.presentation.link: 平台實作 +concepts.platforms.integration.table.uno.integration: Uno 路徑 +concepts.platforms.integration.table.uno.presentation: "將像素回讀至 {writeableBitmap}。請參閱 {zenithViewUnoCs}。" +concepts.platforms.integration.table.winForms.integration: WinForms +concepts.platforms.integration.table.winForms.presentation: 為控制項的 {hWND} 建立 Zenith.NET 交換鏈。請參閱 {zenithViewCs}。 +concepts.platforms.integration.table.winUI.integration: Windows 上的 WinUI +concepts.platforms.integration.table.winUI.presentation: 渲染至匯入的共用 Direct3D 11 紋理,接著複製到附加至 {swapChainPanel} 的合成交換鏈。請參閱 {zenithViewWinUICs}。 +concepts.platforms.integration.table.wpf.integration: WPF +concepts.platforms.integration.table.wpf.presentation: 匯入共用 Direct3D 11 紋理,接著透過 Direct3D 互通複製到由 {d3DImage} 顯示的表面。請參閱 {surfaceCs}。 +concepts.platforms.integration.title: 選擇呈現路徑以及架構 +concepts.platforms.lifecycle.context: 對於 UI 檢視,在建立相符的渲染資源時,使用事件輸出紋理的 {descWidth}、{descHeight}、{descFormat} 與 {descSampleCount}。控制項決定該輸出紋理的解析度;不要假設其邏輯尺寸或顯示比例一律等於紋理尺寸。 +concepts.platforms.lifecycle.description: 對於原生交換鏈,請以像素為單位傳遞畫面緩衝區尺寸。啟用顯示比例縮放時,以邏輯單位表示的視窗大小可能會有所不同。略過零大小的畫面緩衝區,在像素大小變更時調整交換鏈大小,並為每個影格取得 {swapChainDrawable}。輸出紋理歸交換鏈所有,且可能會在呈現或調整大小後變更。 +concepts.platforms.lifecycle.details: "{swapChainResize} 會變更現有呈現目標的尺寸。{swapChainRefresh} 會取代呈現目標描述,包括原生控制代碼。在執行任一作業前,應先完成對受影響資源的所有未完成存取。銷毀原生呈現目標前,應先釋放交換鏈。" +concepts.platforms.lifecycle.guidance: "重新建立尺寸跟隨視窗變更的應用程式自身深度或螢幕外紋理,並更新包含其控制代碼的常數。當附件格式與取樣計數維持相容時,管線可以在尺寸變更後繼續使用。{link}在取代深度紋理的同時保留了其管線。" +concepts.platforms.lifecycle.guidance.link: 旋轉立方體渲染器 +concepts.platforms.lifecycle.title: "讓輸出紋理的尺寸與生命週期配合宿主" +concepts.platforms.ownership.description: "應用程式擁有其指派的圖形上下文以及為渲染所建立的資源。控制項擁有其自身的呈現資源。變更檢視的 {graphicsContext} 屬性會使排程器重新建立控制項的資源;它不會為新上下文重新建立應用程式的管線、緩衝區或紋理。" +concepts.platforms.ownership.details: 將資源取代與檢視的影格生命週期相互協調。在處置應用程式資源或指派的上下文之前,停止檢視的影格活動並完成未決的 GPU 使用。移除檢視不會將上下文所有權移轉給控制項。 +concepts.platforms.ownership.guidance: 共用的 {frameSchedulerCs} 透過檢視的 UI 發送器發送影格工作。保持影格處理常式聚焦於更新與記錄影格;該處過長的 CPU 工作也會延遲 UI。 +concepts.platforms.ownership.title: 將應用程式資源保持在控制項所有權之外 +concepts.platforms.surface.context: 視窗程式庫或 UI 架構支援作業系統並不保證所選的 GPU 後端在該處可用。裝置功能、驅動程式與原生表面支援仍必須相符。在建立這些工作負載之前,請透過 {contextCapabilities} 檢查選用的光線追蹤與網格著色(mesh shading)。 +concepts.platforms.surface.description: "{link}使用 Silk.NET 建立視窗並處理事件。Zenith.NET 透過 {surface} 描述與 {swapChain} 連接至該視窗。表面包含原生控制代碼與尺寸;建構該描述並不會建立或擁有作業系統視窗。" +concepts.platforms.surface.description.link: 三角形教學 +concepts.platforms.surface.details: 控制代碼必須與所選後端相符: +concepts.platforms.surface.guidance: "教學的 {appCs} 顯示了 Windows、macOS 與 X11 的選項。其 Linux 宿主程式提供 Xlib 控制代碼;在 Wayland 工作階段中使用它需要 XWayland。原生 Wayland 應用程式將透過 {surfaceWayland} 提供不同的控制代碼。" +concepts.platforms.surface.table.android.backend: Android 上的 Vulkan。 +concepts.platforms.surface.table.apple.backend: Apple 平台上的 Metal。 +concepts.platforms.surface.table.headings.backend: 後端路徑 +concepts.platforms.surface.table.headings.factory: "呈現目標工廠方法" +concepts.platforms.surface.table.headings.handles: "宿主程式提供的控制代碼" +concepts.platforms.surface.table.wayland.backend: "具有原生 Wayland 宿主程式的 Vulkan。" +concepts.platforms.surface.table.wayland.handles: Wayland 顯示與表面 +concepts.platforms.surface.table.win32.backend: Windows 上的 DirectX 12 或 Vulkan。 +concepts.platforms.surface.table.xlib.backend: Linux 上帶有 X11 或 XWayland 的 Vulkan。 +concepts.platforms.surface.table.xlib.handles: X11 顯示與視窗 +concepts.platforms.surface.title: 當應用程式擁有呈現時提供原生呈現目標 +concepts.platforms.title: 平台整合 +concepts.resources.allocation.context: "除非需要自行實作記憶體配置器,否則先使用圖形上下文建立的資源。使用堆積時,應先等待所有使用這些資源的 GPU 工作完成,再釋放堆積中放置的資源,最後釋放堆積本身。" +concepts.resources.allocation.description: "{heap} 提供記憶體,供您在指定的位元組位移處放置資源。應用程式負責選擇這些位移,並追蹤哪些區域正在使用。" +concepts.resources.allocation.details: "放置資源前,使用準確的緩衝區或紋理描述呼叫 {contextGetSizeAndAlignment}。所選位移必須是傳回對齊值的整數倍,預留空間必須滿足傳回的大小,資源也必須位於堆積的總位元組範圍內。仍在使用的配置區域不得重疊。紋理儲存空間可能包含後端特有的填補與對齊,因此不能以像素數量乘以每像素位元組數來計算配置大小。" +concepts.resources.allocation.guidance: "對於放置於堆積的緩衝區,其記憶體駐留設定應與堆積一致。這裡介紹的一般 GPU 紋理應使用僅供 GPU 使用的堆積。大小與對齊是放置資源的要求,並不保證所有後端都能將任意資源放入任意堆積。" +concepts.resources.allocation.title: 在需要配置控制時將資源放置於堆積中 +concepts.resources.bufferUsages.table.constant.role: 透過常數緩衝區繫結讀取的著色器參數。 +concepts.resources.bufferUsages.table.headings.role: "作用" +concepts.resources.bufferUsages.table.headings.usage: 用途 +concepts.resources.bufferUsages.table.index.role: 索引繪圖所使用的索引。 +concepts.resources.bufferUsages.table.indirect.role: "間接繪製或分派命令讀取的引數。" +concepts.resources.bufferUsages.table.none.role: "未宣告任何緩衝區用途旗標。" +concepts.resources.bufferUsages.table.storageReadOnly.role: "透過唯讀著色器繫結存取的緩衝區資料。" +concepts.resources.bufferUsages.table.storageReadWrite.role: "透過讀寫著色器繫結存取的緩衝區資料。" +concepts.resources.bufferUsages.table.transferDst.role: "GPU 複製作業的目的地儲存空間。" +concepts.resources.bufferUsages.table.transferSrc.role: "GPU 複製作業的來源資料。" +concepts.resources.bufferUsages.table.vertex.role: 為繪製擷取的頂點屬性。 +concepts.resources.bufferUsages.title: 緩衝區用途 +concepts.resources.description: "依據將要使用資源的作業選擇資源描述。如果一個紋理既要接收渲染結果,又要供著色器取樣,還要回讀至 CPU,就需要宣告這三種用途,並處理作業之間的同步。記憶體放置位置與資源生命週期則是另外需要考慮的問題。" +concepts.resources.memory.context: 對於 CPU 可存取的緩衝區,{map} 會提供位址給 CPU。它不會等待 GPU 停止存取相同的位元組。{unmap} 同樣不會提交工作或等待完成。在覆寫 CPU 可寫入資料之前,請先完成仍需要其舊內容的 GPU 讀取。 +concepts.resources.memory.description: "{bufferDesc} 具有 {residency} 欄位。請依據 CPU 與 GPU 將如何存取資料來選擇:" +concepts.resources.memory.details: 記憶體駐留描述對配置預期的 CPU 存取。它並不代表每部裝置皆具有實體獨立的 CPU 與 GPU 記憶體。三角形教學使用 {cpuWriteOnly} 直接初始化小型頂點緩衝區。大型靜態網格則可改為從單次上傳的僅 GPU 儲存空間中獲益。 +concepts.resources.memory.guidance: "{textureDesc} 沒有記憶體駐留欄位。由圖形上下文建立的一般紋理使用 GPU 儲存空間。其公用 API 提供上傳與回讀作業來傳輸 CPU 資料,但不提供直接對應記憶體的方法。明確指定的堆積提供記憶體放置控制,下文將介紹。" +concepts.resources.memory.table.cpuReadOnly.cPUAccess: "在 GPU 複製完成後讀取對應的記憶體。" +concepts.resources.memory.table.cpuReadOnly.typicalRole: "GPU 產生的回讀資料" +concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "在先前的 GPU 讀取完成後寫入對應的記憶體。" +concepts.resources.memory.table.cpuWriteOnly.typicalRole: "CPU 提供或更新的資料" +concepts.resources.memory.table.gpuOnly.cPUAccess: "透過上傳緩衝區或回讀緩衝區傳輸位元組。" +concepts.resources.memory.table.gpuOnly.typicalRole: "靜態幾何體與 GPU 工作資料" +concepts.resources.memory.table.headings.cPUAccess: CPU 存取 +concepts.resources.memory.table.headings.residency: 記憶體駐留 +concepts.resources.memory.table.headings.typicalRole: "典型用途" +concepts.resources.memory.title: "依所需的 CPU 存取方式選擇記憶體" +concepts.resources.textureUsages.description: "傳輸用途旗標描述 GPU 複製的方向。CPU 存取則是另一項記憶體放置選擇,下文將介紹。" +concepts.resources.textureUsages.details: "組合用途旗標只是宣告多個作用,不會執行對應作業,也不會安排存取順序。紋理仍然需要適當的{link},而且其格式必須在所選裝置上支援要求的用途。" +concepts.resources.textureUsages.details.link: "配置與同步" +concepts.resources.textureUsages.table.colorAttachment.role: "渲染通道中的色彩附件。" +concepts.resources.textureUsages.table.depthStencilAttachment.role: "渲染通道中的深度/樣板附件。" +concepts.resources.textureUsages.table.headings.role: "作用" +concepts.resources.textureUsages.table.headings.usage: 用途 +concepts.resources.textureUsages.table.none.role: "未宣告任何紋理用途旗標。" +concepts.resources.textureUsages.table.sampled.role: "透過取樣紋理繫結讀取的紋理資料。" +concepts.resources.textureUsages.table.storage.role: "透過儲存紋理繫結供著色器讀取或寫入的紋理資料。" +concepts.resources.textureUsages.table.transferDst.role: "GPU 複製作業的目的地影像儲存空間。" +concepts.resources.textureUsages.table.transferSrc.role: "GPU 複製作業的來源影像資料。" +concepts.resources.textureUsages.title: 紋理用途 +concepts.resources.title: 資源管理 +concepts.resources.transfers.context: "回讀作業會記錄一條將 GPU 資料複製至內部回讀儲存空間的命令。當程式庫重設已完成的命令緩衝區以供重複使用時,才會將這些位元組複製至提供的 CPU 目的地。在該提交完成值的 {wait} 返回之前,目的地記憶體必須保持已配置狀態,受控記憶體也必須保持釘選。" +concepts.resources.transfers.description: "上傳將 CPU 資料複製至 GPU 資源,回讀將資源資料複製回 CPU 記憶體。資源本身提供的方法會在返回前完成該次傳輸:" +concepts.resources.transfers.details: "這些等待只涵蓋方法本身提交的傳輸。它們不會發現另一個佇列上既有讀寫作業對該資源的相依性。呼叫資源本身的傳輸方法前,應先建立這些相依性。直接透過對應記憶體複製資料時,也需要呼叫端確保相關 GPU 工作已完成。" +concepts.resources.transfers.guidance: 當複製作業應與其他工作一起記錄時,請使用 {commandBufferUpload} 或 {commandBufferDownload}。其指標生命週期各有不同: +concepts.resources.transfers.item: "上傳會在呼叫期間將 CPU 來源資料複製至內部上傳緩衝區,也稱暫存記憶體。來源指標只需在該次呼叫期間保持有效。" +concepts.resources.transfers.notes: "對於紋理,列跨距是 CPU 資料相鄰兩列之間的位元組距離,切片跨距是相鄰深度切片之間的位元組距離。它們並不代表紋理內部的 GPU 記憶體配置。有關工作完成與資料回讀的區別,請參閱{link}。" +concepts.resources.transfers.notes.link: 同步 +concepts.resources.transfers.table.bufferDownload.transfer: 針對 {cpuReadOnly} 進行直接 CPU 複製;否則在傳輸佇列上提交下載並等待。 +concepts.resources.transfers.table.bufferUpload.transfer: 針對 {cpuWriteOnly} 進行直接 CPU 複製;否則在傳輸佇列上提交上傳並等待。 +concepts.resources.transfers.table.headings.method: 方法 +concepts.resources.transfers.table.headings.transfer: "資料傳輸方式" +concepts.resources.transfers.table.textureTransfers.method: "{textureUpload} / {textureDownload}" +concepts.resources.transfers.table.textureTransfers.transfer: "使用圖形佇列,將所選子資源轉換為複製所需的配置,完成複製後轉換為要求的最終配置,並等待傳輸完成。" +concepts.resources.transfers.title: "選擇立即完成的傳輸或隨命令記錄的傳輸" +concepts.resources.usages.description: "{bufferUsages} 與 {textureUsages} 是宣告資源預期角色的旗標列舉。它們分別指派給 {bufferDescUsages} 與 {textureDescUsages}。當資源具有多個角色時,旗標列舉允許使用 {value} 組合多個成員。" +concepts.resources.usages.title: 在建立資源之前宣告所需的用途 +concepts.resources.views.description: "{bufferView} 描述緩衝區區域及其解譯方式。{textureView} 選取相容的紋理型別、格式與子資源範圍。檢視共用底層儲存空間,不會複製資料,也不會新增建立資源時遺漏的用途。指定檢視範圍也不代表各後端都會進行著色器邊界檢查。" +concepts.resources.views.details: "預設檢視可以直接使用資源本身的控制代碼;若需要不同區域或相容的解譯方式,則建立檢視。在 GPU 工作可能使用檢視及其底層資源期間,應保留兩者的 C# 參考;僅有資源控制代碼並不能維持任一物件存活。只有在最後一次 GPU 使用完成後才能釋放它們。取代其中任一物件後,還應更新包含其舊{link}的常數。" +concepts.resources.views.details.link: "資源控制代碼" +concepts.resources.views.guidance: "{link}展示了在調整大小時取代深度紋理。{detail}展示了輸入紋理與其可寫入輸出分開保持。兩者都讓資源的生命週期遵循實際使用它的工作。" +concepts.resources.views.guidance.detail: 計算範例 +concepts.resources.views.guidance.link: 旋轉立方體渲染器 +concepts.resources.views.title: "讓檢視及其底層資源在使用期間保持有效" +concepts.shaders.binding.context: 在計算範例中,{input} 會填入 {inputTextureSampledHandle},而 {output} 會填入 {outputTextureStorageHandle}。Slang 的具型別 {descriptorHandle} 指示著色器如何存取各個資源: +concepts.shaders.binding.description: "{setConstantBuffer} 為目前管線的常數資料繫結緩衝區與位元組位移。它繫結現有的 GPU 可見儲存空間;它不會上傳 C# 數值。請先填入緩衝區,並在覆寫其位元組之前確保先前的 GPU 讀取者已完成。" +concepts.shaders.binding.details: 在設定常數緩衝區之前先設定管線。對於已建立並上傳資源的計算工作負載,記錄使用此順序: +concepts.shaders.binding.guidance: 此程式碼片段假設存在記錄中的 {commandBuffer}、{computePipeline}、具有 {bufferUsagesConstant} 用途的已上傳 {constantBuffer},以及工作負載的執行緒群組計數。位移 0 繫結緩衝區的起始處。如果多個常數資料記錄共用一個緩衝區,則每個記錄的起始位移必須符合後端的繫結對齊需求。該需求與記錄內部的欄位配置分開獨立。 +concepts.shaders.binding.notes: "{resourceHandle} 儲存兩個 32 位元欄位,但其解譯歸後端所有。請勿將其視為通用描述項索引、位址或可在上下文之間傳遞的數值。控制代碼不會建立資源、不會新增遺漏的用途,也不會執行同步。" +concepts.shaders.binding.reference: 保留對資源及用於取得其控制代碼之任何檢視的參考,並僅在著色器的最後一次使用完成後處置它們。取代紋理或檢視時,更新包含其舊控制代碼的常數。{link}解釋了該生命週期關係。 +concepts.shaders.binding.reference.link: 資源管理 +concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: 讀取著色器型別 {t} 的結構化元素。 +concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: 讀取或寫入著色器型別 {t} 的結構化元素。 +concepts.shaders.binding.table.headings.access: 預期存取 +concepts.shaders.binding.table.headings.cHandle: "C# 控制代碼" +concepts.shaders.binding.table.headings.slangFieldType: Slang 欄位型別 +concepts.shaders.binding.table.samplerHandle.access: 提供紋理取樣狀態。 +concepts.shaders.binding.table.textureSampledHandle.access: 讀取紋理。 +concepts.shaders.binding.table.textureStorageHandle.access: 讀取或寫入儲存紋理。 +concepts.shaders.binding.title: 繫結常數緩衝區及其描述的資源 +concepts.shaders.compilation.description: "{zenithCompiler} 會編譯具名的 Slang 進入點並傳回 {shaderDesc}。使用上下文的 {graphicsApi},讓結果以將建立著色器的後端為目標:DirectX 12 的 DXIL、Metal 的 Metal 程式庫,或 Vulkan 的 SPIR-V。" +concepts.shaders.compilation.details: 例如,在已有 {context} 且三角形著色器已複製到可執行檔旁的情況下: +concepts.shaders.compilation.guidance: "{vSMain} 必須與著色器檔案中的進入點名稱完全相符。在建立管線期間維持著色器物件有效,接著在管線建立完成後予以處置,如 {link} 所示。請執行一次此初始化,而非在每個影格中重新編譯。" +concepts.shaders.compilation.guidance.link: 第一個三角形 +concepts.shaders.compilation.title: 為選取的上下文編譯進入點 +concepts.shaders.description: "著色器接收應用程式提供的資料。頂點屬性描述個別頂點;緩衝區保存參數或陣列;資源控制代碼識別著色器將存取的其他資源。C# 宣告與 Slang 宣告必須在這些數值的意義上達成共識。僅比對欄位名稱是不夠的:配置、資源存取與繫結皆必須相符。" +concepts.shaders.dispatch.description: "{dispatch} 接收執行緒群組的數目。計算範例的 {numthreads} 進入點每組執行 16 × 16 個執行緒。將影像尺寸除以 16 並無條件進位即可找出群組計數。例如,17 × 19 的影像需要 2 × 2 組。著色器會比對其像素座標與影像尺寸,因為最後的群組可能包含位於影像外部的執行緒。" +concepts.shaders.dispatch.details: 編譯器將進入點宣告的群組大小儲存在 {shaderDescThreadGroupSize} 中;它不會將提供給 {dispatch} 的像素尺寸轉換為群組計數。完整的繫結與分派範例請結合使用 {computeShaderRendererCs} 及其著色器,並在另一個通道取用輸出前參閱 {link}。 +concepts.shaders.dispatch.details.link: 同步 +concepts.shaders.dispatch.title: 分派執行緒群組,而非像素 +concepts.shaders.layout.context: "{link}明確指出了它們的位移。此宣告的作用範圍需要 {systemRuntimeInteropServices} 與 {zenithNET}:" +concepts.shaders.layout.context.link: "計算範例的 C# 常數" +concepts.shaders.layout.description: "對於頂點輸入,管線的 {inputLayout} 描述了格式、位移、跨距與語意。三角形的 {float3} 位置加上隨後的 {float4} 色彩共佔用 28 位元組,色彩位於位元組 12 處。{inputLayoutAdd} 會計算此緊密配置;它不會檢查 C# 結構。如果 C# 欄位包含填補,請提供相符的配置,而不要假設欄位是緊密排列的。" +concepts.shaders.layout.details: "常數緩衝區保存著色器參數,而結構化緩衝區保存宣告型別的元素陣列。兩者皆依據其 Slang 宣告進行讀取。它們不使用 {inputLayout}。請檢查編譯後著色器表示法的欄位位移與元素大小(包含填補)。非受控 C# 型別適合以位元組形式複製,但這本身無法證明它與著色器型別相符。特別是,請勿將頂點緊密排列的 {float3} 配置套用至每個著色器緩衝區。" +concepts.shaders.layout.guidance: 資源控制代碼是參照現有資源的小型數值。將控制代碼複製至常數緩衝區並不會複製資源的內容。 +concepts.shaders.layout.notes: "{computeShaderSlang} 中的對應宣告為:" +concepts.shaders.layout.reference: "尺寸佔用前八個位元組,後隨兩個八位元組的資源控制代碼。C# 範例總共保留了 256 位元組。該大小是範例選擇的儲存大小,而非所有 Slang 結構或常數裝載皆佔用 256 位元組的規則。填補總大小也無法修正位於錯誤位移處的欄位。" +concepts.shaders.layout.title: 頂點輸入與著色器資料具有不同的配置規則 +concepts.shaders.matrices.description: 編譯器要求列優先(row-major)矩陣儲存,這會將每列的元素一起儲存。{link}將三個 {matrix4x4} 數值放置於位移 0、64 與 128 處。其{detail}依模型、檢視與投影順序使用 {mulVectorMatrix}。 +concepts.shaders.matrices.description.detail: 著色器 +concepts.shaders.matrices.description.link: 旋轉立方體渲染器 +concepts.shaders.matrices.details: 儲存順序決定矩陣元素如何佔用記憶體;乘法順序決定變換。請保持兩端一致。在未檢查這兩個選擇的情況下加入轉置可能會掩蓋一個不相符,同時引入另一個不相符。 +concepts.shaders.matrices.title: 保持矩陣儲存與乘法順序一致 +concepts.shaders.title: 著色器資料與繫結 +concepts.synchronization.backends.description: DirectX 12 與 Vulkan 使用配置與存取資訊對紋理轉換進行編碼。Metal 在 Zenith.NET 的 {transition} 實作中沒有對應的操作。Metal 將記錄的工作分組為渲染與計算編碼器。後端在結束這些群組時插入可見度屏障,使先前的寫入可用於後續工作。明確的 {barrier} 呼叫處理相依性,例如同一個編碼器內連續的計算分派。 +concepts.synchronization.backends.details: 變更工作負載時此差異至關重要。在{link}中,分派之後接續圖形渲染通道,這在 Metal 上也會建立編碼器邊界。兩個相依的計算分派不會僅透過變更紋理宣告的配置就建立該邊界。保留共用 API 所需的轉換,並單獨識別實際生產與取用命令之間的相依性。 +concepts.synchronization.backends.details.link: 計算範例 +concepts.synchronization.backends.title: 轉換在每個後端並非完全相同 +concepts.synchronization.barriers.context: "{barrierStagesAll} 是較廣泛的範圍,而非自動相依性偵測器。選取實際涵蓋工作的階段,並僅在支援這些操作的佇列上使用它們。" +concepts.synchronization.barriers.description: 考慮兩個計算分派:第一個寫入模擬資料,第二個讀取該資料以執行下一步。兩者皆使用儲存緩衝區,因此沒有要變更的紋理配置。在命令緩衝區中的分派之間插入此內容: +concepts.synchronization.barriers.details: 第一個引數識別生產階段,第二個引數識別取用階段。屏障在 GPU 上建立對應的執行與記憶體相依性。後端將這些階段轉譯為其執行與記憶體存取規則。此屏障不會變更紋理的配置,也不會等待裝置上的所有工作。 +concepts.synchronization.barriers.guidance: "{link}在相依分派之間使用了此模式。在發生相依性的位置放置屏障。在取用者已經記錄之後放置屏障無法將該取用者排在較早的生產者之後。" +concepts.synchronization.barriers.guidance.link: FluidTank 模擬 +concepts.synchronization.barriers.title: 以屏障為相依命令排序 +concepts.synchronization.dependencies.description: 針對每個共用資源,識別首先存取它的操作、接續的操作,以及是否有任何存取進行寫入。兩次讀取相同資料不需要排序來保護其內容,儘管配置變更或呈現可能會施加其他需求。寫入後接續讀取、讀取後接續覆寫或兩次寫入皆可能需要建立相依性。 +concepts.synchronization.dependencies.details: 接著依據這些操作執行的位置選擇機制: +concepts.synchronization.dependencies.guidance: 這些機制互相關聯,但不可互換。依序提交命令並不能取代每個記憶體相依性。佇列等待不會宣告新的紋理配置,命令屏障也不會在呼叫端的 CPU 執行緒上等待。 +concepts.synchronization.dependencies.table.cpuAccess.mechanism: 針對相關完成值呼叫 {wait}。 +concepts.synchronization.dependencies.table.cpuAccess.situation: CPU 在存取或釋放資料之前必須等待 +concepts.synchronization.dependencies.table.crossQueue.mechanism: 將其 {timelineValue} 傳遞給取用端命令緩衝區的 {submit}。 +concepts.synchronization.dependencies.table.crossQueue.situation: 另一個佇列上的提交產生了資料 +concepts.synchronization.dependencies.table.headings.mechanism: 機制 +concepts.synchronization.dependencies.table.headings.situation: 情況 +concepts.synchronization.dependencies.table.layoutChange.mechanism: 帶有前一個與下一個配置的 {commandBufferTransition}。 +concepts.synchronization.dependencies.table.layoutChange.situation: 紋理子資源變更其使用方式 +concepts.synchronization.dependencies.table.pipelineStages.mechanism: 帶有生產者與取用者階段的 {commandBufferBarrier}。 +concepts.synchronization.dependencies.table.pipelineStages.situation: 命令串流中相依的 GPU 階段 +concepts.synchronization.dependencies.title: 從生產者與取用者開始著手 +concepts.synchronization.description: 讀取先前命令寫入資料的命令,相依於這些寫入已完成且對其可見。寫入者為生產者(producer);讀取者為取用者(consumer)。CPU 在讀取、覆寫或釋放共用資料之前也需要完成點。Zenith.NET 針對這些不同的相依性提供了屏障、紋理轉換與時間線。 +concepts.synchronization.layouts.context: "{undefined} 代表不需要保留先前的內容。它適用於新影像或將被完全清除的附件。它不是用來避免追蹤需要載入、取樣或累加內容之影像配置的手段。" +concepts.synchronization.layouts.description: 用途旗標描述紋理支援的角色。{textureLayout} 描述特定操作將如何存取特定子資源。子資源是選取的 Mip 層級與陣列層。變更其配置是為該存取做好準備;它不會將紋理轉換為不同的像素格式。例如,計算範例在 {storage} 配置中寫入輸出紋理,接著在圖形通道中對其進行取樣。在這些使用之間,它記錄了: +concepts.synchronization.layouts.details: 此程式碼片段假設 {outputTexture} 是以 {sampledStorage} 用途建立的,且其選取的子資源處於 {storage} 配置。{default} 選取 Mip 層級 0 與陣列層 0。該操作不會轉換紋理的每個 Mip 或層。 +concepts.synchronization.layouts.guidance: 應用程式提供先前的配置。{transition} 不會維護應用程式可見的配置追蹤器,也不會從先前的命令推斷該值。只要資源在渲染階段之間傳遞,即應追蹤其配置。 +concepts.synchronization.layouts.title: 追蹤每個紋理子資源的配置 +concepts.synchronization.readback.description: "{isCompleted} 僅查詢 GPU 時間線是否已達到某個值。它本身不會回收命令緩衝區,也不會將暫存的回讀資料複製至應用程式的目的地指標所指向的記憶體。" +concepts.synchronization.readback.details: "{commandBufferDownload} 首先記錄將資料複製至內部回讀儲存空間的命令。重設已完成的命令緩衝區以供重複使用時,才會由 CPU 將資料複製至提供的指標所指向的記憶體。在該次回讀提交的 {wait} 返回之前,目的地記憶體必須保持有效,受控記憶體必須保持釘選;返回後才能讀取資料或釋放記憶體。等待另一個佇列上的後續提交,本身不會輪詢回讀作業所屬的佇列。" +concepts.synchronization.readback.guidance: "因此,僅輪詢 {isCompleted} 後立即讀取非同步回讀的目的地記憶體並不足夠。{link}介紹了直接複製與透過暫存記憶體傳輸的路徑。" +concepts.synchronization.readback.guidance.link: 資源管理 +concepts.synchronization.readback.title: GPU 完成與下載的 CPU 資料是不同的步驟 +concepts.synchronization.reuse.description: 對於第一個渲染器,在每個影格之後立即等待最為直截了當。若要重疊工作,請為未決影格提供個別的可變資料,並保留每個影格最終用途的完成值。在更新常數緩衝區、取代紋理或處置管線之前,請完成對受影響資源的所有未決存取。 +concepts.synchronization.reuse.details: 調整大小或關閉時,在等待舊工作之前請先停止新用途。{swapChainResize}、資源處置與上下文處置不能用作應用程式工作的通用等待。三角形教學可以在回呼之間安全地調整大小,因為每個先前的影格都已完成其提交。 +concepts.synchronization.reuse.guidance: 目前的 {swapChainPresent} 在其呈現操作之後也會在圖形佇列上發出訊號並等待。因此,僅移除三角形明確的提交等待並不會自動建立起重疊的呈現迴圈。圖形佇列等待對仍在另一個佇列上執行的獨立工作也毫無作用。 +concepts.synchronization.reuse.title: 僅在最後存取後重複使用資料 +concepts.synchronization.timelines.context: 在 CPU 讀取、覆寫或釋放這些資源之前,請等待其最後一次使用: +concepts.synchronization.timelines.description: 時間線使用遞增的數值追蹤佇列上的完成進度。{submit} 傳回包含該時間線與提交關聯數值的 {timelineValue}。來自不同時間線的完成值不能僅透過其數值 {value} 欄位進行比較。 +concepts.synchronization.timelines.details: 假設 {producer} 與 {consumer} 是來自相同上下文之兩個佇列中已記錄的命令緩衝區。生產者寫入取用者使用的資料。像這樣提交它們: +concepts.synchronization.timelines.guidance: 傳遞產生的數值會使取用佇列在 GPU 上等待該數值。CPU 在此處不呼叫 {producedWait}。在 {consumed} 完成之前保持共用資源有效,並記錄取用者所需的任何紋理配置變更。 +concepts.synchronization.timelines.notes: "{wait} 等待該時間線值,接著檢查其所屬佇列中已完成的提交。完成的命令緩衝區會重設以供重複使用,其中暫存的回讀資料會複製至提供的 CPU 目的地。{queueTimelineSignal} 也可以在已提交至該佇列的工作之後排入完成點。呼叫 {signal} 不代表 GPU 已經到達該點。" +concepts.synchronization.timelines.title: 使用時間線進行完成通知與佇列交接 +concepts.synchronization.title: 同步 +home.actions.reference: 瀏覽 API +home.actions.tutorial: 從三角形開始 +home.entries.description: 第一個影格。聚焦的範例。深入探討 API。 +home.entries.label: 探索說明文件 +home.entries.reference.action: 探索 API +home.entries.reference.category: 參考 +home.entries.reference.description: 尋找支援您應用程式的型別、簽章與成員。 +home.entries.reference.title: API 參考 +home.entries.samples.action: 瀏覽範例 +home.entries.samples.category: 範例 +home.entries.samples.description: 透過原始碼探索聚焦的渲染與計算技術。 +home.entries.samples.title: 範例 +home.entries.title: 開始建置。 +home.entries.tutorial.action: 開始教學 +home.entries.tutorial.category: 教學 +home.entries.tutorial.description: 從設定到第一個影格,建置完整的渲染應用程式。 +home.entries.tutorial.title: 第一個三角形 +home.introduction.accent: "以 C# 打造。" +home.introduction.description: 透過單一 .NET API 建立資源、記錄命令並提交圖形或計算工作。 +home.introduction.title: 建置專屬的渲染器。 +home.meta.description: "橫跨 DirectX、Metal 與 Vulkan,為圖形與計算提供一致的 C# API。" +home.scene.description: 旋轉幾何體研究。拖曳或使用方向鍵調整檢視。 +home.scene.label: 幾何體顯示 +home.scene.surface: 表面 +home.scene.wireframe: 線框 +home.title: 適用於 .NET 的現代 RHI +learning.concepts.description: 在組合渲染通道之前,先理解命令、資源、著色器資料與同步如何相互配合。 +learning.concepts.execution.description: 記錄 GPU 工作、予以提交並維持其資源存活。 +learning.concepts.platforms.description: 連接原生視窗或 UI 渲染控制項。 +learning.concepts.resources.description: 選擇資源用途、記憶體配置位置與檢視。 +learning.concepts.shaders.description: "使 C# 配置與資源控制代碼符合 Slang。" +learning.concepts.synchronization.description: 安排相依存取的順序,並掌握工作完成的時間點。 +learning.concepts.title: 核心概念 +learning.description: 從完整的三角形教學開始。接著利用聚焦範例與概念指南,理解更大型渲染器背後的資源、資料與相依性。 +learning.entries.samples.action: 瀏覽範例 +learning.entries.samples.description: "尋找幾何體、計算、光線查詢與網格著色(mesh shading)的 C# 和 Slang 範例。" +learning.entries.tutorial.action: 開啟教學 +learning.entries.tutorial.description: 建立主控台應用程式、開啟視窗並繪製三角形。 +learning.meta.description: 開始使用 Zenith.NET 並探索其程式設計模型。 +learning.title: 學習 +reference.description: 查詢資源型別、命令簽章與平台整合。 +reference.entries.commands.description: 記錄圖形、計算與傳輸命令。 +reference.entries.commands.label: 記錄工作 +reference.entries.context.description: 為所選後端建立 GPU 資源。 +reference.entries.context.label: 從這裡開始 +reference.meta.description: 探索 Zenith.NET 中的型別與成員。 +reference.navigation.core: 瀏覽核心 API。 +reference.title: API 參考 +samples.computeShader.description: 透過計算分派將影像轉換為灰階並顯示產生的紋理。展示了用於取樣輸入紋理與可寫入輸出紋理的資源控制代碼、無條件進位的執行緒群組計數,以及著色器內部的邊界檢查。請保留隨附的 {assetsTexturesShokoPng} 資產;渲染器會處理一次並在後續影格中呈現結果。 +samples.computeShader.details: "{computeShaderRendererCs} · {computeShaderSlang}" +samples.computeShader.title: 計算著色器 +samples.cube.description: 新增索引繪製、常數緩衝區中的模型、檢視與投影矩陣,以及深度測試。深度紋理會在調整大小時重新建立。從裁剪空間幾何體過渡到變換物件時可參考此範例;渲染器使用 {d32FloatS8UInt} 深度/樣板附件。 +samples.cube.details: "{spinningCubeRendererCs} · {spinningCubeSlang}" +samples.cube.title: 旋轉立方體 +samples.description: "針對您要研究的功能選擇聚焦的範例。每個範例都會連結至 C# 渲染器及其 Slang 著色器。若希望從空白專案逐步理解完整的應用程式,請從 {link} 開始。" +samples.description.link: 第一個三角形 +samples.execution.description: "{link} 在單一桌面應用程式中包含六個獨立的渲染器。請使用 .NET 10 SDK 與下方所述受支援的桌面後端。建置並執行該應用程式,然後從主控台功能表中選取範例:" +samples.execution.description.link: ZenithTutorials +samples.execution.details: "宿主程式在 Windows 上選取 DirectX 12,在 macOS 上選取 Metal,在 Linux 上選取 Vulkan。請使用所選後端支援的裝置、驅動程式與著色器編譯器環境。Linux 視窗路徑需要 X11 或 XWayland。{link} 宣告了套件相依性,並複製執行階段所需的著色器與紋理資產。" +samples.execution.details.link: 專案檔 +samples.execution.guidance: 這些範例共用視窗處理與呈現程式碼。您可以依據想研究的功能獨立選擇任何範例。 +samples.execution.title: 執行教學範例 +samples.host.description: "{appCs} 建立圖形上下文、視窗與交換鏈。它取得命令緩衝區、呼叫選取的渲染器、提交影格並進行呈現。{iRendererCs} 定義了渲染器的更新、渲染、調整大小與處置方法。" +samples.host.details: "計算與光線追蹤會產生螢幕外紋理。{texturePresenterCs} 與 {presentTextureSlang} 將這些紋理繪製到視窗目前影格的輸出紋理中。宿主程式仍保有提交與交換鏈呈現的所有權。" +samples.host.title: "共用宿主程式與呈現" +samples.indirectDrawing.description: 使用索引間接引數緩衝區與結構化緩衝區中的逐執行個體資料繪製立方體的多個複本。CPU 提供繪製引數並更新變換。在加入 GPU 產生的引數前,可透過此範例了解間接引數配置以及著色器對執行個體資料的存取。 +samples.indirectDrawing.details: "{indirectDrawingRendererCs} · {indirectDrawingSlang}" +samples.indirectDrawing.title: 間接繪製 +samples.meshShading.description: 使用工作著色器(task shader)剔除球體執行個體,並將其索引傳遞至發出幾何體的網格著色器(mesh shader)。渲染器在建立管線前會檢查 {contextCapabilitiesMeshShadingSupported}。可用於追蹤跨工作與網格階段的資源控制代碼及裝載資料。 +samples.meshShading.details: "{meshShadingRendererCs} · {meshShadingSlang}" +samples.meshShading.title: 網格著色(Mesh Shading) +samples.rayTracing.description: 為地面與程序化球體建置底層與頂層加速結構,接著在計算著色器中執行內嵌光線查詢。渲染器在建構工作負載前會檢查 {contextCapabilitiesRayTracingSupported}。此範例適用於加速結構輸入與著色器端光線周遊。 +samples.rayTracing.details: "{rayTracingRendererCs} · {rayTracingSlang}" +samples.rayTracing.title: 光線追蹤 +samples.title: 範例 +samples.triangle.description: 建立頂點緩衝區與相符的輸入配置,接著透過圖形管線繪製三個頂點。可用於將資源建立與渲染通道中的命令連結起來。 +samples.triangle.details: "{helloTriangleRendererCs} · {helloTriangleSlang} · {link}" +samples.triangle.details.link: 完整教學 +samples.triangle.title: Hello Triangle +samples.workloads.description: 主要存放庫的 {link} 包含結合多項功能的應用程式。其專案會參考程式庫原始碼。從 Zenith.NET 的簽出目錄執行所選專案即可,例如: +samples.workloads.description.link: Experiments 目錄 +samples.workloads.details: "視窗化實驗在 Windows、macOS 與 Linux/X11 上使用相同的宿主程式選項。若要在 Avalonia、WinForms、WPF、WinUI/Uno 或 MAUI 中繪製,請參閱 {link} 以取得控制項影格生命週期與實作連結。" +samples.workloads.details.link: 平台整合 +samples.workloads.table.cornellBox.example: "{link}" +samples.workloads.table.cornellBox.example.link: CornellBox +samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: "路徑追蹤、降噪、色調對應、影像升頻與 ImGui 控制項。需要光線追蹤支援,以及對應桌面後端的著色器編譯環境。" +samples.workloads.table.fluidTank.example: "{link}" +samples.workloads.table.fluidTank.example.link: FluidTank +samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: "計算流體模擬、模擬各階段之間的相依性,以及多通道表面渲染。需要該桌面後端與著色器編譯器環境。" +samples.workloads.table.headings.example: 範例 +samples.workloads.table.headings.whatItDemonstratesAndRequires: 示範內容與需求 +samples.workloads.table.inkCanvas.example: "{link}" +samples.workloads.table.inkCanvas.example.link: InkCanvas +samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: 在原生視窗中進行 Skia 繪圖與輸入處理。需要目標平台的後端與 Skia 原生程式庫。 +samples.workloads.table.platformDetection.example: "{link}" +samples.workloads.table.platformDetection.example.link: PlatformDetection +samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: 嘗試為每個後端建立圖形上下文並回報裝置功能。若上下文建立失敗,則回報為不支援;該結果也可能代表缺少驅動程式或執行階段相依性。 +samples.workloads.title: 探索更大型的工作負載 +tutorial.context.description: 視窗現在可以開啟,但我們尚未建立將要渲染至其中的 GPU 物件。{graphicsContext} 提供對所選圖形後端及其命令佇列的存取。 +tutorial.context.details: 在{emphasis}插入此區塊: +tutorial.context.details.emphasis: using 指示詞之後、{iWindowWindow} 之前 +tutorial.context.guidance: 分支邏輯會在 Windows 上選取 DirectX 12,在 macOS 上選取 Metal,在 Linux 上選取 Vulkan。後續的渲染程式碼皆使用共用的 Zenith.NET API。我們在開發期間要求啟用驗證,並列印透過 {validationMessage} 回報的訊息。診斷資訊取決於後端以及電腦上可用的驗證元件。 +tutorial.context.title: 建立圖形上下文 +tutorial.description: 建置一個 .NET 主控台應用程式,開啟視窗並繪製帶有平滑色彩漸層的三角形。您將學習頂點資料、著色器與管線狀態如何協同運作,接著記錄並提交產生影像的命令。 +tutorial.details: 請依序閱讀各章節。您將先開啟空白視窗,接著顯示背景色彩,最後繪製三角形。在新增下一部分之前,每個檢查點都會確認應用程式的一部分正常運作。初始化僅執行一次;渲染回呼每次被叫用時都會記錄新的影格。 +tutorial.draw.context: "{draw} 的引數如下:" +tutorial.draw.description: 在 {windowRender} 回呼中,在 {beginRenderPass} 與 {endRenderPass} 之間,將 {addTheTriangleDrawCommandsHereLater} 取代為下列三個命令: +tutorial.draw.details: "{setPipeline} 選取我們剛建立的著色器與狀態。請在繫結頂點資料之前設定它:後端會使用管線的輸入配置來解譯繫結。" +tutorial.draw.guidance: "{setVertexBufferVertexBuffer} 將從位元組位移 0 開始的緩衝區繫結至輸入插槽 0。該插槽對應於 {inputLayouts} 中的單一項目。它不會再次複製或上傳資料。" +tutorial.draw.notes: 此時命令仍僅處於已記錄狀態。已位於渲染回呼結尾的 {submitWait} 與 {present} 呼叫會執行工作並顯示其結果。清除操作依然必要,因為三角形只覆蓋影像的一部分;背景在每個影格中也必須接收定義好的色彩。 +tutorial.draw.table.firstInstance.meaning: 執行個體編號從零開始。 +tutorial.draw.table.firstVertex.meaning: 從緩衝區中的第一個頂點開始。 +tutorial.draw.table.headings.argument: 引數 +tutorial.draw.table.headings.description: 值 +tutorial.draw.table.headings.meaning: 意義 +tutorial.draw.table.instanceCount.meaning: 繪製三角形的一個複本。 +tutorial.draw.table.vertexCount.meaning: 讀取三個頂點。 +tutorial.draw.title: 在通道內繪製三角形 +tutorial.execution.description: 從 {firstTriangle} 目錄建置並執行: +tutorial.execution.details: 視窗應顯示一個三角形,在深色背景下具有紅色的上頂點、綠色的右下角與藍色的左下角。內部應顯示這些色彩之間的平滑漸層。 +tutorial.execution.guidance: 調整視窗大小。調整大小回呼會更新畫面緩衝區尺寸並調整交換鏈的大小。渲染通道會建立符合該影像的視口。由於頂點位置保持為標準化座標,三角形保持視窗寬度與高度的相同比例;變更外觀比例可能會拉伸其形狀。保留物件的外觀比例需要投影或視口原則,這超出了此初次繪製的範疇。 +tutorial.execution.title: 執行、調整大小與關閉 +tutorial.frame.commands.context: 在 {endRenderPass} 之後,第二次轉換會準備影像以供呈現。{submit} 結束記錄並提交命令緩衝區;{wait} 等待 GPU 完成該提交。接著 {present} 要求顯示渲染完成的影像。 +tutorial.frame.commands.description: 渲染通道(render pass)將使用相同附件的繪製操作分組在一起。在此,色彩附件是交換鏈的輸出紋理,即接收繪圖的影像。{colorAttachmentClear} 會建立描述,指示通道清除為指定的 RGBA 色彩,並在通道結束時保留結果。{beginRenderPass} 記錄這些指示;GPU 會在命令提交後執行清除。 +tutorial.frame.commands.details: 中括號內包含我們唯一的色彩附件。{null} 引數代表沒有深度/樣板附件,該附件通常會儲存用於深度與樣板測試的深度值與樣板遮罩。 +tutorial.frame.commands.guidance: "{beginRenderPass} 會設定涵蓋附件的視口與裁剪區域。視口將渲染座標對應至像素,而裁剪區域則限制可寫入的像素。這些預設值涵蓋整個輸出紋理,這正是繪製此三角形所需的。" +tutorial.frame.commands.title: 清除、提交與呈現 +tutorial.frame.description: 首先以單一背景色彩填滿影像。此操作稱為清除(clear)。若該色彩出現在視窗中,即表示原生呈現目標、命令提交與呈現路徑正常協同運作。此檢查點可讓您在新增幾何體與著色器之前先驗證影格迴圈。 +tutorial.frame.details: 渲染回呼是 Silk.NET 在需要繪製影格時叫用的程式碼。此回呼不需要事件的經過時間引數,因此命名為 {value}。在{emphasis}註冊它: +tutorial.frame.details.emphasis: "{windowRun} 之前" +tutorial.frame.target.description: "{graphicsQueueCommandBuffer} 會取得已開始記錄的命令緩衝區。記錄是為 GPU 描述工作;它不會立即執行該工作。" +tutorial.frame.target.details: 第一個 {transition} 會準備輸出紋理以供色彩附件存取。{default} 選取 Mip 層級 0 與陣列層 0。我們使用 {undefined} 作為前一個配置,因為我們將清除整個影像並捨棄先前的內容。需要保留現有內容的通道則必須改用其實際的前一個配置。 +tutorial.frame.target.guidance: 每個影格請使用交換鏈目前的輸出紋理。呈現操作可能會變更可用的影像,因此從較早影格儲存的紋理並非永久的視窗渲染目標。 +tutorial.frame.target.title: 準備輸出紋理 +tutorial.frame.title: 顯示背景色彩 +tutorial.geometry.data.description: 在{emphasis}新增此陣列。後續的資源建立步驟也依所示順序位於該回呼之前。 +tutorial.geometry.data.description.emphasis: "{windowRender} 之前" +tutorial.geometry.data.details: 每個陣列項目建立一個 {vertex}。內部的兩個 {new} 運算式建立其 {vector3} 位置與 {vector4} 色彩。頂點描述了頂部、右下角與左下角。頂點著色器將提供第四個位置座標 {w}。當 w 等於 1 時,x 與 y 直接描述標準化裝置座標:-1 與 +1 是影像邊緣,0 是中心。這些座標與視窗的像素尺寸無關。 +tutorial.geometry.data.guidance: "每種色彩包含紅、綠、藍與 Alpha 分量。三個頂點的 Alpha 皆為 1,且位置的 z 座標皆為 0,因此位於同一平面上。這些位置已經直接描述要渲染的座標,無需相機或變換矩陣。對於這個單一平面三角形,我們還會停用混合與深度測試,並省略深度緩衝區。" +tutorial.geometry.data.title: 選擇頂點位置 +tutorial.geometry.description: "頂點由一個位置以及繪製時使用的資料組成。我們的三角形有三個頂點,每個角各一個。每個頂點都包含位置與色彩。GPU 會對色彩進行插補,計算三角形內部各處的中間值。" +tutorial.geometry.format.description: 在{emphasis}附加此宣告: +tutorial.geometry.format.description.emphasis: "{programCs} 的結尾處、清理陳述式之後" +tutorial.geometry.format.details: "{file} 將此型別限制在 {programCs} 內,建構函式初始化其位置與色彩欄位。{layoutKindSequential} 保持欄位依宣告順序排列。{position} 包含三個 32 位元浮點數,{color} 包含四個。在此結構中,位置始於位元組 0,色彩始於位元組 12,完整的頂點佔用 28 個位元組。我們將向圖形管線描述這完全相同的配置。" +tutorial.geometry.format.title: 定義頂點 +tutorial.geometry.title: 向 GPU 提供三個頂點 +tutorial.geometry.upload.context: "{fixed} 可防止記憶體回收行程在使用陣列位址時移動該陣列。對於此 CPU 可寫入的緩衝區,{upload} 在返回之前會對應、複製並取消對應記憶體,因此之後無需保持陣列固定。緩衝區在整個渲染過程中必須保持存活,且上傳只需進行一次,因為頂點不會改變。" +tutorial.geometry.upload.description: 受控陣列是 CPU 資料。{buffer} 提供 GPU 可從中讀取頂點的儲存空間。在陣列之後新增: +tutorial.geometry.upload.details: 總大小為 {sizeofVertexVerticesLength}:每個頂點 28 位元組,三個頂點,總共 84 位元組。{bufferUsagesVertex} 允許頂點輸入存取。{cpuWriteOnly} 允許 CPU 直接初始化此小型緩衝區。描述項的跨距記錄了元素大小;我們稍後建立的輸入配置將指示頂點擷取機制如何讀取個別屬性。 +tutorial.geometry.upload.guidance: 建立緩衝區並不會填入資料。{upload} 會將陣列複製到該配置中,起始於目標位元組位移 0。其來源描述提供指標與要複製的位元組數。 +tutorial.geometry.upload.notes: 在 {programCs} 底部的清理程式碼中,緊接在 {swapChainDispose} 之前新增 {vertexBufferDispose}。對於較大型的靜態幾何體,{link}解釋了何時應選擇僅 GPU 記憶體並改用傳輸上傳。 +tutorial.geometry.upload.notes.link: 資源管理 +tutorial.geometry.upload.title: 配置緩衝區並上傳陣列 +tutorial.input.description: 頂點位元組與著色器皆已就緒。接下來描述 GPU 應該如何讀取每個頂點。屬性是單一值,例如位置或色彩。輸入配置賦予每個屬性格式與位元組位移;跨距提供從一個頂點到下一個頂點的位元組距離。在建立著色器後新增此初始化區塊: +tutorial.input.details: "{inputLayoutAdd} 會在目前跨距處附加元素,並將該跨距增加該元素的大小。它不會檢查 C# 結構。在此處它產生了 CPU 記憶體與著色器輸入之間的下列協議:" +tutorial.input.guidance: "變更 C# 欄位順序或填補而未更新此描述會使 GPU 讀取錯誤的位元組。預設的 {semanticIndex} 為零,符合 {pOSITION0} 與 {cOLOR0}。兩個元素屬於同一個緩衝區,因此管線將包含一個輸入配置,且我們會將該緩衝區繫結至插槽 0。" +tutorial.input.table.headings.byteOffset: 位元組位移 +tutorial.input.table.headings.cField: "C# 欄位" +tutorial.input.table.headings.format: 格式 +tutorial.input.table.headings.shaderInput: 著色器輸入 +tutorial.input.table.nextVertex.cField: 下一個頂點 +tutorial.input.table.nextVertex.format: 總跨距:28 位元組 +tutorial.input.table.nextVertex.shaderInput: 下一筆輸入記錄 +tutorial.input.table.vertexColor.format: "{float4}(16 位元組)" +tutorial.input.table.vertexPosition.format: "{float3}(12 位元組)" +tutorial.input.title: 描述頂點輸入配置 +tutorial.lifecycle.description: 完成的應用程式會重複此順序: +tutorial.lifecycle.details: 關閉視窗會從 {run} 返回。每個渲染完成的影格都已等待其 GPU 工作完成,因此我們現在可以處置它所使用的資源。{windowRun} 之後的清理程式碼應為: +tutorial.lifecycle.guidance: "在銷毀原生視窗前釋放交換鏈,並在釋放所有資源後釋放圖形上下文。佇列擁有並回收提交的命令緩衝區,交換鏈擁有其輸出紋理。因此,本應用程式不需要個別對這些命令緩衝區或輸出紋理呼叫 {dispose}。" +tutorial.lifecycle.title: 追蹤單一影格的生命週期 +tutorial.pipeline.behavior: 在輸入配置之後新增: +tutorial.pipeline.context: "{cullNone} 會填滿三角形而不捨棄任何面朝向。其頂點的順序決定了面的環繞方向,因此停用剔除可防止該順序隱藏我們第一個三角形。" +tutorial.pipeline.description: 我們現在擁有頂點資料、輸入配置與兩個著色器。{graphicsPipeline} 將它們連接起來,並指定 GPU 如何將頂點組裝為基本圖元並將結果寫入附件。 +tutorial.pipeline.details: 管線將可程式化著色器階段與固定功能設定結合,後者控制諸如三角形組裝、面剔除與混合等 GPU 操作。對於此三角形,請選取下列設定: +tutorial.pipeline.guidance: 色彩格式取自 {swapChainDescFormat}。它必須符合渲染通道所使用的影像。{count1} 代表每個像素一個取樣。 +tutorial.pipeline.item: "{triangleList} 會將每組連續的三個頂點組裝成一個三角形。我們將提供三個頂點並繪製一次,因此不需要索引緩衝區。" +tutorial.pipeline.notes: "{depthNone} 會停用深度測試與寫入,符合沒有深度附件的通道。" +tutorial.pipeline.reference: "{opaque} 會停用混合,因此片元著色器的色彩會取代三角形內部的背景。" +tutorial.pipeline.title: 連接著色器與頂點配置 +tutorial.pipeline.usage: 著色器物件可在建立管線後釋放,正如範例渲染器中所做的那樣。對於使用該管線進行繪製的每個影格,請保持管線本身存活。在清理程式碼中將 {pipelineDispose} 加入 {vertexBufferDispose} 之前。管線建立是渲染回呼前的最後一個初始化步驟。 +tutorial.pipeline.validation: 管線描述宣告了附件設定;它不會建立另一個影像。{inputLayouts} 只有一個項目,因為位置與色彩一起儲存在單一緩衝區中。 +tutorial.presentation.title: 將 GPU 連接至視窗 +tutorial.project.context: 在專案建置設定中啟用{emphasis}({allowUnsafeBlocks})。我們將用它將頂點資料傳遞給 GPU,並用於視窗協助程式的原生呼叫。 +tutorial.project.context.emphasis: 允許不安全的程式碼 +tutorial.project.description: 建立專案並進入其目錄: +tutorial.project.details: 安裝套件: +tutorial.project.guidance: "{zenithNET} 提供共用渲染 API。這三個後端套件讓同一個程式能選擇適合其平台的實作。{zenithNETCompiler} 會針對該實作編譯 Slang 著色器(我們稍後將編寫的小型 GPU 程式)。Silk.NET 提供視窗與事件迴圈。" +tutorial.project.title: 建立主控台專案 +tutorial.requirements.context: 您可以從空白專案開始跟隨本頁操作。{link}與其{detail}可作為此處使用之渲染與視窗 API 的參考。 +tutorial.requirements.context.detail: "共用宿主程式" +tutorial.requirements.context.link: Hello Triangle 範例 +tutorial.requirements.description: "您需要 {emphasis}、程式碼編輯器或 IDE,以及配備 Zenith.NET 後端所支援之 GPU 與驅動程式的桌上型電腦。具備基礎 C# 知識即可;圖形概念會在初次使用時一併介紹。這是一個標準的 {net10} 主控台專案。後端負責將 Zenith.NET 操作轉譯為對圖形 API(例如 DirectX 12、Metal 或 Vulkan)的呼叫。應用程式在啟動時選擇其一:" +tutorial.requirements.description.emphasis: .NET 10 SDK +tutorial.requirements.details: 在此處使用的視窗路徑中,Linux 需要與 X11 相容的視窗工作階段。此三角形不需要選用的光線追蹤與網格著色(mesh shading)功能。 +tutorial.requirements.guidance: Zenith.NET 會渲染至應用程式提供的表面。Silk.NET.Windowing 將建立桌面視窗並處理其事件。在 macOS 上,呈現目標為 Metal 圖層({cAMetalLayerCs});教學的視窗協助程式會為我們附加該圖層。 +tutorial.requirements.table.headings.graphicsBackend: 圖形後端 +tutorial.requirements.table.headings.platform: 平台 +tutorial.requirements.table.headings.windowSurface: 視窗表面 +tutorial.requirements.table.linux.graphicsBackend: Vulkan 1.4 +tutorial.requirements.table.linux.platform: Linux +tutorial.requirements.table.linux.windowSurface: X11 視窗與顯示;XWayland 亦適用 +tutorial.requirements.table.macOS.graphicsBackend: Metal 4 +tutorial.requirements.table.macOS.platform: macOS +tutorial.requirements.table.macOS.windowSurface: 附加至視窗的 Metal 圖層 +tutorial.requirements.table.windows.graphicsBackend: DirectX 12 +tutorial.requirements.table.windows.platform: Windows +tutorial.requirements.table.windows.windowSurface: Win32 視窗控制代碼 +tutorial.requirements.title: 開始之前 +tutorial.resize.context: 再次執行 {dotnetRun}。視窗現在應該具有均勻的深色背景,並在調整大小後繼續填滿視窗。請保留此回呼:三角形將繪製在其現有的渲染通道內。 +tutorial.resize.description: 交換鏈的影像必須遵循畫面緩衝區的尺寸。使用 {framebufferResize} 回應像素大小的變更,包括因顯示比例調整而引起的變更。在渲染回呼之後、仍處於 {windowRun} 之前新增: +tutorial.resize.details: Silk.NET 會區分視窗大小變更與{link}。我們需要後者,因為交換鏈儲存的是像素。最小化的視窗可能具有零大小的畫面緩衝區。在這種情況下,兩個回呼都會略過其 GPU 工作。調整大小後,渲染通道將使用新的附件尺寸作為其視口與裁剪區域。 +tutorial.resize.details.link: 畫面緩衝區大小變更 +tutorial.resize.guidance: 我們在每次提交後都會等待,因此當調整大小處理常式取代影像時,沒有較早的影格仍在使用這些影像。目前的 {present} 實作也會在圖形佇列上等待。這個簡單的迴圈確保前一個影格的工作完成後下一個影格才會開始;{link}涵蓋了更進階的排程方式。 +tutorial.resize.guidance.link: 同步 +tutorial.resize.title: 回應視窗大小調整 +tutorial.shaders.compilation.context: 編譯會在初始化期間執行一次。{appContextBaseDirectory} 負責在可執行檔旁找出複製的著色器,而與目前工作目錄無關。這些著色器僅使用頂點輸入,因此目前尚無常數緩衝區、紋理或資源控制代碼需要繫結。 +tutorial.shaders.compilation.description: "在 {triangleSlang} 的檔案屬性中,將{emphasis}設為{detail}。建置時會將著色器複製到可執行檔旁。" +tutorial.shaders.compilation.description.detail: 有更新時才複製 +tutorial.shaders.compilation.description.emphasis: 複製到輸出目錄 +tutorial.shaders.compilation.details: 返回 {programCs}。在頂點上傳之後、渲染回呼之前新增這些初始化陳述式: +tutorial.shaders.compilation.guidance: "{zenithCompiler} 會傳回包含所要求圖形 API 程式碼的著色器描述。{createShader} 會建立對應的後端物件。圖形 API 與進入點名稱皆至關重要:使用 {contextGraphicsApi},並將 {vSMain} 與 {fSMain} 拼寫得與 Slang 檔案完全相同。" +tutorial.shaders.compilation.title: 針對選取的後端進行編譯 +tutorial.shaders.context: "{fSInput} 連接頂點著色器的輸出與片元著色器的輸入。由頂點著色器寫入時,{sVPOSITION} 提供裁剪空間位置,即 GPU 用來判斷哪些內容位於可見影像範圍內的四個座標。{cOLOR0} 傳遞要在頂點之間插補的色彩。兩個階段使用的型別與語意必須一致。" +tutorial.shaders.description: 著色器是由 GPU 執行的程式。本次繪圖需要一個頂點著色器來定位頂點,以及一個片元著色器來產生三角形內部的色彩。我們將使用 Slang 著色器語言編寫它們,並從同一個檔案編譯兩個進入點。進入點是著色器階段開始執行的函式。 +tutorial.shaders.details: 建立 {triangleSlang},從以下兩個結構開始: +tutorial.shaders.fragment.description: 將片元進入點附加至同一個檔案: +tutorial.shaders.fragment.details: 光柵化決定三角形涵蓋哪些影像位置。它會產生片元(由片元著色器處理的資料),頂點色彩在涵蓋區域內進行插補。{fSMain} 透過識別第一個色彩附件的 {sVTARGET} 傳回此插補色彩。 +tutorial.shaders.fragment.guidance: 頂點色彩插補與附件混合是獨立分開的。混合會將片元的輸出與附件中已儲存的色彩結合。我們的不透明混合狀態停用了該結合,因此插補色彩會直接取代三角形內部的背景。 +tutorial.shaders.fragment.title: 為片元著色 +tutorial.shaders.guidance: "{vSInput} 描述頂點著色器從頂點緩衝區接收的內容。語意 {pOSITION0} 與 {cOLOR0} 識別輸入;僅憑 C# 欄位名稱無法建立該對應。" +tutorial.shaders.title: 編寫兩個著色器階段 +tutorial.shaders.vertex.description: 將頂點進入點附加至 {triangleSlang}: +tutorial.shaders.vertex.details: GPU 會針對每個輸入頂點叫用此進入點。它將齊次座標 {w} 加入位置並轉發色彩。在頂點階段之後,位置會除以 w;在此處該除法保持 x、y 與 z 不變。這就是為何上方選擇的位置可以直接理解為標準化裝置座標的原因。 +tutorial.shaders.vertex.title: 定位每個頂點 +tutorial.surface.description: 圖形上下文還需要知道要在何處顯示其輸出。在{emphasis}新增下列內容: +tutorial.surface.description.emphasis: "{windowCenter} 之後、{windowRun} 之前" +tutorial.surface.details: "{surface} 描述原生呈現目標及其像素尺寸。畫面緩衝區是與視窗關聯的像素影像。{framebufferSize} 以像素為單位提供其尺寸;啟用顯示比例縮放時,視窗的邏輯尺寸可能會有所不同。" +tutorial.surface.guidance: 此表面與上方選取的後端相符。Windows 提供視窗控制代碼,Linux 提供 X11 顯示與視窗,macOS 協助程式則提供附加的 Metal 圖層。這是將視窗連接至渲染流程中唯一與平台相關的部分。 +tutorial.surface.title: 描述原生呈現目標 +tutorial.swapChain.context: 交換鏈同時使用圖形上下文與原生視窗。將 {programCs} 底部的 {windowDispose} 行取代為以下清理順序: +tutorial.swapChain.description: 使用表面描述來建立將要呈現的影像。緊接在表面區塊之後新增: +tutorial.swapChain.details: "{swapChain} 管理視窗中顯示的影像。在每個影格中,{drawable} 會以影像資料 API 型別 {texture} 的形式為我們提供目前影像。繪製後,{present} 會要求顯示結果並前進至下一個 drawable。" +tutorial.swapChain.guidance: "{b8G8R8A8UNorm} 依藍、綠、紅與 Alpha 順序儲存四個 8 位元色彩通道。{uNorm} 表示 0 到 255 的整數值對應 0 到 1 的數值。著色器仍會傳回邏輯 RGBA 值;此格式決定這些通道在影像中的儲存方式。稍後圖形管線將使用 {swapChainDescFormat} 來匹配此附件。" +tutorial.swapChain.title: 建立交換鏈 +tutorial.title: 第一個三角形 +tutorial.troubleshooting.description: 先閱讀主控台中的任何錯誤,然後使用先前的檢查點來找出失敗的階段: +tutorial.troubleshooting.details: "使用 {link} 與 {detail} 來比較頂點資料、輸入配置與繪製操作。該範例將視窗處理與提交放入共用宿主程式;本教學則將應用程式流程保留在 {programCs} 中。請繼續閱讀 {context} 以學習索引繪製、變換與深度測試。" +tutorial.troubleshooting.details.context: 旋轉立方體 +tutorial.troubleshooting.details.detail: Slang 著色器 +tutorial.troubleshooting.details.link: 範例渲染器 +tutorial.troubleshooting.table.backend.check: 檢查選取的後端是否受到裝置與已安裝的圖形驅動程式支援。 +tutorial.troubleshooting.table.backend.symptom: 後端建立失敗 +tutorial.troubleshooting.table.drawing.check: 檢查上傳大小、輸入配置、管線選取,以及渲染通道內部繪製命令的位置。 +tutorial.troubleshooting.table.drawing.symptom: 背景出現但三角形未出現 +tutorial.troubleshooting.table.headings.check: 檢查項目 +tutorial.troubleshooting.table.headings.symptom: 徵狀 +tutorial.troubleshooting.table.input.check: 檢查 28 位元組跨距以及 0 與 12 的位置/色彩位移。 +tutorial.troubleshooting.table.input.symptom: 頂點位置或色彩損毀 +tutorial.troubleshooting.table.shaders.check: 檢查複製的 {triangleSlang}、進入點拼寫,以及編譯器回報的診斷資訊。 +tutorial.troubleshooting.table.shaders.symptom: 清除色彩步驟運作正常,但著色器載入失敗 +tutorial.troubleshooting.table.window.check: 確認 .NET 專案可成功建置,且僅含視窗的步驟可在桌面工作階段中執行。在 Linux 上,檢查 X11 或 XWayland 是否可用。 +tutorial.troubleshooting.table.window.symptom: 沒有開啟任何視窗 +tutorial.troubleshooting.title: 檢查失敗的階段 +tutorial.window.context: "{usingZenithTutorials} 會匯入協助程式的命名空間。每個 C# 檔案都使用各自的一般 using 指示詞,因此兩個檔案都需要互通性匯入。別名 {buffer} 是指 Zenith.NET 緩衝區型別,並將其與 {systemBuffer} 區分開來。" +tutorial.window.description: 將 {cocoaHelperCs} 新增至專案,並保留其命名空間。在該檔案頂端、其命名空間宣告之前新增 {interopUsing}。該協助程式會在 macOS 上將 Metal 圖層附加至視窗;其他平台分支不會呼叫它。 +tutorial.window.details: 將產生的 {programCs} 取代為下列程式碼。它使用最上層陳述式,依序執行而無需明確的 {main} 方法。後續小節將說明在此同一個檔案中新增程式碼的位置: +tutorial.window.guidance: "{graphicsAPINone} 要求 Silk.NET 建立沒有自身圖形上下文的視窗。我們將使用 Zenith.NET 建立該上下文。{initialize} 建立原生視窗並提供其控制代碼。控制代碼是由視窗系統提供的識別碼。{center} 使視窗置中,而 {run} 會處理事件直到視窗關閉。接著執行會繼續進行至 {dispose},釋放視窗。" +tutorial.window.notes: 執行 {dotnetRun}。應該會開啟一個空白視窗,並能回應移動、調整大小與關閉操作。由於我們尚未提交任何渲染命令,其內容尚未定義。請先將其關閉再繼續。 +tutorial.window.title: 開啟視窗 +ui.action.copy: 複製 +ui.action.navigate: 巡覽 +ui.action.open: 開啟 +ui.action.source: 檢視原始碼 +ui.api.browse: 瀏覽命名空間與型別。 +ui.api.clearTypeSearch: 清除型別搜尋 +ui.api.findType: 尋找型別 +ui.api.loadError: 無法載入型別。重新載入此頁面以重試。 +ui.api.loadingNamespaces: 正在載入命名空間… +ui.api.loadingTypes: 正在載入型別… +ui.api.matchingTypes: 相符的型別 +ui.api.namespace: 命名空間 +ui.api.namespaces: 命名空間 +ui.api.noNamespaceTypes: 此命名空間中沒有型別。 +ui.api.noTypes: 沒有相符的型別。 +ui.api.types: 型別 +ui.content.reference: 參考 +ui.content.source: 原始碼 +ui.content.tutorial: 教學 +ui.contents.close: 關閉目錄 +ui.contents.open: 開啟目錄 +ui.contents.title: 目錄 +ui.footer.caption: 適用於 .NET 的現代 RHI。 +ui.footer.label: 頁尾 +ui.language.label: 語言 +ui.language.unavailable: 未翻譯 +ui.members.clear: 清除成員搜尋 +ui.members.close: 關閉成員尋找工具 +ui.members.empty: 沒有相符的成員。 +ui.members.open: 前往成員 +ui.members.placeholder: 名稱或簽章… +ui.members.search: 搜尋成員 +ui.members.title: 尋找成員 +ui.members.undeclared: 此型別沒有宣告的成員。 +ui.navigation.api: API +ui.navigation.concepts: 概念 +ui.navigation.home: 首頁 +ui.navigation.label: 主要導覽 +ui.navigation.toggle: 切換導覽 +ui.outline.title: 本頁內容 +ui.reference.assembly: 組件 +ui.reference.classes: 類別 +ui.reference.constructors: 建構函式 +ui.reference.declaration: "C# 型別宣告" +ui.reference.delegates: 委派 +ui.reference.derived: 衍生型別 +ui.reference.enums: 列舉 +ui.reference.events: 事件 +ui.reference.examples: 範例 +ui.reference.exceptions: 例外狀況 +ui.reference.extensionMethods: 擴充方法 +ui.reference.fields: 欄位 +ui.reference.implementations: 明確介面實作 +ui.reference.implements: 實作 +ui.reference.inheritance: 繼承 +ui.reference.inheritedMembers: 繼承的成員 +ui.reference.interfaces: 介面 +ui.reference.metadata: 型別中繼資料 +ui.reference.methods: 方法 +ui.reference.namespace: 命名空間 +ui.reference.open: 開啟 {name} 的參考 +ui.reference.operators: 運算子 +ui.reference.parameters: 參數 +ui.reference.properties: 屬性 +ui.reference.related: 請參閱 +ui.reference.relationships: 繼承與中繼資料 +ui.reference.remarks: 備註 +ui.reference.returns: 傳回 +ui.reference.structs: 結構 +ui.reference.typeParameters: 型別參數 +ui.reference.value: 值 +ui.reference.values: 值 +ui.search.close: 關閉搜尋 +ui.search.empty: 找不到「{query}」的結果。 +ui.search.hint: 搜尋教學、概念、範例與 API 參考。 +ui.search.loading: 正在載入搜尋… +ui.search.more: 顯示更多結果 +ui.search.pending: 正在搜尋… +ui.search.placeholder: 您在尋找什麼? +ui.search.resultCount: 結果:{count} +ui.search.title: 搜尋文件 +ui.search.unavailable: 無法使用搜尋功能。您仍然可以開啟下方頁面。 diff --git a/documents/templates/public/resources.js b/documents/templates/public/resources.js index cc5cab70..cbad4724 100644 --- a/documents/templates/public/resources.js +++ b/documents/templates/public/resources.js @@ -11,13 +11,16 @@ export function setStrings(value) { if (!value || Array.isArray(value) || typeof value !== 'object' || Object.values(value).some(text => typeof text !== 'string' || !text.trim())) { throw new Error('Invalid resource dictionary'); } + if (Object.keys(value).length !== Object.keys(resourceState.placeholders).length) { + throw new Error('Resource key set differs'); + } const requireKey = (key, slots) => { if (!has(value, key)) throw new Error(`Missing text resource: ${key}`); if (slots && JSON.stringify(format.placeholders(value[key])) !== JSON.stringify([...slots].sort())) { throw new Error(`Resource placeholders differ: ${key}`); } }; - for (const [key, text] of Object.entries(resourceState.strings)) requireKey(key, format.placeholders(text)); + for (const [key, slots] of Object.entries(resourceState.placeholders)) requireKey(key, slots); for (const element of document.querySelectorAll('[data-resource]')) { const slots = element.querySelector(':scope > template[data-resource-slots]')?.content.children || []; requireKey(element.dataset.resource, [...slots].map(slot => slot.dataset.slot)); diff --git a/documents/templates/public/search.js b/documents/templates/public/search.js index ec08786b..3e33ce71 100644 --- a/documents/templates/public/search.js +++ b/documents/templates/public/search.js @@ -77,7 +77,9 @@ export function initializeSearch() { showResults(query, matches); return; } - const terms = query.split(/\s+/).map(term => '+' + term.replace(/[+\-:^~*\\]/g, '\\$&')).join(' '); + // Use the same separators as DocFX's index for filenames and qualified API names. + const terms = query.split(/[\s\-.()]+/).filter(Boolean).map(term => '+' + term.replace(/[+\-:^~*\\]/g, '\\$&')).join(' '); + if (!terms) return showResults(query, []); pendingQueries.push(query); worker.postMessage({ q: terms }); } @@ -150,13 +152,15 @@ export function initializeSearch() { if (!key) return { page: original, title: normalize(original.title.replace(/\s*\|\s*Zenith\.NET\s*$/, '')), - body: normalize(`${original.title} ${original.keywords || ''} ${original.summary || ''}`) + body: normalize(`${original.href} ${original.title} ${original.keywords || ''} ${original.summary || ''}`) }; const prefix = key.slice(0, -'.title'.length); const values = Object.entries(strings).filter(([key]) => key.startsWith(prefix + '.')).map(([, value]) => value); const description = strings[prefix + '.description'] || strings[prefix + '.meta.description']; const page = { ...original, title: t(key), summary: description && !description.includes('{') ? description : '' }; - return { page, title: normalize(page.title), body: normalize(values.join(' ')) }; + // Keep shared code, filenames and API identifiers searchable in every language. + const body = `${values.join(' ')} ${original.href} ${original.keywords || ''} ${original.summary || ''}`; + return { page, title: normalize(page.title), body: normalize(body) }; }); ready = true; runQuery(); diff --git a/documents/templates/resources.common.js b/documents/templates/resources.common.js index 6a37c197..3bdd9308 100644 --- a/documents/templates/resources.common.js +++ b/documents/templates/resources.common.js @@ -66,6 +66,7 @@ exports.prepare = function (model) { model._resourceState = json({ sourceLanguage: model._sourceLanguage, languages: model._languages, + placeholders: Object.fromEntries(Object.entries(source).map(([key, value]) => [key, format.placeholders(value)])), strings: Object.fromEntries(interfaceEntries) }); return source; From 8074346e622d69840da789881e5de5806e89bf72 Mon Sep 17 00:00:00 2001 From: qian-o <1324771795@qq.com> Date: Mon, 21 Sep 2026 17:47:44 +0800 Subject: [PATCH 19/35] Enhance translation guidelines and improve resource binding - Updated translation guidelines in `translation.md` for clarity on style, context, and usage of terms. - Modified `conceptual.extension.js` to include a new template handling mechanism for resource slots. - Adjusted `_master.tmpl` to ensure translation slot templates are rendered correctly outside the indexed articles. - Enhanced `resources.js` to support additional attributes for resource binding and improved slot template handling. - Updated `resources.common.js` to accommodate the new template structure in resource binding, ensuring proper handling of dynamic content. --- documents/authoring.md | 27 +- documents/index.md | 2 +- .../learn/concepts/platform-integration.md | 9 +- .../learn/concepts/resource-management.md | 1 - documents/learn/first-triangle.md | 70 +- documents/learn/samples.md | 20 +- documents/locales/de-DE/strings.yml | 658 ++++---- documents/locales/de-DE/translation.md | 12 +- documents/locales/en-US/strings.yml | 1338 ++++++++--------- documents/locales/es-ES/strings.yml | 1124 +++++++------- documents/locales/es-ES/translation.md | 10 + documents/locales/fr-FR/strings.yml | 658 ++++---- documents/locales/fr-FR/translation.md | 10 + documents/locales/ja-JP/strings.yml | 1120 +++++++------- documents/locales/ja-JP/translation.md | 10 + documents/locales/ko-KR/strings.yml | 690 +++++---- documents/locales/ko-KR/translation.md | 10 + documents/locales/pt-BR/strings.yml | 1112 +++++++------- documents/locales/pt-BR/translation.md | 10 + documents/locales/ru-RU/strings.yml | 700 +++++---- documents/locales/ru-RU/translation.md | 10 + documents/locales/zh-CN/strings.yml | 1108 +++++++------- documents/locales/zh-CN/translation.md | 16 +- documents/locales/zh-TW/strings.yml | 1102 +++++++------- documents/locales/zh-TW/translation.md | 18 +- documents/templates/conceptual.extension.js | 6 +- documents/templates/layout/_master.tmpl | 3 + documents/templates/public/resources.js | 10 +- documents/templates/resources.common.js | 13 +- 29 files changed, 4893 insertions(+), 4984 deletions(-) diff --git a/documents/authoring.md b/documents/authoring.md index 816d60bb..175e3725 100644 --- a/documents/authoring.md +++ b/documents/authoring.md @@ -35,7 +35,8 @@ Do not turn the samples index into a sequence of advanced tutorials. The triangl - Maintain the canonical prose in American English in `documents/locales/en-US/strings.yml`. Other `documents/locales//` directories hold translated dictionaries and follow that directory's permanent `translation.md`. Keep C# identifiers and namespace names exact. - Describe the current API directly. Avoid release histories, migration narratives, product-version badges, "new in" labels and temporary preview-package instructions. A new package release alone does not require a documentation edit when the documented behavior remains accurate. -- Omit package versions and `--prerelease` from installation commands. Necessary platform/SDK prerequisites and target frameworks may be stated when needed to run the example; these are environment requirements, not a product-version narrative. +- List required NuGet packages by package ID in alphabetical order, without package versions. Necessary platform/SDK prerequisites and target frameworks may be stated when needed to run the example; these are environment requirements, not a product-version narrative. +- Keep setup instructions specific to the example: its project type and name, target framework, and required packages. Assume readers know the basic operations for creating, opening, building, and running a .NET project and obtaining a repository. Avoid routine workflow narration and phrases such as "in your usual development environment." Do not prescribe shell commands or require a particular editor, IDE, or Git client. - Request validation by default with `useValidationLayer: true` in documented context creation. Runnable tutorials should connect `ValidationMessage` to console output so reported diagnostics are visible. - Verify behavior against `sources/` and runnable examples before writing. Read the implementation when ownership, synchronization or platform support is unclear; do not infer it from a type's name. If package behavior and repository source differ, resolve the mismatch before calling an example runnable. - Introduce unfamiliar graphics terms when they first matter. Distinguish descriptions from recorded commands, and recording from GPU execution. Explain prerequisites and insertion points before asking the reader to use them. @@ -46,11 +47,25 @@ Do not turn the samples index into a sequence of advanced tutorials. The triangl - Keep diagrams small enough to read on a phone. Prefer a vertical sequence to a wide horizontal graph when scaling would make its labels too small. - Replace `` when a page is filled. Check the existing homepage, Learn overview and README for placeholder wording that has become inaccurate; update that wording without redesigning those pages. +## Editorial style + +Use the register of a technical textbook: precise, measured, and readable. Explain the relationship between operations before stating their constraints. Tutorials still need direct instructions and observable checkpoints; academic style does not require passive voice, abstract phrasing, or longer sentences. + +Edit each article in its reading order, including the preceding paragraph, code, table, and following explanation. Resource keys are storage boundaries, not independent translation units. Link labels and emphasized fragments must agree grammatically with the complete sentence in which they appear. Avoid repeated requests to the reader, stock transitions, and literal phrases such as "the control owns the frame boundary" when the intended meaning is responsibility for the frame lifecycle. + +Keep a sentence when it explains the current operation, a design choice, an observable result, or a condition needed for correct use. Omit inventories of features the example does not use, generic platform caveats, repeated prerequisites, and comparisons with techniques not yet introduced. State a prerequisite once, where the reader needs it. Preserve concrete lifetime, synchronization, and layout requirements, and explain their effect on the operation at hand. + +Translate a heading or sentence as a whole, including text split across styled elements. Use movable named slots for emphasis and line breaks when the language order differs; do not hard-code English word order in shared markup or compensate by swapping unrelated resource values. The homepage title demonstrates this with its `accent` and `lineBreak` slots. When removing a redundant passage, remove its shared binding and retire its dedicated keys from all dictionaries together. + +Use concise headings and interface labels without terminal sentence punctuation. Visible homepage headings, introductory lines, card summaries, and the footer caption also omit terminal periods; write them as coherent short phrases instead of disconnected sentences. Body paragraphs, diagnostics, and accessibility instructions retain normal punctuation in the target language. + +Use one established term for each concept within a language. Do not append English equivalents selectively to translated terms or link labels. Preserve API identifiers, product names, filenames, and the named slots needed to locate code or IDE settings. Parentheses are appropriate for an actual explanation or setting identifier, not as a routine translation gloss. + ## Triangle and sample workflow First locate and inspect the existing tutorial/sample source. This checkout has examples under `sources/Experiments/`; it does not contain a dedicated triangle tutorial project. Locate any separately maintained tutorial repository before depending on it, and verify each linked file and API. Do not invent repository paths or treat an experiment as the canonical triangle tutorial without inspecting it. -The first triangle is a general .NET console application using NuGet packages. Show installation commands without package versions. Do not replace package installation with source project references or cloning the main repository to accommodate the validation machine. Keep any explicitly authorized test-only package selection in a temporary project outside the repository. +The first triangle is a general .NET console application using NuGet packages. Specify the project name, target framework, and required packages. Do not replace package installation with source project references or cloning the main repository to accommodate the validation machine. Keep any explicitly authorized test-only package selection in a temporary project outside the repository. Introduce the windowing library, backend selection and native-surface differences before graphics setup. Use one shared application flow for Windows, macOS and Linux, identify the windowing requirements, and keep platform interop in a small, verified support file where possible. Do not turn this into a platform-specific SDK setup tutorial. @@ -58,7 +73,7 @@ Teach the triangle in cumulative steps: an empty window, a presented clear color Follow the established tutorial source's code style: explicit control flow, target-typed initialization, and its blank lines between logical operations and fields. Do not compress branches into nested conditional expressions, manually wrap method calls to fit the page, or introduce constants and helper functions solely to reorganize the article. Long code lines scroll within the existing code blocks. -Use ordinary file-level `using` directives in the standalone tutorial. A support file copied from the tutorial repository may rely on that repository's global imports; state the imports it needs in the reader's project instead of introducing a global import to make the file compile. +Use ordinary file-level `using` directives, introducing each directive or alias in the step that first needs it. The initial window code should import only the windowing namespace. For a downloaded support file, provide its link and purpose. Treat adapting its namespace and imports as routine C# integration work; do not prescribe a namespace or walk through those adjustments. Introduce file settings when the file is created. For a shader, describe its Copy to Output Directory setting after writing the shader; do not front-load project XML for files the reader has not created. Prefer a directly linked support filename with a short purpose statement over raw-file download instructions. @@ -66,6 +81,8 @@ Keep snippets consistent with the complete application. The assembled source mus For each sample, provide a verified source link, its purpose and relevant requirements. Avoid copying its implementation into the page. Use the repository's normal branch links rather than transient local paths or release-specific URLs unless the example requires otherwise. +For screenshots maintained in the tutorial repository, use its main-branch raw image URLs in shared Markdown. Link each preview to the full-size image, include its intrinsic dimensions, and use native lazy loading. Bind alternative text with `alt="@resource.key"` and `data-resource-alt="resource.key"`; an existing sample title can identify its preview when the adjacent prose explains the result. The build renders English alternative text, and language switching updates it from the selected dictionary. + Compile the complete tutorial using its documented setup and run it to verify the visible triangle on the selected platform. A DocFX build validates the documentation, not the C# or shader examples. Report any platform that could not be exercised; do not claim cross-platform execution from a single-platform check. ## Inline references @@ -144,13 +161,13 @@ Keep XML `` contents literal using `CDATA`. Put `` references in the This is a WPF-style resource model. `index.md`, `learn/` and `api/index.md` contain the single shared page structure, anchors, links, illustrations and code. `toc.yml` is the only hand-maintained navigation tree. The API TOC is generated from C# metadata; it is not another authored navigation or a language-specific copy. -`locales/en-US/strings.yml` is the sole English source dictionary. Other language folders contain only their permanent `translation.md` until translation begins. A translator adds just `strings.yml`, keeping the `### YamlMime:Resources` header and the complete source key set. No localized pages, TOCs, images, templates, scripts or configuration are needed. All resource values are strings. +`locales/en-US/strings.yml` is the sole English source dictionary. Each other language folder retains its permanent `translation.md` and, when translated, a `strings.yml`. A translator adds or updates only `strings.yml`, keeping the `### YamlMime:Resources` header and the complete source key set. No localized pages, TOCs, images, templates, scripts or configuration are needed. All resource values are strings. Language folders, registrations and menus use code order: `de-DE`, `en-US`, `es-ES`, `fr-FR`, `ja-JP`, `ko-KR`, `pt-BR`, `ru-RU`, `zh-CN`, `zh-TW`. English is explicitly the source and fallback. Complete resource dictionaries become available automatically after the normal DocFX build. Missing keys, stale extra keys, non-string values and changed placeholder names fail that build. Pages share the same URL paths. `?lang=` selects a dictionary, retaining the page and fragment. Without an explicit language, the site uses a saved manual selection, browser preferences, then English. An explicit unsupported or unpublished language falls back to English, without substituting a different saved language. A missing, stale or malformed downloaded dictionary is rejected before any translated text is applied, keeping the complete English page usable. The English HTML is fully rendered during the build; other static dictionaries bind to that same markup in the browser. No translation API is used. Search uses translated resources with the shared generated API index. -All images remain in `images/`; all generated API YAML remains in `api/`. This is a complete refactor, with no legacy route or compatibility layer. Do not create `pages/`, `snippets/`, a parallel content graph or an additional build command for localization. +Site-owned images remain in `images/`; screenshots maintained in the tutorial repository are referenced by their main-branch URLs. All generated API YAML remains in `api/`. This is a complete refactor, with no legacy route or compatibility layer. Do not create `pages/`, `snippets/`, a parallel content graph or an additional build command for localization. ## Resource keys and placeholders diff --git a/documents/index.md b/documents/index.md index a4da1b07..f96697d9 100644 --- a/documents/index.md +++ b/documents/index.md @@ -9,7 +9,7 @@ _disableAffix: true
    -


    +


    diff --git a/documents/learn/concepts/platform-integration.md b/documents/learn/concepts/platform-integration.md index 566e3478..7008c2a8 100644 --- a/documents/learn/concepts/platform-integration.md +++ b/documents/learn/concepts/platform-integration.md @@ -45,13 +45,11 @@ title: '@concepts.platforms.title'

    App.csSurface.Wayland

    -

    context.Capabilities

    SwapChain.Drawable

    SwapChain.ResizeSwapChain.Refresh

    -

    Desc.WidthDesc.HeightDesc.FormatDesc.SampleCount

    IZenithViewGraphicsContextUpdateRequestedRenderRequestedRenderEventArgs

    @@ -70,6 +68,7 @@ view.RenderRequested += (_, args) =>

    ColorAttachment

    Undefined

    ZenithViewHelper.DrawableFormat

    +

    Desc.WidthDesc.HeightDesc.FormatDesc.SampleCount

    @@ -107,11 +106,7 @@ view.RenderRequested += (_, args) =>

    RenderRequested

    -

    - -```sh -dotnet add package Zenith.NET.Views.Avalonia -``` +

    Zenith.NET.Views.Avalonia

    UseZenithViewExtensions.cs

    diff --git a/documents/learn/concepts/resource-management.md b/documents/learn/concepts/resource-management.md index 2a573b11..22042388 100644 --- a/documents/learn/concepts/resource-management.md +++ b/documents/learn/concepts/resource-management.md @@ -166,4 +166,3 @@ title: '@concepts.resources.title'

    BufferViewTextureView

    -

    diff --git a/documents/learn/first-triangle.md b/documents/learn/first-triangle.md index 0c288142..40324dfd 100644 --- a/documents/learn/first-triangle.md +++ b/documents/learn/first-triangle.md @@ -13,67 +13,46 @@ title: '@tutorial.title' - - - - -

    CAMetalLayer.cs

    2.

    -

    - -```sh -dotnet new console -n FirstTriangle -f net10.0 -cd FirstTriangle -``` - +

    FirstTriangle

    - -```sh -dotnet add package Zenith.NET -dotnet add package Zenith.NET.Compiler -dotnet add package Zenith.NET.DirectX12 -dotnet add package Zenith.NET.Metal -dotnet add package Zenith.NET.Vulkan -dotnet add package Silk.NET.Windowing -``` - +
      +
    • Silk.NET.Windowing
    • +
    • Zenith.NET
    • +
    • Zenith.NET.Compiler
    • +
    • Zenith.NET.DirectX12
    • +
    • Zenith.NET.Metal
    • +
    • Zenith.NET.Vulkan
    • +

    Zenith.NETZenith.NET.Compiler

    AllowUnsafeBlocks

    3.

    -

    CocoaHelper.csusing System.Runtime.InteropServices;

    +

    CocoaHelper.cs

    Program.csMain

    ```csharp -using System.Numerics; -using System.Runtime.InteropServices; using Silk.NET.Windowing; -using Zenith.NET; -using Zenith.NET.DirectX12; -using Zenith.NET.Metal; -using Zenith.NET.Vulkan; -using ZenithTutorials; -using Buffer = Zenith.NET.Buffer; IWindow window = Window.Create(WindowOptions.Default with { @@ -90,12 +69,20 @@ window.Dispose(); ```

    GraphicsAPI.NoneInitialize()Center()Run()Dispose()

    -

    using ZenithTutorialsBufferSystem.Buffer

    -

    dotnet run

    +

    4.

    GraphicsContext

    +

    Program.cs

    + +```csharp +using Zenith.NET; +using Zenith.NET.DirectX12; +using Zenith.NET.Metal; +using Zenith.NET.Vulkan; +``` +

    IWindow window

    ```csharp @@ -223,11 +210,18 @@ window.FramebufferResize += _ =>

    Present()

    -

    dotnet run

    +

    6.

    +

    Program.cs

    + +```csharp +using System.Numerics; +using System.Runtime.InteropServices; +``` +

    Program.cs

    ```csharp @@ -256,6 +250,7 @@ Vertex[] vertices =

    VertexnewVector3Vector4w = 1

    +

    Program.csusing Buffer = Zenith.NET.Buffer;System.Buffer

    Buffer

    ```csharp @@ -337,7 +332,6 @@ float4 FSMain(FSInput input) : SV_TARGET ```

    FSMainSV_TARGET

    -

    Triangle.slang

    Program.cs

    @@ -430,7 +424,6 @@ vertexShader.Dispose(); fragmentShader.Dispose(); ``` -

    InputLayouts

    pipeline.Dispose();vertexBuffer.Dispose();

    10.

    @@ -482,11 +475,6 @@ commandBuffer.Draw(3, 1, 0, 0);

    11.

    FirstTriangle

    -```sh -dotnet build -dotnet run --no-build -``` -

    diff --git a/documents/learn/samples.md b/documents/learn/samples.md index a5eb613b..f7135203 100644 --- a/documents/learn/samples.md +++ b/documents/learn/samples.md @@ -7,33 +7,29 @@ title: '@samples.title'

    - -```sh -git clone https://github.com/qian-o/ZenithTutorials.git -cd ZenithTutorials -dotnet build ZenithTutorials.slnx -dotnet run --project ZenithTutorials/ZenithTutorials.csproj -``` - -

    -

    +

    @samples.triangle.title

    HelloTriangleRenderer.csHelloTriangle.slang

    D32FloatS8UInt

    +

    @samples.cube.title

    SpinningCubeRenderer.csSpinningCube.slang

    Assets/Textures/shoko.png

    +

    @samples.computeShader.title

    ComputeShaderRenderer.csComputeShader.slang

    +

    @samples.indirectDrawing.title

    IndirectDrawingRenderer.csIndirectDrawing.slang

    context.Capabilities.RayTracingSupported

    +

    @samples.rayTracing.title

    RayTracingRenderer.csRayTracing.slang

    context.Capabilities.MeshShadingSupported

    +

    @samples.meshShading.title

    MeshShadingRenderer.csMeshShading.slang

    App.csIRenderer.cs

    @@ -42,10 +38,6 @@ dotnet run --project ZenithTutorials/ZenithTutorials.csproj

    -```sh -dotnet run --project sources/Experiments/FluidTank/FluidTank.csproj -``` - diff --git a/documents/locales/de-DE/strings.yml b/documents/locales/de-DE/strings.yml index 2c7df811..81e97805 100644 --- a/documents/locales/de-DE/strings.yml +++ b/documents/locales/de-DE/strings.yml @@ -1,92 +1,91 @@ ### YamlMime:Resources -concepts.execution.context.description: "Ein {graphicsContext} repräsentiert ein Backend-Gerät und stellt dessen Grafik-, Compute- und Transferwarteschlangen bereit. Erstellen Sie die Puffer, Texturen, Shader und Pipelines für eine Arbeitslast über denselben Kontext. Ressourcen oder Handles aus einem anderen Kontext können nicht einfach an die Befehlspuffer dieses Kontexts gebunden werden." -concepts.execution.context.details: Wählen Sie das Backend für die Plattform und die Präsentationsoberfläche. Die API bleibt gemeinsam, aber die Geräteunterstützung spielt weiterhin eine Rolle. {capabilities} macht den Gerätenamen sowie die Flags {rayTracingSupported} und {meshShadingSupported} verfügbar. Überprüfen Sie das entsprechende Flag, bevor Sie eine optionale Arbeitslast erstellen, wie es die Beispiele {link} und {detail} tun. Diese Flags sind keine vollständige Liste von Format-, Speicher- oder Plattformbeschränkungen. +concepts.execution.context.description: "Ein {graphicsContext} verbindet die Anwendung über ein bestimmtes Backend mit einem GPU-Gerät und stellt dessen Grafik-, Compute- und Transferwarteschlangen bereit. Gemeinsam verwendete Ressourcen müssen demselben Kontext angehören: Puffer, Texturen, Shader, Pipelines und ihre Handles lassen sich nicht über Kontextgrenzen hinweg binden." +concepts.execution.context.details: "{capabilities} liefert den Gerätenamen und die unterstützten Funktionen. Prüfen Sie mit {rayTracingSupported} und {meshShadingSupported}, ob die jeweilige Funktion verfügbar ist, bevor Sie ihre Ressourcen erstellen. Die Beispiele für {link} und {detail} zeigen diese Prüfung bei der Initialisierung." concepts.execution.context.details.detail: Mesh-Shading concepts.execution.context.details.link: Raytracing -concepts.execution.context.title: Der Kontext verbindet Ressourcen und Warteschlangen -concepts.execution.description: Eine Zenith.NET-Anwendung erstellt GPU-Ressourcen, zeichnet Befehle auf, die diese verwenden, und reicht diese Befehle bei einer Warteschlange ein. Die CPU kann fortfahren, während die GPU die Übermittlung ausführt. Halten Sie Ressourcen gültig, bis diese Arbeit abgeschlossen ist, selbst nachdem die Aufzeichnungsaufrufe zurückgekehrt sind. -concepts.execution.ownership.description: "Hier bedeutet Besitz die Verantwortung für die Freigabe. Eine C#-Referenz hält ein verwaltetes Objekt erreichbar; sie verhindert nicht, dass ein explizites {dispose} die native Ressource zerstört. Ebenso überträgt das Einreichen eines Befehls, der einen Puffer verwendet, nicht den Besitz dieses Puffers an die Warteschlange." -concepts.execution.ownership.details: "Stoppen Sie beim Herunterfahren das Einreichen neuer Arbeit, warten Sie auf die letzten Verwendungen in jeder beteiligten Warteschlange, geben Sie die Ressourcen der Anwendung frei und anschließend den Kontext. Die Kontextfreigabe gibt dessen Warteschlangen und interne Hilfsobjekte frei; sie wartet nicht auf alle Anwendungsarbeiten und gibt nicht jede von der Anwendung erstellte Ressource frei." -concepts.execution.ownership.guidance: Wenden Sie beim Rendern dieselben Lebensdauerregeln an. Behalten Sie den Fertigstellungswert für die letzte Verwendung einer Ressource bei, damit Sie wissen, wann ihre Bytes überschrieben werden können oder die Ressource ersetzt werden kann. Siehe {link} für Ansichten und die Lebensdauer von zugrunde liegenden Ressourcen. +concepts.execution.context.title: "Grafikkontext" +concepts.execution.description: "GPU-Arbeit beginnt auf der CPU: Die Anwendung erstellt Ressourcen, zeichnet Befehle zu ihrer Verwendung auf und reicht diese bei einer Warteschlange ein. Danach kann die CPU weiterarbeiten, während die GPU die Befehle ausführt. Die benötigten Ressourcen müssen bis zum Ende dieser Ausführung verfügbar bleiben." +concepts.execution.ownership.description: "Der Besitz legt fest, wer ein Objekt freigibt; der GPU-Abschluss bestimmt, wann dies zulässig ist. {dispose} gibt native Ressourcen auch dann frei, wenn noch C#-Referenzen auf das Objekt bestehen. Das Einreichen von Befehlen überträgt den Besitz ihrer Ressourcen nicht an die Warteschlange." +concepts.execution.ownership.details: "Stoppen Sie beim Beenden neue Einreichungen und warten Sie auf die letzte Ressourcennutzung in allen beteiligten Warteschlangen. Geben Sie danach die Anwendungsressourcen und zuletzt den Kontext frei. Der Kontext gibt seine Warteschlangen und internen Hilfsobjekte frei; dieser Schritt muss deshalb nach Abschluss der Anwendungsarbeit erfolgen." +concepts.execution.ownership.guidance: "Verfolgen Sie während des Renderings den Abschluss aller Zugriffe auf Daten, die überschrieben, oder Ressourcen, die ersetzt werden sollen. Warten Sie auf diese Zugriffe, bevor Sie den betreffenden Speicher ändern oder freigeben. Wie Ansichten und ihre zugrunde liegenden Ressourcen in dieses Lebensdauermodell passen, beschreibt {link}." concepts.execution.ownership.guidance.link: Ressourcenverwaltung concepts.execution.ownership.table.applicationResources.object: Von der Anwendung erstellte Ressourcen concepts.execution.ownership.table.applicationResources.ownership: Die Anwendung gibt sie nach ihrer letzten GPU-Verwendung frei. concepts.execution.ownership.table.commandBuffers.object: Geliehene Befehlspuffer concepts.execution.ownership.table.commandBuffers.ownership: Die Warteschlange verwaltet und recycelt sie. concepts.execution.ownership.table.headings.object: Objekt -concepts.execution.ownership.table.headings.ownership: Wer gibt es frei? -concepts.execution.ownership.table.queues.object: Kontext-Warteschlangen und deren Zeitleisten +concepts.execution.ownership.table.headings.ownership: "Verantwortung für die Freigabe" +concepts.execution.ownership.table.queues.object: "Kontextwarteschlangen und ihre Timelines" concepts.execution.ownership.table.queues.ownership: Der Kontext und die Warteschlangen verwalten sie. concepts.execution.ownership.table.swapChainDrawable.ownership: Die Swapchain verwaltet sie. -concepts.execution.ownership.title: Besitz von der GPU-Fertigstellung trennen -concepts.execution.pipelines.description: Eine Grafikpipeline kombiniert Shader, das Scheitelpunkteingabelayout, die Regel für das Zusammensetzen von Scheitelpunkten zu Primitiven, Attachment-Formate und den Renderzustand. Legen Sie sie fest, bevor Sie Scheitelpunkt-, Index- oder Konstantendaten binden und Zeichenbefehle ausgeben. Ihre Attachment-Formate und die Sample-Anzahl müssen mit den Attachments des Renderpasses übereinstimmen. -concepts.execution.pipelines.details: Eine Compute-Pipeline stellt den Shader-Einstiegspunkt für einen Dispatch bereit, der Gruppen von GPU-Threads startet. Legen Sie sie und ihre Konstanten vor dem Dispatching fest. Compute-Dispatches gehören außerhalb von Grafik-Renderpässen. Das Ändern der Pipeline ändert die Art und Weise, wie nachfolgende Befehle ihre Eingaben interpretieren; binden Sie die für die ausgewählte Pipeline erforderlichen Daten vor deren Verwendung. -concepts.execution.pipelines.guidance: Der {link} zeigt die vollständige Grafiksequenz. Das {detail} zeichnet einen Dispatch gefolgt von einem Grafikpass auf, der das Ergebnis anzeigt. +concepts.execution.ownership.title: "Besitz und Lebensdauer" +concepts.execution.pipelines.description: "Eine Grafikpipeline legt Shader, Vertex-Eingabelayout, Primitivzusammensetzung, Attachment-Formate und Renderzustand für Zeichenbefehle fest. Wählen Sie die Pipeline, bevor Sie Vertex-, Index- oder Konstantendaten binden. Attachment-Formate und Sample-Anzahl müssen mit dem Renderpass übereinstimmen." +concepts.execution.pipelines.details: "Eine Compute-Pipeline wählt den Shader-Einstiegspunkt für einen Dispatch. Binden Sie Pipeline und Konstanten vor dem Dispatch, außerhalb eines Grafik-Renderpasses." +concepts.execution.pipelines.guidance: "Der {link} zeigt die Grafiksequenz. Das {detail} ergänzt einen Compute-Dispatch vor dem Grafikpass, der dessen Ausgabe darstellt." concepts.execution.pipelines.guidance.detail: Compute-Beispiel concepts.execution.pipelines.guidance.link: Render-Callback des Dreiecks -concepts.execution.pipelines.title: Eine Pipeline bestimmt, wie Befehle Daten interpretieren -concepts.execution.queues.description: Beginnen Sie mit {graphicsQueue}, wenn ein Frame Zeichnen, Compute und Kopiervorgänge kombiniert. Wenn abhängige Arbeiten auf einer einzigen Warteschlange verbleiben, lässt sich deren Reihenfolge leichter nachvollziehen. -concepts.execution.queues.details: Eine Warteschlange nimmt Batches von Befehlen zur Ausführung entgegen. Getrennte Warteschlangen entsprechen nicht zwangsläufig getrennten Hardware-Engines, sodass ihre Arbeiten möglicherweise nicht gleichzeitig ausgeführt werden. Verwenden Sie eine andere Warteschlange, wenn die Arbeitslast von Überlappung profitieren kann, und fügen Sie eine explizite Abhängigkeit hinzu, wenn eine Warteschlange die Ergebnisse einer anderen Warteschlange verbraucht. -concepts.execution.queues.guidance: Wenn spätere Befehle von früheren Schreibvorgängen abhängen, muss die Anwendung auch sicherstellen, dass diese Schreibvorgänge für die späteren Befehle verfügbar sind. Das Übermitteln beider Befehlspuffer an dieselbe Warteschlange stellt nicht automatisch jede solche Abhängigkeit her. Befehle können unterschiedliche GPU-Stufen verwenden, und spätere Zugriffe erfordern möglicherweise eine Barriere oder einen Texturübergang. {link} erläutert den Unterschied zwischen Übermittlungsreihenfolge und Ressourcensichtbarkeit. +concepts.execution.pipelines.title: "Pipeline-Zustand" +concepts.execution.queues.description: "{graphicsQueue} ist der übliche Ausgangspunkt für Frames mit Zeichnen, Berechnungen und Kopien. Abhängige Operationen auf einer Warteschlange lassen sich einfacher anordnen." +concepts.execution.queues.details: "Mit getrennten Warteschlangen lassen sich unabhängige Aufgaben getrennt einreichen. Daraus folgt jedoch nicht, dass ihnen unabhängige Hardwareeinheiten zugeordnet sind. Zusätzliche Warteschlangen sind sinnvoll, wenn Aufgaben von einer überlappenden Ausführung profitieren. Verwendet eine Warteschlange Daten aus einer anderen, benötigen ihre Einreichungen eine explizite Abhängigkeit." +concepts.execution.queues.guidance: "Auch innerhalb einer Warteschlange können abhängige Operationen Barrieren oder Texturübergänge benötigen, damit spätere Zugriffe die Ergebnisse früherer Schreibvorgänge sehen. Diese Speicherabhängigkeiten sind von der Einreichungsreihenfolge zu unterscheiden. Wie sie angegeben werden, erläutert {link}." concepts.execution.queues.guidance.link: Synchronisation concepts.execution.queues.table.computeQueue.workToRecord: Compute-Dispatches und kompatible Transferarbeiten, ohne Grafik-Renderpässe. -concepts.execution.queues.table.graphicsQueue.workToRecord: Renderpässe und Zeichnen sowie vom Frame verwendete Compute- und Transferoperationen. +concepts.execution.queues.table.graphicsQueue.workToRecord: "Renderpässe, Zeichenbefehle sowie Compute- und Transferoperationen." concepts.execution.queues.table.headings.queue: Warteschlange -concepts.execution.queues.table.headings.workToRecord: Aufzuzeichnende Arbeit +concepts.execution.queues.table.headings.workToRecord: "Unterstützte Operationen" concepts.execution.queues.table.transferQueue.workToRecord: Upload-, Download- und Kopierarbeiten, ohne Zeichnen oder Compute-Dispatches. -concepts.execution.queues.title: Wählen Sie eine Warteschlange für die auszuführende Arbeit -concepts.execution.recording.context: Die Warteschlange fragt die Fertigstellung ab und recycelt fertige Befehlspuffer. Rufen Sie {queueCommandBuffer} für jede neue Aufzeichnung auf; dies kann eine recycelte Instanz zurückgeben. Geben Sie einen geliehenen Befehlspuffer nicht frei, reichen Sie ihn nicht zweimal ein und zeichnen Sie nach dem Einreichen nicht weiter darin auf. Zeichnen Sie einen bestimmten Befehlspuffer jeweils nur von einem Thread aus auf; die interne Sperre der Warteschlange schützt nicht vor gleichzeitigen Bearbeitungen eines Befehlspuffers. -concepts.execution.recording.description: "{queueCommandBuffer} gibt einen {commandBuffer} zurück, dessen Aufzeichnung bereits begonnen hat. Zeichnen Sie die Befehle und deren Abhängigkeiten auf und rufen Sie dann einmal {submit} auf. Das Einreichen beendet die Aufzeichnung und gibt einen {timelineValue} zurück, der einen Fertigstellungspunkt auf dieser Warteschlange identifiziert." -concepts.execution.recording.details: "Nachdem beispielsweise ein Frame in {commandBuffer} aufgezeichnet wurde, reicht das Dreieck diesen ein und wartet auf die Fertigstellung mit:" -concepts.execution.recording.guidance: "{submit} plant die Arbeit ein; {wait} hindert die CPU daran fortzufahren, bis diese Übermittlung abgeschlossen ist. Das Aufzeichnen eines Zeichenbefehls, das Beenden eines Renderpasses und das Einreichen eines Befehlspuffers sind getrennte Operationen. Weder das Aufzeichnen des Zeichenbefehls noch das Beenden des Passes wartet auf die GPU." -concepts.execution.recording.title: Aufzeichnen führt Befehle nicht aus +concepts.execution.queues.title: "Wahl der Warteschlange" +concepts.execution.recording.context: "Die Warteschlange nimmt abgeschlossene Befehlspuffer zur Wiederverwendung zurück. Fordern Sie für jede Aufzeichnung mit {queueCommandBuffer} einen Puffer an, zeichnen Sie jeweils nur von einem Thread aus auf und reichen Sie den Puffer einmal ein. Nach der Einreichung übernimmt die Warteschlange seine Verwaltung; ändern Sie ihn nicht mehr, reichen Sie ihn nicht erneut ein und geben Sie ihn nicht selbst frei." +concepts.execution.recording.description: "{queueCommandBuffer} liefert einen {commandBuffer} mit bereits begonnener Aufzeichnung. Zeichnen Sie die Operationen und ihre Abhängigkeiten auf und rufen Sie anschließend einmal {submit} auf. Dadurch endet die Aufzeichnung; der zurückgegebene {timelineValue} bezeichnet den Abschlusspunkt in dieser Warteschlange." +concepts.execution.recording.details: "Nach der Aufzeichnung eines Frames in {commandBuffer} reicht das Dreieck-Tutorial die Befehle ein und wartet:" +concepts.execution.recording.guidance: "Die Aufzeichnung legt die Befehlsfolge fest; {submit} plant deren Ausführung ein. Ein anschließender Aufruf von {wait} blockiert den CPU-Thread bis zum Abschluss der Einreichung. Im Dreieck-Tutorial bleibt der Frame-Ablauf dadurch übersichtlich: Ein Frame ist abgeschlossen, bevor der nächste beginnt." +concepts.execution.recording.title: "Aufzeichnung und Einreichung" concepts.execution.title: Ausführungsmodell -concepts.platforms.description: Wählen Sie, ob Ihre Anwendung das native Fenster und die Frame-Schleife selbst besitzt oder ein UI-Rendering-Steuerelement verwendet. Diese Wahl bestimmt, wer die Ausgabetextur bezieht, Befehle einreicht und das Ergebnis präsentiert. Die Ausgabetextur ist die Textur, die als Ausgabe des aktuellen Frames dient. Offscreen-Grafik- und Compute-Arbeiten benötigen weder ein Fenster noch eine Swapchain. -concepts.platforms.frame.context: Fügen Sie Ihre Pipeline-Bindungen und Zeichenbefehle innerhalb dieses Passes hinzu. Beenden Sie den Pass vor der Rückgabe. Reichen Sie den bereitgestellten Befehlspuffer nicht unabhängig ein, präsentieren Sie nicht selbst und geben Sie weder den Befehlspuffer noch die Ausgabetextur frei. Wenn Ihr Handler die Ausgabetextur in einem anderen Layout verwendet, überführen Sie sie für den abschließenden Übergang des Steuerelements zurück in {colorAttachment}. -concepts.platforms.frame.description: Die Integrationen implementieren {iZenithView}. Die Anwendung stellt ihren {graphicsContext} bereit, aktualisiert Szenendaten in {updateRequested} und zeichnet das Rendering in {renderRequested} unter Verwendung von {renderEventArgs} auf. -concepts.platforms.frame.details: "Das Steuerelement steuert den Ablauf eines Frames. Es bezieht die Ausgabetextur und den Befehlspuffer, überführt die Ausgabetextur in {colorAttachment}, ruft die Handler auf und übernimmt dann die für das Framework erforderliche Einreichung und Präsentation." -concepts.platforms.frame.guidance: "Für ein initialisiertes {iZenithView} namens {view}, dem ein Kontext zugewiesen ist, zeichnet dieser Handler einen vollständigen Löschpass auf. Er erfordert {usingZenithNET}:" -concepts.platforms.frame.notes: Die Steuerelemente gehen zu Beginn jedes Frames von {undefined} aus, sodass Anwendungen sich nicht darauf verlassen können, dass vorherige Inhalte der Ausgabetextur erhalten bleiben. Löschen oder rendern Sie das erforderliche Bild in jedem Frame. Halten Sie persistente Akkumulationen oder zwischengespeichertes Rendering in einer anwendungseigenen Textur und zeigen Sie diese Textur über die Ansicht an. -concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat} liefert das Standardfarbformat der Integrationen. Überprüfen Sie die tatsächliche Ausgabetextur des Ereignisses beim Abgleich von Attachment-Formaten, Sample-Anzahlen und Abmessungen." -concepts.platforms.frame.title: In den von einem UI-Steuerelement bereitgestellten Frame aufzeichnen -concepts.platforms.integration.context: WinForms, WPF und der Windows-WinUI-Pfad erfordern Windows. MAUI-Anwendungen benötigen die Arbeitslast ihrer Zielplattform und müssen den Steuerelement-Handler mit {useZenithView} registrieren; siehe {extensionsCs}. Sowohl die Framework-Unterstützung als auch die Backend-Unterstützung müssen erfüllt sein. -concepts.platforms.integration.description: "Die Steuerelemente teilen sich die Ereignisschnittstelle, präsentieren jedoch nicht alle auf dieselbe Weise:" -concepts.platforms.integration.details: Bitmap-Rücklesen kopiert gerenderte Pixel in den CPU-Speicher, bevor die Benutzeroberfläche sie anzeigt. Die Interoperabilität über geteilte Texturen vermeidet dieses Rücklesen, kann jedoch weiterhin GPU-Kopien und Synchronisation erfordern. Die gemeinsame Schnittstelle {renderRequested} bedeutet daher nicht identische Präsentationskosten oder native Interop-Anforderungen. -concepts.platforms.integration.guidance: "Verwenden Sie das Paket für das Framework der Anwendung; zum Beispiel:" +concepts.platforms.description: "Die Präsentation übernimmt entweder die Anwendung oder ein UI-Steuerelement. Damit steht fest, wer die Ausgabetextur des Frames abruft, Befehle aufzeichnet und einreicht und das Ergebnis präsentiert. Diese Ausgabetextur heißt Drawable." +concepts.platforms.frame.context: "Zeichnen Sie Pipeline-Bindungen und Zeichenbefehle innerhalb des Passes auf und beenden Sie ihn, bevor der Handler zurückkehrt. Das Steuerelement reicht die Befehle ein und präsentiert das Ergebnis. Der Handler darf weder den Befehlspuffer einreichen noch eines der beiden bereitgestellten Objekte freigeben. Ändert er das Texturlayout, muss er vor seiner Rückkehr {colorAttachment} wiederherstellen, damit das Steuerelement den abschließenden Übergang ausführen kann." +concepts.platforms.frame.description: "Die Steuerelemente implementieren {iZenithView}. Die Anwendung weist {graphicsContext} zu, aktualisiert die Szene in {updateRequested} und zeichnet in {renderRequested} anhand der übergebenen {renderEventArgs} auf." +concepts.platforms.frame.details: "Für jeden Frame bezieht das Steuerelement eine Ausgabetextur und einen Befehlspuffer, überführt die Textur nach {colorAttachment} und ruft die Update- und Render-Handler auf. Anschließend reicht es die aufgezeichneten Befehle ein und zeigt das Bild über den Präsentationsmechanismus des Frameworks an." +concepts.platforms.frame.guidance: "Ergänzen Sie {usingZenithNET} in der Datei. Für ein initialisiertes {iZenithView} namens {view} mit zugewiesenem Grafikkontext registrieren Sie diesen Handler, der die Ausgabetextur mit einer Farbe füllt:" +concepts.platforms.frame.notes: "Der anfängliche Übergang verwendet {undefined} und erlaubt damit, den bisherigen Bildinhalt zu verwerfen. Füllen oder zeichnen Sie deshalb in jedem Frame das gesamte Bild neu. Speichern Sie akkumulierte oder zwischengespeicherte Ergebnisse in einer anwendungseigenen Textur und zeichnen Sie diese anschließend in die Ausgabetextur des Steuerelements." +concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat} liefert das Standardfarbformat dieser Integrationen." +concepts.platforms.frame.title: "Rendering über UI-Steuerelemente" +concepts.platforms.integration.context: "WinForms, WPF und die Windows-Integration von WinUI laufen unter Windows. Installieren Sie für MAUI die Workload der Zielplattform und registrieren Sie den Steuerelement-Handler mit {useZenithView}, wie in {extensionsCs} gezeigt." +concepts.platforms.integration.description: "Die Ereignisschnittstelle ist gemeinsam, der Präsentationsmechanismus hängt jedoch vom Framework ab:" +concepts.platforms.integration.details: "Die Implementierungen unterscheiden sich darin, wie das GPU-Bild in die Oberfläche gelangt. Beim Bitmap-Rücklesen werden die Pixel vor der Anzeige in CPU-Speicher kopiert. Interop über gemeinsam genutzte Texturen vermeidet diese CPU-Kopie, kann aber weiterhin GPU-Kopien und Synchronisation erfordern. Berücksichtigen Sie bei der Wahl der Integration neben dem gemeinsamen Ereignis {renderRequested} auch diesen Präsentationsweg." +concepts.platforms.integration.guidance: "Fügen Sie das Integrationspaket für Ihr UI-Framework über NuGet hinzu. Für Avalonia verwenden Sie {avaloniaPackage}." concepts.platforms.integration.table.avalonia.integration: Avalonia -concepts.platforms.integration.table.avalonia.presentation: Rendert in eine Textur und lädt Pixel in eine {writeableBitmap} herunter. Siehe {zenithViewCs} und {surfaceCs}. +concepts.platforms.integration.table.avalonia.presentation: "Rendert in eine Textur und liest die Pixel in {writeableBitmap} zurück. Implementierung: {zenithViewCs} und {surfaceCs}." concepts.platforms.integration.table.headings.integration: Integration -concepts.platforms.integration.table.headings.presentation: Wie das Bild die Benutzeroberfläche erreicht +concepts.platforms.integration.table.headings.presentation: "Präsentationsmechanismus" concepts.platforms.integration.table.maui.integration: .NET MAUI -concepts.platforms.integration.table.maui.presentation: Verwendet native Oberflächen unter Android, iOS und Mac Catalyst sowie Komposition über geteilte Texturen unter Windows. Siehe die {link}. +concepts.platforms.integration.table.maui.presentation: "Verwendet native Oberflächen unter Android, iOS und Mac Catalyst sowie Komposition über gemeinsam genutzte Texturen unter Windows. Siehe die {link}." concepts.platforms.integration.table.maui.presentation.link: Plattformimplementierungen concepts.platforms.integration.table.uno.integration: Uno-Pfad -concepts.platforms.integration.table.uno.presentation: Lädt Pixel in eine {writeableBitmap} herunter. Siehe {zenithViewUnoCs}. +concepts.platforms.integration.table.uno.presentation: "Liest Pixel in {writeableBitmap} zurück. Implementierung: {zenithViewUnoCs}." concepts.platforms.integration.table.winForms.integration: WinForms -concepts.platforms.integration.table.winForms.presentation: Erstellt eine Zenith.NET-Swapchain für das {hWND} des Steuerelements. Siehe {zenithViewCs}. +concepts.platforms.integration.table.winForms.presentation: "Erstellt eine Zenith.NET-Swapchain für das Fensterhandle {hWND} des Steuerelements. Implementierung: {zenithViewCs}." concepts.platforms.integration.table.winUI.integration: WinUI unter Windows -concepts.platforms.integration.table.winUI.presentation: Rendert in eine importierte geteilte Direct3D 11-Textur und kopiert dann in eine an {swapChainPanel} angebundene Kompositions-Swapchain. Siehe {zenithViewWinUICs}. +concepts.platforms.integration.table.winUI.presentation: "Rendert in eine importierte, gemeinsam genutzte Direct3D 11-Textur und kopiert das Ergebnis in eine an {swapChainPanel} angebundene Kompositions-Swapchain. Siehe {zenithViewWinUICs}." concepts.platforms.integration.table.wpf.integration: WPF -concepts.platforms.integration.table.wpf.presentation: Importiert eine geteilte Direct3D 11-Textur und kopiert dann über Direct3D-Interop in eine von {d3DImage} angezeigte Oberfläche. Siehe {surfaceCs}. -concepts.platforms.integration.title: Sowohl den Präsentationspfad als auch das Framework auswählen -concepts.platforms.lifecycle.context: Verwenden Sie bei einer UI-Ansicht die Eigenschaften {descWidth}, {descHeight}, {descFormat} und {descSampleCount} der Ausgabetextur des Ereignisses, wenn Sie passende Rendering-Ressourcen erstellen. Das Steuerelement bestimmt die Auflösung dieser Ausgabetextur; gehen Sie nicht davon aus, dass seine logischen Abmessungen oder die Anzeigeskalierung stets den Texturabmessungen entsprechen. -concepts.platforms.lifecycle.description: Übergeben Sie bei einer nativen Swapchain Framebuffer-Abmessungen in Pixeln. In logischen Einheiten ausgedrückte Fenstergrößen können abweichen, wenn die Anzeigeskalierung aktiviert ist. Überspringen Sie Framebuffer der Größe null, passen Sie die Größe der Swapchain an, wenn sich ihre Pixelgröße ändert, und fordern Sie {swapChainDrawable} für jeden Frame an. Die Ausgabetextur gehört der Swapchain und kann sich nach der Präsentation oder Größenänderung ändern. -concepts.platforms.lifecycle.details: "{swapChainResize} ändert die Abmessungen der vorhandenen Oberfläche. {swapChainRefresh} ersetzt die Oberflächenbeschreibung einschließlich ihrer nativen Handles. Schließen Sie vor beiden Operationen ausstehende Verwendungen der betroffenen Ressourcen ab. Geben Sie die Swapchain frei, bevor Sie ihr natives Präsentationsziel zerstören." -concepts.platforms.lifecycle.guidance: "Erstellen Sie anwendungseigene Tiefen- oder Offscreen-Texturen, deren Größe dem Fenster folgt, neu und aktualisieren Sie Konstanten, die ihre Handles enthalten. Eine Pipeline kann bei einer Größenänderung erhalten bleiben, wenn ihre Attachment-Formate und die Sample-Anzahl kompatibel bleiben. Der {link} behält seine Pipeline bei, während er seine Tiefentextur ersetzt." +concepts.platforms.integration.table.wpf.presentation: "Importiert eine gemeinsam genutzte Direct3D 11-Textur und kopiert ihren Inhalt über Direct3D-Interop in eine von {d3DImage} angezeigte Oberfläche. Siehe {surfaceCs}." +concepts.platforms.integration.title: "Framework und Präsentationspfad" +concepts.platforms.lifecycle.context: "Verwenden Sie {descWidth}, {descHeight}, {descFormat} und {descSampleCount} der im Render-Ereignis bereitgestellten Ausgabetextur, um passende Attachments zu erstellen. Diese Textur liefert die tatsächlichen Maße des Renderziels. Richten Sie sich nach diesen Maßen, statt sie aus der Layoutgröße des Steuerelements oder der Anzeigeskalierung zu berechnen." +concepts.platforms.lifecycle.description: "Die Swapchain verwendet Breite und Höhe des Framebuffers in Pixeln. Bei Anzeigeskalierung können sie von den logischen Fenstermaßen abweichen. Verschieben Sie Rendering und Swapchain-Größenanpassung, solange eine Abmessung null ist. Beziehen Sie {swapChainDrawable} für jeden Frame neu: Diese Textur gehört der Swapchain und kann nach Präsentation oder Größenänderung ersetzt werden." +concepts.platforms.lifecycle.details: "Ändern sich die Framebuffer-Maße, warten Sie vor {swapChainResize} auf alle noch laufenden GPU-Zugriffe auf die alten Bilder. Soll das native Präsentationsziel ersetzt werden, übergeben Sie nach Abschluss dieser Zugriffe seine neue Beschreibung und Handles an {swapChainRefresh}. Geben Sie beim Beenden die Swapchain vor ihrem nativen Präsentationsziel frei." +concepts.platforms.lifecycle.guidance: "Richten sich anwendungseigene Tiefen- oder Offscreen-Texturen nach der Fenstergröße, erstellen Sie sie bei einer Größenänderung neu und aktualisieren Sie Konstanten mit ihren Handles. Die Pipeline bleibt verwendbar, solange Attachment-Formate und Sample-Anzahlen weiterhin übereinstimmen. Der {link} zeigt, wie angepasste Texturen und eine wiederverwendete Pipeline zusammenarbeiten." concepts.platforms.lifecycle.guidance.link: Renderer des rotierenden Würfels -concepts.platforms.lifecycle.title: Größe und Lebensdauer der Ausgabetextur beim Host belassen -concepts.platforms.ownership.description: Die Anwendung besitzt den von ihr zugewiesenen Kontext und die Ressourcen, die sie für das Rendering erstellt. Das Steuerelement besitzt seine eigenen Präsentationsressourcen. Eine Änderung der Eigenschaft {graphicsContext} der Ansicht veranlasst den Scheduler, die Ressourcen des Steuerelements neu zu erstellen; die Pipelines, Puffer oder Texturen der Anwendung werden für den neuen Kontext nicht neu erstellt. -concepts.platforms.ownership.details: Stimmen Sie den Ressourcenersatz mit dem Frame-Lebenszyklus der Ansicht ab. Stoppen Sie die Frame-Aktivität der Ansicht und schließen Sie ausstehende GPU-Verwendungen ab, bevor Sie Anwendungsressourcen oder den zugewiesenen Kontext freigeben. Das Entfernen einer Ansicht überträgt den Kontextbesitz nicht auf das Steuerelement. -concepts.platforms.ownership.guidance: Der gemeinsame {frameSchedulerCs} verteilt die Frame-Arbeit über den UI-Dispatcher der Ansicht. Halten Sie Frame-Handler auf das Aktualisieren und Aufzeichnen des Frames fokussiert; langwierige CPU-Arbeiten dort verzögern auch die Benutzeroberfläche. -concepts.platforms.ownership.title: Anwendungsressourcen außerhalb des Besitzes des Steuerelements halten -concepts.platforms.surface.context: Die Unterstützung eines Betriebssystems durch eine Fensterbibliothek oder ein UI-Framework garantiert nicht, dass das ausgewählte GPU-Backend dort verfügbar ist. Gerätefunktionen, Treiber und native Oberflächenunterstützung müssen dennoch zusammenpassen. Überprüfen Sie optionales Raytracing und Mesh-Shading über {contextCapabilities}, bevor Sie diese Arbeitslasten erstellen. -concepts.platforms.surface.description: Das {link} verwendet Silk.NET, um ein Fenster zu erstellen und Ereignisse zu verarbeiten. Zenith.NET verbindet sich mit diesem Fenster über eine {surface}-Beschreibung und eine {swapChain}. Eine Oberfläche enthält native Handles und Abmessungen; das Erstellen der Beschreibung erstellt oder besitzt das Betriebssystemfenster nicht. -concepts.platforms.surface.description.link: Dreieck -concepts.platforms.surface.details: "Das Handle muss zum ausgewählten Backend passen:" -concepts.platforms.surface.guidance: Die Datei {appCs} des Tutorials zeigt die Auswahlmöglichkeiten für Windows, macOS und X11. Ihr Linux-Host liefert Xlib-Handles; die Verwendung in einer Wayland-Sitzung erfordert XWayland. Eine native Wayland-Anwendung würde andere Handles über {surfaceWayland} bereitstellen. +concepts.platforms.lifecycle.title: "Swapchain-Abmessungen und Lebensdauer" +concepts.platforms.ownership.description: "Die Anwendung besitzt den zugewiesenen Kontext und ihre Rendering-Ressourcen, das Steuerelement seine Präsentationsressourcen. Ändert sich {graphicsContext} der Ansicht, erstellt der Scheduler die Steuerelement-Ressourcen für den neuen Kontext neu. Auch die Anwendung muss ihre Pipelines, Puffer und Texturen für diesen Kontext neu erstellen." +concepts.platforms.ownership.details: "Halten Sie vor dem Ersetzen von Rendering-Ressourcen die Frame-Verarbeitung der Ansicht an und warten Sie auf die GPU-Arbeit, die diese Ressourcen verwendet. Erst danach dürfen die alten Ressourcen oder der Kontext freigegeben werden. Auch beim Entfernen der Ansicht bleibt die Anwendung für die Freigabe des zugewiesenen Kontexts verantwortlich." +concepts.platforms.ownership.guidance: "Der gemeinsame {frameSchedulerCs} führt die Frame-Handler über den UI-Dispatcher der Ansicht aus. Beschränken Sie diese Handler auf Szenenaktualisierung und Befehlsaufzeichnung; aufwendige CPU-Arbeit verzögert dort auch die Benutzeroberfläche." +concepts.platforms.ownership.title: "Verantwortung von Anwendung und Steuerelement" +concepts.platforms.surface.description: "Das {link} verwendet Silk.NET für Fenstererstellung und Ereignisverarbeitung. Zenith.NET erhält die nativen Fensterhandles und Abmessungen in einer {surface}-Beschreibung und erstellt damit eine {swapChain}. Für das Betriebssystemfenster bleibt die Anwendung verantwortlich." +concepts.platforms.surface.description.link: "Dreieck-Tutorial" +concepts.platforms.surface.details: "Die nativen Handles müssen zum Backend passen:" +concepts.platforms.surface.guidance: "Der Beispielhost in {appCs} unterstützt Windows, macOS und X11. Unter Linux liefert sein Fenster Xlib-Handles; eine Wayland-Sitzung benötigt deshalb XWayland. Eine native Wayland-Anwendung übergibt Display- und Surface-Handles über {surfaceWayland}." concepts.platforms.surface.table.android.backend: Vulkan unter Android. concepts.platforms.surface.table.apple.backend: Metal auf Apple-Plattformen. -concepts.platforms.surface.table.headings.backend: Backend-Pfad +concepts.platforms.surface.table.headings.backend: "Backend und Plattform" concepts.platforms.surface.table.headings.factory: Oberflächen-Factory concepts.platforms.surface.table.headings.handles: Vom Host bereitgestellte Handles concepts.platforms.surface.table.wayland.backend: Vulkan mit einem nativen Wayland-Host. @@ -94,13 +93,13 @@ concepts.platforms.surface.table.wayland.handles: Wayland-Display und -Surface concepts.platforms.surface.table.win32.backend: DirectX 12 oder Vulkan unter Windows. concepts.platforms.surface.table.xlib.backend: Vulkan unter Linux mit X11 oder XWayland. concepts.platforms.surface.table.xlib.handles: X11-Display und -Fenster -concepts.platforms.surface.title: Eine native Oberfläche bereitstellen, wenn die Anwendung die Präsentation besitzt +concepts.platforms.surface.title: "Native Präsentationsziele" concepts.platforms.title: Plattformintegration -concepts.resources.allocation.context: "Verwenden Sie zunächst über den Kontext erstellte Ressourcen, sofern Sie keinen eigenen Speicherallokator benötigen. Warten Sie bei einem Heap zunächst auf alle GPU-Arbeiten, die seine Ressourcen verwenden. Geben Sie dann die platzierten Ressourcen und erst danach den Heap selbst frei." -concepts.resources.allocation.description: "Ein {heap} stellt Speicher bereit, in dem Ressourcen an ausdrücklich gewählten Byte-Offsets platziert werden. Die Anwendung wählt diese Offsets und verfolgt, welche Bereiche belegt sind." -concepts.resources.allocation.details: "Verwenden Sie vor dem Platzieren {contextGetSizeAndAlignment} mit der genauen Puffer- oder Texturbeschreibung. Wählen Sie einen Offset, der ein Vielfaches der zurückgegebenen Ausrichtung ist, reservieren Sie die zurückgegebene Größe und halten Sie die Ressource innerhalb der Gesamtgröße des Heaps. Noch verwendete Allokationen dürfen sich nicht überlappen. Texturspeicher kann backendabhängige Auffüllung und Ausrichtung enthalten; Pixelzahl mal Bytes pro Pixel ergibt daher nicht die benötigte Allokationsgröße." -concepts.resources.allocation.guidance: "Bei platzierten Puffern muss die Speicherresidenz des Puffers mit der des Heaps übereinstimmen. Verwenden Sie GPU-only-Heaps für die hier beschriebenen gewöhnlichen GPU-Texturen. Größe und Ausrichtung sind Platzierungsanforderungen; sie garantieren nicht, dass jede Ressource auf jedem Backend in jeden Heap passt." -concepts.resources.allocation.title: Ressourcen in einem Heap platzieren, wenn Allokationskontrolle erforderlich ist +concepts.resources.allocation.context: "Platzierte Ressourcen benötigen den Speicher ihres Heaps während ihrer gesamten Lebensdauer. Warten Sie auf ihre letzte GPU-Nutzung und geben Sie anschließend zuerst die Ressourcen und dann den Heap frei." +concepts.resources.allocation.description: "Verwenden Sie einen {heap}, wenn die Anwendung die Speicherzuteilung selbst verwalten soll. Ressourcen werden darin an expliziten Byte-Offsets platziert. Die Anwendung legt diese Offsets fest und verfolgt die belegten Bereiche." +concepts.resources.allocation.details: "Rufen Sie für jede Ressource {contextGetSizeAndAlignment} mit der Puffer- oder Texturbeschreibung auf, die auch für die Erstellung verwendet wird. Reservieren Sie die zurückgegebene Größe an einem Offset, der ein Vielfaches der angegebenen Ausrichtung ist. Die Allokation muss innerhalb des Heaps liegen und darf keine andere noch aktive Allokation überlappen. Texturgrößen können backendabhängige Auffüllungen enthalten und lassen sich deshalb nicht allein aus Pixelzahl und Bytes pro Pixel berechnen." +concepts.resources.allocation.guidance: "Ein in einem Heap platzierter Puffer muss dieselbe Residenz wie der Heap angeben. Verwenden Sie für Texturen einen Heap mit GPU-only-Residenz." +concepts.resources.allocation.title: "Heap-Allokation" concepts.resources.bufferUsages.table.constant.role: Shader-Parameter, die über eine Konstantenpuffer-Bindung gelesen werden. concepts.resources.bufferUsages.table.headings.role: "Rolle" concepts.resources.bufferUsages.table.headings.usage: Nutzung @@ -111,25 +110,25 @@ concepts.resources.bufferUsages.table.storageReadOnly.role: "Pufferdaten, auf di concepts.resources.bufferUsages.table.storageReadWrite.role: "Pufferdaten, auf die über eine Shader-Bindung mit Lese- und Schreibzugriff zugegriffen wird." concepts.resources.bufferUsages.table.transferDst.role: "Zielspeicher für eine GPU-Kopie." concepts.resources.bufferUsages.table.transferSrc.role: "Quelldaten für eine GPU-Kopie." -concepts.resources.bufferUsages.table.vertex.role: Scheitelpunktattribute, die für das Zeichnen abgerufen werden. +concepts.resources.bufferUsages.table.vertex.role: "Vertexattribute, die für das Zeichnen abgerufen werden." concepts.resources.bufferUsages.title: Puffernutzungen -concepts.resources.description: "Wählen Sie die Ressourcenbeschreibung anhand der geplanten Operationen. Eine Textur, in die gerendert wird, die ein Shader abtastet und deren Daten zur CPU zurückgelesen werden, benötigt alle drei Nutzungen sowie die Synchronisation zwischen ihnen. Speicherplatzierung und Ressourcenlebensdauer sind zusätzliche Entscheidungen." -concepts.resources.memory.context: Für einen CPU-zugänglichen Puffer liefert {map} der CPU eine Adresse. Es wartet nicht darauf, dass die GPU den Zugriff auf dieselben Bytes beendet. {unmap} reicht ebenfalls keine Arbeit ein und wartet nicht auf den Abschluss. Bevor Sie CPU-beschreibbare Daten überschreiben, schließen Sie die GPU-Lesevorgänge ab, die noch den alten Inhalt benötigen. -concepts.resources.memory.description: "Ein {bufferDesc} besitzt ein {residency}-Feld. Wählen Sie es danach aus, wie CPU und GPU auf die Daten zugreifen werden:" -concepts.resources.memory.details: Residenz beschreibt den beabsichtigten CPU-Zugriff auf die Allokation. Sie bedeutet nicht, dass jedes Gerät über separaten physischen CPU- und GPU-Speicher verfügt. Das Dreieck verwendet {cpuWriteOnly}, um einen kleinen Scheitelpunktpuffer direkt zu initialisieren. Ein großes statisches Mesh kann stattdessen von reinem GPU-Speicher mit einem einmaligen Upload profitieren. -concepts.resources.memory.guidance: "{textureDesc} besitzt kein Residenzfeld. Gewöhnliche vom Kontext erstellte Texturen verwenden GPU-Speicher. Ihre öffentliche API bietet Upload- und Download-Operationen für CPU-Datenübertragungen, ohne eine direkte Mapping-Methode offenzulegen. Explizite Heaps bieten Platzierungskontrolle, wie unten beschrieben." -concepts.resources.memory.table.cpuReadOnly.cPUAccess: "Zugeordneten Speicher nach Abschluss der GPU-Kopie lesen." +concepts.resources.description: "Die Ressourcenbeschreibung legt fest, wie die Anwendung den Speicher verwenden darf. Soll eine Textur als Renderziel dienen, im Shader abgetastet und zur CPU zurückgelesen werden, benötigt sie die Nutzungsflags für alle drei Vorgänge. Die Speicherplatzierung bestimmt den CPU-Zugriff. Synchronisation und Lebensdauerverwaltung bestimmen dagegen, wann Daten zugänglich sind und Speicher freigegeben werden darf." +concepts.resources.memory.context: "Bei CPU-zugänglichen Puffern liefert {map} die Adresse zum Lesen oder Schreiben der Daten. Weder das Mapping noch {unmap} wartet auf GPU-Arbeit. Vor dem Lesen eines GPU-Ergebnisses muss die Anwendung auf den Schreibvorgang warten. Bevor sie dieselben Bytes verändert, muss sie alle noch ausstehenden GPU-Zugriffe darauf abwarten." +concepts.resources.memory.description: "Das Feld {residency} von {bufferDesc} beschreibt den vorgesehenen CPU-Zugriff auf die Allokation:" +concepts.resources.memory.details: "Die Residenz beschreibt den benötigten CPU-Zugriff, auch auf Systemen mit gemeinsamem physischem CPU- und GPU-Speicher. Das Dreieck verwendet {cpuWriteOnly}, um seinen kleinen Vertexpuffer direkt zu initialisieren. Für größere statische Geometrie kann ein Upload in GPU-only-Speicher geeigneter sein." +concepts.resources.memory.guidance: "Direkt über den Kontext erstellte Texturen verwenden GPU-Speicher. {textureDesc} enthält deshalb kein Residenzfeld; Daten werden über Uploads und Downloads mit dem CPU-Speicher ausgetauscht." +concepts.resources.memory.table.cpuReadOnly.cPUAccess: "Nur Lesen" concepts.resources.memory.table.cpuReadOnly.typicalRole: "Von der GPU erzeugte Rücklesedaten" -concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "Zugeordneten Speicher erst beschreiben, wenn frühere GPU-Lesezugriffe beendet sind." +concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "Nur Schreiben" concepts.resources.memory.table.cpuWriteOnly.typicalRole: "Von der CPU bereitgestellte oder aktualisierte Daten" -concepts.resources.memory.table.gpuOnly.cPUAccess: "Bytes über einen Upload- oder Rücklesepuffer übertragen." +concepts.resources.memory.table.gpuOnly.cPUAccess: "Keiner" concepts.resources.memory.table.gpuOnly.typicalRole: "Statische Geometrie und GPU-Arbeitsdaten" -concepts.resources.memory.table.headings.cPUAccess: CPU-Zugriff +concepts.resources.memory.table.headings.cPUAccess: "Vorgesehener CPU-Zugriff" concepts.resources.memory.table.headings.residency: Residenz concepts.resources.memory.table.headings.typicalRole: Typische Rolle -concepts.resources.memory.title: "Speicher nach dem benötigten CPU-Zugriff wählen" -concepts.resources.textureUsages.description: "Transfer-Nutzungsflags beschreiben die Richtung von GPU-Kopien. Der CPU-Zugriff ist eine eigene Entscheidung zur Speicherplatzierung, die weiter unten erläutert wird." -concepts.resources.textureUsages.details: "Die Kombination von Nutzungsflags deklariert mehrere Rollen; sie führt die Operationen weder aus noch ordnet sie deren Zugriffe. Für Texturen müssen außerdem {link} stimmen, und ihre Formate müssen die angeforderten Nutzungen auf dem ausgewählten Gerät unterstützen." +concepts.resources.memory.title: "CPU-Zugriff und Speicherplatzierung" +concepts.resources.textureUsages.description: "Transferflags geben an, ob eine Ressource als Quelle oder Ziel einer GPU-Kopie dient. Ob die CPU direkt auf ihren Speicher zugreifen kann, wird unabhängig davon durch die Speicherplatzierung festgelegt." +concepts.resources.textureUsages.details: "Nutzungsflags geben die vorgesehenen Rollen einer Textur an. Für den Wechsel zwischen diesen Rollen gelten die unter {link} beschriebenen Anforderungen. Außerdem muss das Gerät die gewählten Verwendungszwecke für das Texturformat unterstützen." concepts.resources.textureUsages.details.link: "Layout und Synchronisation" concepts.resources.textureUsages.table.colorAttachment.role: "Ein Farb-Attachment in einem Renderpass." concepts.resources.textureUsages.table.depthStencilAttachment.role: "Ein Tiefen-/Stencil-Attachment in einem Renderpass." @@ -142,362 +141,352 @@ concepts.resources.textureUsages.table.transferDst.role: "Zielbildspeicher für concepts.resources.textureUsages.table.transferSrc.role: "Quellbilddaten für eine GPU-Kopie." concepts.resources.textureUsages.title: Texturnutzungen concepts.resources.title: Ressourcenverwaltung -concepts.resources.transfers.context: Ein Download zeichnet eine GPU-Kopie in internen Rücklesespeicher auf. Die Bibliothek kopiert diese Bytes in das angegebene CPU-Ziel, wenn sie den abgeschlossenen Befehlspuffer zur Wiederverwendung zurücksetzt. Halten Sie das Ziel alloziiert und verwalteten Speicher fixiert, bis das {wait} des Übermittlungswerts zurückkehrt. -concepts.resources.transfers.description: "Ein Upload kopiert CPU-Daten zu einer GPU-Ressource; ein Download liest Ressourcendaten in den CPU-Speicher zurück. Die Methoden direkt an der Ressource schließen ihre Übertragung vor der Rückkehr ab:" -concepts.resources.transfers.details: "Diese Warteoperationen decken nur die von der jeweiligen Methode eingereichte Übertragung ab. Sie erkennen keine Abhängigkeiten von einer anderen Warteschlange, die bereits auf die Ressource liest oder schreibt. Stellen Sie diese Abhängigkeiten vor dem Aufruf der Ressourcenmethode her. Auch bei einer direkten Kopie über zugeordneten Speicher muss der Aufrufer sicherstellen, dass die betreffende GPU-Arbeit abgeschlossen ist." -concepts.resources.transfers.guidance: "Verwenden Sie {commandBufferUpload} oder {commandBufferDownload}, wenn Kopiervorgänge zusammen mit anderer Arbeit aufgezeichnet werden sollen. Die Lebensdauern ihrer Zeiger unterscheiden sich:" -concepts.resources.transfers.item: "Ein Upload kopiert die CPU-Quelldaten während des Aufrufs in einen internen Upload-Puffer, auch Staging-Speicher genannt. Der Quellzeiger muss nur für die Dauer dieses Aufrufs gültig bleiben." -concepts.resources.transfers.notes: "Bei Texturen bezeichnet der Zeilenabstand den Byte-Abstand zwischen aufeinanderfolgenden Zeilen der CPU-Daten, der Schichtabstand den Byte-Abstand zwischen aufeinanderfolgenden Tiefenschichten. Beide beschreiben nicht das interne GPU-Speicherlayout der Textur. {link} erläutert den Unterschied zwischen Abschluss und Rücklesen." +concepts.resources.transfers.context: "Ein Download kopiert GPU-Daten zunächst in einen internen Rücklesespeicher. Wenn die Bibliothek den abgeschlossenen Befehlspuffer zur Wiederverwendung zurücknimmt, kopiert sie die Daten an das bereitgestellte CPU-Ziel. Ein Aufruf von {wait} auf dem Abschlusswert der Download-Einreichung beendet beide Schritte. Bis zur Rückkehr muss der Zielspeicher erhalten und verwalteter Speicher fixiert bleiben." +concepts.resources.transfers.description: "Uploads kopieren CPU-Daten in eine GPU-Ressource, Downloads kopieren Ressourcendaten in CPU-Speicher. Die Methoden auf Puffern und Texturen schließen diesen Transfer vor ihrer Rückkehr ab:" +concepts.resources.transfers.details: "Stellen Sie vor diesen Aufrufen die erforderlichen Abhängigkeiten zu Zugriffen auf anderen Warteschlangen her. Eine Warteoperation innerhalb der Methode deckt nur ihren eigenen Transfer ab; sie stellt keine Abhängigkeit zu einer anderen Warteschlange her. Bei direktem Zugriff auf gemappten Speicher muss der Aufrufer selbst auf GPU-Zugriffe warten, die mit dem Transfer in Konflikt stehen." +concepts.resources.transfers.guidance: "Mit {commandBufferUpload} oder {commandBufferDownload} lassen sich Transfers zusammen mit anderer GPU-Arbeit aufzeichnen und einreichen. Für den Quellspeicher eines Uploads und den Zielspeicher eines Downloads gelten unterschiedliche Anforderungen an die Lebensdauer:" +concepts.resources.transfers.item: "Während des Upload-Aufrufs kopiert die Bibliothek die Quelldaten in einen temporären Upload-Speicher, den Staging-Speicher. Die GPU liest später aus diesem Zwischenspeicher. Der Quellzeiger der Anwendung wird deshalb nur bis zur Rückkehr des Aufrufs benötigt." +concepts.resources.transfers.notes: "Bei Texturtransfers bezeichnet der Zeilen-Stride den Byte-Abstand zwischen aufeinanderfolgenden Zeilen der CPU-Daten, der Schicht-Stride den Abstand zwischen Tiefenschichten. Mithilfe dieser Werte kopiert der Transfer Daten zwischen CPU-Speicher und GPU-Textur. Warum GPU-Abschluss und Bereitstellung am Download-Ziel getrennte Schritte sind, erläutert {link}." concepts.resources.transfers.notes.link: Synchronisation -concepts.resources.transfers.table.bufferDownload.transfer: Direkte CPU-Kopie für {cpuReadOnly}; andernfalls reicht es einen Download auf der Transferwarteschlange ein und wartet. -concepts.resources.transfers.table.bufferUpload.transfer: Direkte CPU-Kopie für {cpuWriteOnly}; andernfalls reicht es einen Upload auf der Transferwarteschlange ein und wartet. +concepts.resources.transfers.table.bufferDownload.transfer: "Kopiert bei {cpuReadOnly} direkt aus dem gemappten Speicher. Andernfalls reicht die Methode den Download bei der Transferwarteschlange ein und wartet auf dessen Abschluss." +concepts.resources.transfers.table.bufferUpload.transfer: "Kopiert bei {cpuWriteOnly} direkt in den gemappten Speicher. Andernfalls reicht die Methode den Upload bei der Transferwarteschlange ein und wartet auf dessen Abschluss." concepts.resources.transfers.table.headings.method: Methode -concepts.resources.transfers.table.headings.transfer: "Art der Datenübertragung" +concepts.resources.transfers.table.headings.transfer: "Übertragungsverhalten" concepts.resources.transfers.table.textureTransfers.method: "{textureUpload} / {textureDownload}" -concepts.resources.transfers.table.textureTransfers.transfer: "Verwendet die Grafikwarteschlange, überführt die gewählte Unterressource in das Kopierlayout und anschließend in das angeforderte Endlayout und wartet auf den Abschluss." -concepts.resources.transfers.title: "Zwischen sofort abgeschlossenen und aufgezeichneten Übertragungen wählen" -concepts.resources.usages.description: "{bufferUsages} und {textureUsages} sind Flag-Enums, die die vorgesehenen Rollen einer Ressource deklarieren. Sie werden {bufferDescUsages} beziehungsweise {textureDescUsages} zugewiesen. Ein Flag-Enum ermöglicht es, mehrere Member mit {value} zu kombinieren, wenn eine Ressource mehr als eine Rolle hat." -concepts.resources.usages.title: Deklarieren Sie die erforderlichen Verwendungen vor dem Erstellen einer Ressource -concepts.resources.views.description: "Eine {bufferView} beschreibt einen Pufferbereich und dessen Interpretation. Eine {textureView} wählt einen kompatiblen Texturtyp, ein Format und einen Unterressourcenbereich. Eine Ansicht teilt den zugrunde liegenden Speicher; sie kopiert keine Daten und ergänzt keine bei der Ressourcenerstellung fehlenden Nutzungen. Ihr Bereich garantiert auch nicht auf allen Backends eine Prüfung der Shader-Zugriffsgrenzen." -concepts.resources.views.details: "Verwenden Sie das Handle der Ressource für ihre Standardansicht oder erstellen Sie eine Ansicht, wenn Sie einen anderen Bereich oder eine andere kompatible Interpretation benötigen. Halten Sie C#-Referenzen auf die Ansicht und ihre zugrunde liegende Ressource, solange GPU-Arbeit darauf zugreifen kann; ein Ressourcenhandle allein hält keines der Objekte am Leben. Geben Sie beide erst nach ihrer letzten GPU-Verwendung frei. Aktualisieren Sie nach dem Ersetzen eines der Objekte auch die Konstanten mit dessen altem {link}." +concepts.resources.transfers.table.textureTransfers.transfer: "Reicht die Kopie und ihre Texturübergänge bei der Grafikwarteschlange ein und wartet auf den Abschluss. Die ausgewählte Unterressource bleibt im angeforderten abschließenden Layout." +concepts.resources.transfers.title: "Sofortige und aufgezeichnete Übertragungen" +concepts.resources.usages.description: "{bufferUsages} und {textureUsages} sind Flag-Enums für die vorgesehenen Ressourcenrollen. Sie werden {bufferDescUsages} beziehungsweise {textureDescUsages} zugewiesen. Für mehrere Rollen lassen sich die benötigten Member mit {value} kombinieren." +concepts.resources.usages.title: "Ressourcennutzungen" +concepts.resources.views.description: "Eine {bufferView} beschreibt einen Pufferbereich und die Interpretation seiner Daten. Eine {textureView} wählt einen Unterressourcenbereich sowie einen kompatiblen Texturtyp und ein passendes Format. Beide beziehen sich auf vorhandenen Speicher mit den bei seiner Erstellung angegebenen Nutzungen. Ansichtsbereiche beschreiben den Zugriff, gewährleisten aber keine einheitliche shaderseitige Bereichsprüfung über alle Backends hinweg." +concepts.resources.views.details: "Der eigene Handle einer Ressource stellt ihre Standardansicht bereit. Erstellen Sie eine separate Ansicht, wenn ein anderer Bereich oder eine andere kompatible Interpretation benötigt wird. Ansicht und zugrunde liegende Ressource müssen bis zum Ende ihrer GPU-Nutzung erhalten bleiben; ein Ressourcenhandle hält keines dieser Objekte am Leben. Wird eines ersetzt, aktualisieren Sie alle Konstanten mit dem bisherigen {link}." concepts.resources.views.details.link: "Ressourcenhandle" -concepts.resources.views.guidance: "Das {link} zeigt, wie eine Tiefentextur bei einer Größenänderung ersetzt wird. Das {detail} hält die Eingabetextur von der beschreibbaren Ausgabe getrennt. In beiden Fällen richtet sich die Lebensdauer der Ressource nach der Arbeit, die sie tatsächlich verwendet." -concepts.resources.views.guidance.detail: "Compute-Beispiel" -concepts.resources.views.guidance.link: "Beispiel des rotierenden Würfels" -concepts.resources.views.title: "Ansichten und zugrunde liegende Ressourcen gemeinsam gültig halten" -concepts.shaders.binding.context: "Im Compute-Beispiel wird {input} mit {inputTextureSampledHandle} und {output} mit {outputTextureStorageHandle} befüllt. Das typisierte {descriptorHandle} von Slang teilt dem Shader mit, wie auf die jeweilige Ressource zugegriffen werden soll:" -concepts.shaders.binding.description: "{setConstantBuffer} bindet einen Puffer und einen Byte-Offset für die Konstantendaten der aktuellen Pipeline. Es bindet vorhandenen GPU-sichtbaren Speicher; es lädt keinen C#-Wert hoch. Füllen Sie zuerst den Puffer und stellen Sie sicher, dass frühere GPU-Leser fertig sind, bevor Sie dessen Bytes überschreiben." -concepts.shaders.binding.details: "Setzen Sie die Pipeline vor ihrem Konstantenpuffer. Bei einer Compute-Arbeitslast mit bereits erstellten und hochgeladenen Ressourcen verwendet die Aufzeichnung diese Reihenfolge:" -concepts.shaders.binding.guidance: Dieses Fragment setzt einen aufzeichnenden {commandBuffer}, eine {computePipeline}, einen hochgeladenen {constantBuffer} mit der Nutzung {bufferUsagesConstant} und die Threadgruppen-Anzahlen für die Arbeitslast voraus. Offset 0 bindet den Anfang des Puffers. Wenn sich mehrere Konstantendatensätze einen Puffer teilen, muss der Start-Offset jedes Datensatzes die Bindungsausrichtung des Backends erfüllen. Diese Anforderung ist unabhängig vom Feldlayout innerhalb des Datensatzes. -concepts.shaders.binding.notes: "{resourceHandle} speichert zwei 32-Bit-Felder, seine Interpretation obliegt jedoch dem Backend. Behandeln Sie es nicht als universellen Deskriptorindex, Adresse oder Wert, der zwischen Kontexten übertragen werden kann. Ein Handle erstellt keine Ressource, fügt keine fehlende Verwendung hinzu und führt keine Synchronisation durch." -concepts.shaders.binding.reference: Behalten Sie Referenzen auf die Ressource und jede Ansicht, die zum Beziehen ihres Handles verwendet wurde, und geben Sie sie erst frei, nachdem die letzte Verwendung durch den Shader abgeschlossen ist. Wenn Sie eine Textur oder Ansicht ersetzen, aktualisieren Sie die Konstanten, die ihr altes Handle enthalten. {link} erläutert diese Lebensdauerbeziehung. +concepts.resources.views.title: "Ansichten und zugrunde liegende Ressourcen" +concepts.shaders.binding.context: "Im Compute-Beispiel erhält {input} den Wert {inputTextureSampledHandle} und {output} den Wert {outputTextureStorageHandle}. In Slang bestimmt der Typparameter von {descriptorHandle} den Ressourcenzugriff:" +concepts.shaders.binding.description: "{setConstantBuffer} wählt einen vorhandenen Puffer und den Byte-Offset, ab dem die aktuelle Pipeline ihre Konstanten liest. Laden Sie die Parameterdaten in diesen Speicher, bevor der Shader darauf zugreift. Liest frühere GPU-Arbeit noch dieselben Bytes, muss sie vor der Aktualisierung abgeschlossen sein." +concepts.shaders.binding.details: "Der Befehlspuffer, die Compute-Pipeline, der mit Daten gefüllte Konstantenpuffer und die Anzahl der Threadgruppen müssen bereits vorliegen. Zeichnen Sie den Dispatch dann in dieser Reihenfolge auf. Wählen Sie zuerst die Pipeline, da die Konstantenpufferbindung für diese Pipeline gilt:" +concepts.shaders.binding.guidance: "Hier zeichnet {commandBuffer} einen Dispatch mit {computePipeline} und den Parametern aus {constantBuffer} auf. Der Puffer benötigt die Nutzung {bufferUsagesConstant}; Offset 0 wählt seinen Anfang. Teilen sich mehrere Konstantendatensätze einen Puffer, muss jeder Anfangsoffset zusätzlich die Bindungsausrichtung des Backends erfüllen. Diese Anforderung gilt unabhängig von der Feldanordnung innerhalb des Datensatzes." +concepts.shaders.binding.notes: "{resourceHandle} enthält zwei 32-Bit-Felder, deren Interpretation vom Backend abhängt. Die Werte gelten nur innerhalb des Kontexts, in dem die Ressource erstellt wurde." +concepts.shaders.binding.reference: "Ressource und zugehörige Ansicht müssen bis zum Abschluss des letzten Shader-Zugriffs erhalten bleiben. Ihr Ersatz erfordert eine Aktualisierung der Konstanten mit alten Handles. Die Besitzregeln erläutert {link}." concepts.shaders.binding.reference.link: Ressourcenverwaltung -concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: Strukturierte Elemente des Shader-Typs {t} lesen. -concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: Strukturierte Elemente des Shader-Typs {t} lesen oder schreiben. +concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: "Lesen strukturierter Elemente des im Shader verwendeten Datentyps {t}" +concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: "Lesen und Schreiben strukturierter Elemente des im Shader verwendeten Datentyps {t}" concepts.shaders.binding.table.headings.access: Beabsichtigter Zugriff concepts.shaders.binding.table.headings.cHandle: "C#-Handle" concepts.shaders.binding.table.headings.slangFieldType: Slang-Feldtyp -concepts.shaders.binding.table.samplerHandle.access: Textur-Abtastzustand bereitstellen. -concepts.shaders.binding.table.textureSampledHandle.access: Eine Textur lesen. -concepts.shaders.binding.table.textureStorageHandle.access: Eine Speichertextur lesen oder schreiben. -concepts.shaders.binding.title: Den Konstantenpuffer und die darin beschriebenen Ressourcen binden -concepts.shaders.compilation.description: "{zenithCompiler} kompiliert einen benannten Slang-Einstiegspunkt und gibt eine {shaderDesc} zurück. Verwenden Sie {graphicsApi} des Kontexts, damit das Ergebnis auf das Backend abzielt, das den Shader erstellen wird: DXIL für DirectX 12, eine Metal-Bibliothek für Metal oder SPIR-V für Vulkan." -concepts.shaders.compilation.details: "Zum Beispiel mit einem vorhandenen {context} und dem neben der ausführbaren Datei kopierten Dreieck-Shader:" -concepts.shaders.compilation.guidance: "{vSMain} muss exakt mit dem Namen des Einstiegspunkts in der Shader-Datei übereinstimmen. Halten Sie Shader-Objekte während der Erstellung der Pipeline gültig und geben Sie sie nach der Pipeline-Erstellung frei, wie in {link} gezeigt. Führen Sie diese Initialisierung einmalig durch, anstatt für jeden Frame neu zu kompilieren." +concepts.shaders.binding.table.samplerHandle.access: "Zustand für die Texturabtastung" +concepts.shaders.binding.table.textureSampledHandle.access: "Lesen von Texturdaten" +concepts.shaders.binding.table.textureStorageHandle.access: "Lese- und Schreibzugriff auf Speichertexturen" +concepts.shaders.binding.title: "Konstantenpuffer und Ressourcenhandles" +concepts.shaders.compilation.description: "{zenithCompiler} kompiliert einen benannten Slang-Einstiegspunkt zu einer {shaderDesc}. Die Eigenschaft {graphicsApi} bestimmt das Ziel: DXIL für DirectX 12, eine Metal-Bibliothek für Metal oder SPIR-V für Vulkan." +concepts.shaders.compilation.details: "Mit einem bereits erstellten Grafikkontext namens {context} wird der Dreieck-Shader aus der Kopie neben der ausführbaren Datei kompiliert:" +concepts.shaders.compilation.guidance: "Der Einstiegspunktname {vSMain} muss mit der Deklaration in der Shader-Datei übereinstimmen. Kompilieren Sie Shader und erstellen Sie Pipelines während der Initialisierung; beim Rendering werden die Pipelines wiederverwendet. Nach Abschluss der Pipeline-Erstellung dürfen die Shader-Objekte freigegeben werden, wie im Tutorial {link} gezeigt." concepts.shaders.compilation.guidance.link: Erstes Dreieck -concepts.shaders.compilation.title: Einen Einstiegspunkt für den ausgewählten Kontext kompilieren -concepts.shaders.description: "Ein Shader empfängt von der Anwendung bereitgestellte Daten. Scheitelpunktattribute beschreiben einzelne Scheitelpunkte; Puffer enthalten Parameter oder Arrays; Ressourcen-Handles identifizieren andere Ressourcen, auf die der Shader zugreift. Die C#-Deklarationen und Slang-Deklarationen müssen darin übereinstimmen, was diese Werte bedeuten. Das bloße Übereinstimmen eines Feldnamens reicht nicht aus: Layout, Ressourcenzugriff und Bindung müssen alle übereinstimmen." -concepts.shaders.dispatch.description: "{dispatch} nimmt die Anzahl der Threadgruppen entgegen. Der Einstiegspunkt {numthreads} des Compute-Beispiels führt 16 × 16 Threads pro Gruppe aus. Teilen Sie die Bildabmessungen durch 16 und runden Sie auf, um die Gruppenanzahlen zu ermitteln. Ein 17 × 19 Bild benötigt beispielsweise 2 × 2 Gruppen. Der Shader vergleicht seine Pixelkoordinaten mit den Bildabmessungen, da die letzten Gruppen Threads außerhalb des Bildes enthalten können." -concepts.shaders.dispatch.details: Der Compiler speichert die deklarierte Gruppengröße des Einstiegspunkts in {shaderDescThreadGroupSize}; er rechnet die an {dispatch} übergebenen Pixelabmessungen nicht in Gruppenanzahlen um. Verwenden Sie {computeShaderRendererCs} mit seinem Shader für das vollständige Binde- und Dispatch-Beispiel und {link}, bevor ein anderer Pass die Ausgabe verbraucht. +concepts.shaders.compilation.title: "Shader-Kompilierung" +concepts.shaders.description: "C#- und Slang-Deklarationen müssen darin übereinstimmen, wo Werte gespeichert werden und wie der Shader darauf zugreift. Vertex-Eingabelayouts beschreiben Vertexattribute, Shader-Pufferdeklarationen beschreiben Parameter und Arrays, und Ressourcenhandles identifizieren die vom Shader verwendeten Ressourcen." +concepts.shaders.dispatch.description: "{dispatch} gibt die Anzahl der auszuführenden Threadgruppen an. Das Compute-Beispiel deklariert {numthreads}, sodass jede Gruppe 16 × 16 Threads enthält. Teilen Sie Breite und Höhe des Bildes jeweils durch 16 und runden Sie auf, um es vollständig abzudecken: Ein Bild mit 17 × 19 Pixeln benötigt 2 × 2 Gruppen. Der Shader prüft die Koordinaten jedes Threads und überspringt Positionen außerhalb des Bildes." +concepts.shaders.dispatch.details: "Die deklarierte Gruppengröße ist über {shaderDescThreadGroupSize} verfügbar und kann zur Berechnung der an {dispatch} übergebenen Gruppenanzahl dienen. {computeShaderRendererCs} zeigt die vollständige Berechnung. Für Zugriffe auf das erzeugte Bild gelten anschließend die in {link} beschriebenen Anforderungen." concepts.shaders.dispatch.details.link: Synchronisation -concepts.shaders.dispatch.title: Threadgruppen dispatchen, nicht Pixel -concepts.shaders.layout.context: "Die {link} machen ihre Offsets explizit. Diese Deklaration benötigt {systemRuntimeInteropServices} und {zenithNET} im Gültigkeitsbereich:" +concepts.shaders.dispatch.title: "Threadgruppen" +concepts.shaders.layout.context: "Die {link} zeigen diese Anordnung anhand von Bildabmessungen und zwei Texturhandles. Explizite Offsets legen den Beginn jedes Feldes fest. Die Deklaration verwendet {systemRuntimeInteropServices} und {zenithNET}:" concepts.shaders.layout.context.link: "C#-Konstanten des Compute-Beispiels" -concepts.shaders.layout.description: "Für Scheitelpunkteingaben beschreibt das {inputLayout} der Pipeline Formate, Offsets, Stride und Semantiken. Die {float3}-Position des Dreiecks gefolgt von einer {float4}-Farbe belegt 28 Bytes, wobei die Farbe bei Byte 12 liegt. {inputLayoutAdd} berechnet dieses gepackte Layout; es überprüft die C#-Struktur nicht. Wenn die C#-Felder Padding enthalten, stellen Sie ein passendes Layout bereit, anstatt davon auszugehen, dass die Felder gepackt sind." -concepts.shaders.layout.details: "Konstantenpuffer enthalten Shader-Parameter, während strukturierte Puffer Arrays von Elementen eines deklarierten Typs enthalten. Beide werden gemäß ihren Slang-Deklarationen gelesen. Sie verwenden kein {inputLayout}. Überprüfen Sie Feldoffsets und Elementgrößen für die kompilierte Shader-Repräsentation einschließlich Padding. Ein nicht verwalteter C#-Typ eignet sich zum Kopieren als Bytes, dies allein beweist jedoch nicht, dass er mit einem Shader-Typ übereinstimmt. Wenden Sie insbesondere nicht das dicht gepackte {float3}-Layout eines Scheitelpunkts auf jeden Shader-Puffer an." -concepts.shaders.layout.guidance: Ein Ressourcen-Handle ist ein kleiner Wert, der auf eine vorhandene Ressource verweist. Das Kopieren des Handles in einen Konstantenpuffer kopiert nicht den Inhalt der Ressource. -concepts.shaders.layout.notes: "Die entsprechende Deklaration in {computeShaderSlang} lautet:" -concepts.shaders.layout.reference: "Die Dimensionen belegen die ersten acht Bytes, gefolgt von zwei Acht-Byte-Ressourcen-Handles. Das C#-Beispiel reserviert insgesamt 256 Bytes. Diese Größe ist die vom Beispiel gewählte Speichergröße und keine Regel, dass alle Slang-Strukturen oder Konstanten-Nutzlasten 256 Bytes belegen müssen. Das Auffüllen der Gesamtgröße korrigiert auch kein Feld an einem falschen Offset." -concepts.shaders.layout.title: Scheitelpunkteingabe und Shader-Daten haben unterschiedliche Layout-Regeln -concepts.shaders.matrices.description: Der Compiler fordert zeilenweise Matrixspeicherung (row-major) an, bei der die Elemente jeder Zeile zusammenhängend gespeichert werden. Der {link} platziert drei {matrix4x4}-Werte an den Offsets 0, 64 und 128. Sein {detail} verwendet {mulVectorMatrix} in der Reihenfolge Modell, Ansicht und Projektion. +concepts.shaders.layout.description: "Für Vertexeingaben beschreibt {inputLayout} das Format, den Offset und die Semantik jedes Attributs sowie den Stride zwischen Vertices. Beim Dreieck folgt auf eine {float3}-Position eine {float4}-Farbe. Die Farbe beginnt am Byte-Offset 12; jeder Vertex belegt 28 Bytes. {inputLayoutAdd} berechnet diese dicht gepackte Anordnung aus den Elementformaten. Enthält die C#-Struktur Auffüllungen, müssen Offsets und Stride diese berücksichtigen." +concepts.shaders.layout.details: "Konstantenpuffer enthalten Shader-Parameter, strukturierte Puffer Arrays typisierter Elemente. Ihre Anordnung folgt den Slang-Deklarationen und nicht {inputLayout}. Stimmen Sie C#-Feldoffsets, Elementgrößen und Auffüllungen mit dem kompilierten Shader-Layout ab. Ein nicht verwalteter C#-Typ lässt sich als Bytes kopieren, doch seine Speicheranordnung entspricht nicht zwangsläufig dem Shader-Layout. Ein im Vertex dicht gepacktes {float3} kann in einem Shader-Puffer eine andere Ausrichtung benötigen." +concepts.shaders.layout.guidance: "Shader-Parameter können neben gewöhnlichen Werten auch Ressourcenhandles enthalten. Ein Handle bezeichnet bereits vorhandenen Speicher. Wird er in einen Konstantenpuffer kopiert, werden deshalb nicht die Inhalte der Ressource mitkopiert." +concepts.shaders.layout.notes: "Die zugehörige Deklaration in {computeShaderSlang} lautet:" +concepts.shaders.layout.reference: "Die beiden Abmessungen belegen die ersten acht Bytes; darauf folgen zwei Handles mit je acht Bytes. Das C#-Beispiel reserviert insgesamt 256 Bytes für den Datensatz. Die Größe anderer Datensätze ist anhand ihrer eigenen Felder sowie der benötigten Anordnung und Ausrichtung zu bestimmen." +concepts.shaders.layout.title: "Datenlayout" +concepts.shaders.matrices.description: "Der Compiler wählt zeilenweise Matrixspeicherung mit zusammenhängenden Zeilen. Der {link} speichert drei {matrix4x4}-Werte an den Byte-Offsets 0, 64 und 128. Sein {detail} führt {mulVectorMatrix} in Modell-, View- und Projektionsreihenfolge aus." concepts.shaders.matrices.description.detail: Shader concepts.shaders.matrices.description.link: Renderer des rotierenden Würfels -concepts.shaders.matrices.details: Die Speicherreihenfolge bestimmt, wie Matrixelemente den Speicher belegen; die Multiplikationsreihenfolge bestimmt die Transformation. Halten Sie beide Seiten konsistent. Das Hinzufügen einer Transposition ohne Überprüfung dieser beiden Optionen kann eine Nichtübereinstimmung verbergen, während eine andere eingeführt wird. -concepts.shaders.matrices.title: Matrixspeicherung und -multiplikation konsistent halten +concepts.shaders.matrices.details: "Die Speicherreihenfolge bestimmt die Anordnung der Matrixelemente; die Multiplikationsreihenfolge bestimmt die Transformation. C# und Slang müssen aufeinander abgestimmte Konventionen verwenden." +concepts.shaders.matrices.title: "Matrixkonventionen" concepts.shaders.title: Shader-Daten und Bindung -concepts.synchronization.backends.description: DirectX 12 und Vulkan kodieren Texturübergänge mit Layout- und Zugriffsinformationen. Metal hat keine Operation in der {transition}-Implementierung von Zenith.NET. Metal gruppiert aufgezeichnete Arbeiten in Render- und Compute-Encoder. Das Backend fügt Sichtbarkeitsbarrieren ein, wenn es diese Gruppen beendet, wodurch frühere Schreibvorgänge für spätere Arbeiten verfügbar werden. Explizite {barrier}-Aufrufe behandeln Abhängigkeiten wie aufeinanderfolgende Compute-Dispatches innerhalb desselben Encoders. -concepts.synchronization.backends.details: Dieser Unterschied ist wichtig, wenn eine Arbeitslast geändert wird. Im {link} folgt auf den Dispatch ein Grafik-Renderpass, der auch auf Metal eine Encoder-Grenze erzeugt. Zwei abhängige Compute-Dispatches erzeugen diese Grenze nicht allein durch Ändern des deklarierten Layouts der Textur. Behalten Sie die von der gemeinsamen API geforderten Übergänge bei und identifizieren Sie separat die Abhängigkeit zwischen den tatsächlichen erzeugenden und verbrauchenden Befehlen. +concepts.synchronization.backends.description: "DirectX 12 und Vulkan setzen Texturübergänge als Layout- und Zugriffsänderungen um. Für Metal führt die Implementierung von {transition} in Zenith.NET keine entsprechende Operation aus. Das Metal-Backend fasst Befehle stattdessen in Render- und Compute-Encodern zusammen und fügt beim Ende eines Encoders Sichtbarkeitsbarrieren ein. Abhängige Operationen innerhalb desselben Encoders, etwa aufeinanderfolgende Compute-Dispatches, verwenden explizite Aufrufe von {barrier}." +concepts.synchronization.backends.details: "Im {link} beendet der Beginn des Grafik-Renderpasses den Compute-Encoder und macht dessen Ausgabe für die Grafikbefehle sichtbar. Zwei aufeinanderfolgende Compute-Dispatches bleiben dagegen im selben Encoder. Ihre Abhängigkeit benötigt deshalb eine Barriere, auch wenn dazwischen ein Texturübergang aufgezeichnet wird. Portable Befehlsfolgen berücksichtigen daher sowohl Zugriffsabhängigkeiten als auch Texturlayouts." concepts.synchronization.backends.details.link: Compute-Beispiel -concepts.synchronization.backends.title: Ein Übergang ist nicht auf jedem Backend identisch -concepts.synchronization.barriers.context: "{barrierStagesAll} ist ein breiterer Gültigkeitsbereich, kein automatischer Abhängigkeitsdetektor. Wählen Sie Stufen aus, die die Arbeit tatsächlich abdecken, und verwenden Sie sie nur auf einer Warteschlange, die diese Operationen unterstützt." -concepts.synchronization.barriers.description: "Betrachten Sie zwei Compute-Dispatches: Der erste schreibt Simulationsdaten, und der zweite liest diese Daten, um den nächsten Schritt durchzuführen. Beide verwenden Speicherpuffer, sodass kein Texturlayout zu ändern ist. Fügen Sie Folgendes zwischen den Dispatches in deren Befehlspuffer ein:" -concepts.synchronization.barriers.details: Das erste Argument identifiziert die Erzeugerstufe und das zweite die Verbraucherstufe. Die Barriere stellt die entsprechende Ausführungs- und Speicherabhängigkeit auf der GPU her. Das Backend übersetzt diese Stufen in seine Ausführungs- und Speicherzugriffsregeln. Diese Barriere ändert nicht das Layout einer Textur und wartet nicht auf alle Arbeiten auf dem Gerät. -concepts.synchronization.barriers.guidance: Die {link} verwendet dieses Muster zwischen abhängigen Dispatches. Platzieren Sie eine Barriere dort, wo die Abhängigkeit auftritt. Eine Barriere, nachdem der Verbraucher bereits aufgezeichnet wurde, kann diesen Verbraucher nicht nach einem früheren Erzeuger ordnen. +concepts.synchronization.backends.title: "Backend-Verhalten" +concepts.synchronization.barriers.context: "Wählen Sie Stufen, die die relevanten Zugriffe umfassen und von der Warteschlange unterstützt werden. {barrierStagesAll} schließt alle unterstützten Stufen ein. Beschränken Sie die Auswahl, wenn die Abhängigkeit nur einen Teil davon betrifft." +concepts.synchronization.barriers.description: "Angenommen, zwei Compute-Dispatches stehen im selben Befehlspuffer: Der erste schreibt Simulationsdaten, der zweite liest sie. Eine Barriere dazwischen stellt sicher, dass der zweite Dispatch die abgeschlossenen Schreibvorgänge sieht. Bei einem Speicherpuffer genügt es, die Zugriffe zu ordnen; ein Texturlayoutübergang ist nicht erforderlich:" +concepts.synchronization.barriers.details: "Das erste Argument benennt die Stufen, die die Daten erzeugt haben; das zweite die Stufen, die sie verwenden werden. Gemeinsam beschreiben sie die benötigte Ausführungsreihenfolge und Speichersichtbarkeit zwischen den beiden Dispatches." +concepts.synchronization.barriers.guidance: "Die {link} verwendet dieses Muster zwischen Simulationsschritten. Jede Barriere steht nach dem Dispatch, der die Daten erzeugt, und vor dem Dispatch, der sie verwendet." concepts.synchronization.barriers.guidance.link: FluidTank-Simulation -concepts.synchronization.barriers.title: Abhängige Befehle mit einer Barriere ordnen -concepts.synchronization.dependencies.description: Identifizieren Sie für jede gemeinsam genutzte Ressource die Operation, die zuerst darauf zugreift, die nachfolgende Operation und ob einer der Zugriffe ein Schreibzugriff ist. Das zweimalige Lesen derselben Daten erfordert keine Ordnung zum Schutz ihres Inhalts, obwohl Layoutänderungen oder Präsentationen andere Anforderungen auferlegen können. Ein Schreibvorgang gefolgt von einem Lesevorgang, ein Lesevorgang gefolgt von einem Überschreiben oder zwei Schreibvorgänge können eine Abhängigkeit erfordern. -concepts.synchronization.dependencies.details: "Wählen Sie dann den Mechanismus dafür aus, wo diese Operationen ausgeführt werden:" -concepts.synchronization.dependencies.guidance: Diese Mechanismen hängen zusammen, sind aber nicht austauschbar. Das Einreichen von Befehlen in der richtigen Reihenfolge ersetzt nicht jede Speicherabhängigkeit. Ein Warten auf einer Warteschlange deklariert kein neues Texturlayout, und eine Befehlsbarriere wartet nicht auf dem aufrufenden CPU-Thread. -concepts.synchronization.dependencies.table.cpuAccess.mechanism: "{wait} auf dem relevanten Fertigstellungswert aufrufen." -concepts.synchronization.dependencies.table.cpuAccess.situation: Die CPU muss vor dem Zugriff auf oder der Freigabe von Daten warten -concepts.synchronization.dependencies.table.crossQueue.mechanism: Seinen {timelineValue} an das {submit} des verbrauchenden Befehlspuffers übergeben. -concepts.synchronization.dependencies.table.crossQueue.situation: Eine Übermittlung auf einer anderen Warteschlange erzeugt die Daten +concepts.synchronization.barriers.title: "Pipeline-Barrieren" +concepts.synchronization.dependencies.description: "Ermitteln Sie für jede Ressource, welche Zugriffe dieselben Daten betreffen. Sobald einer davon schreibt, muss die benötigte Reihenfolge erhalten bleiben. Zwei Lesezugriffe stehen nicht im Konflikt; Anforderungen an Texturlayout und Präsentation gelten dennoch. Auch CPU-Aktualisierungen und Ressourcenfreigaben müssen warten, bis die GPU den betroffenen Speicher nicht mehr verwendet." +concepts.synchronization.dependencies.details: "Der Mechanismus richtet sich nach dem Ausführungsort der Operationen:" +concepts.synchronization.dependencies.guidance: "Eine Aufgabe kann mehrere Mechanismen benötigen. Stammt eine Textur etwa aus einer anderen Warteschlange, sind sowohl eine Einreichungsabhängigkeit als auch das passende Layout für den nächsten Zugriff erforderlich. Die CPU muss dafür nur blockiert werden, wenn sie selbst auf die Daten zugreifen oder deren Speicher freigeben soll." +concepts.synchronization.dependencies.table.cpuAccess.mechanism: "{wait} auf dem relevanten Abschlusswert aufrufen." +concepts.synchronization.dependencies.table.cpuAccess.situation: "CPU-Zugriff oder Ressourcenfreigabe erfordert den Abschluss der GPU-Arbeit" +concepts.synchronization.dependencies.table.crossQueue.mechanism: "Den {timelineValue} der erzeugenden Einreichung an {submit} der weiterverarbeitenden Einreichung übergeben." +concepts.synchronization.dependencies.table.crossQueue.situation: "Eine Warteschlange verwendet Daten aus einer anderen Warteschlange" concepts.synchronization.dependencies.table.headings.mechanism: Mechanismus concepts.synchronization.dependencies.table.headings.situation: Situation concepts.synchronization.dependencies.table.layoutChange.mechanism: "{commandBufferTransition} mit vorherigem und folgendem Layout." concepts.synchronization.dependencies.table.layoutChange.situation: Eine Textur-Unterressource ändert ihre Verwendungsart concepts.synchronization.dependencies.table.pipelineStages.mechanism: "{commandBufferBarrier} mit den Erzeuger- und Verbraucherstufen." concepts.synchronization.dependencies.table.pipelineStages.situation: Abhängige GPU-Stufen in einem Befehlsstrom -concepts.synchronization.dependencies.title: Mit dem Erzeuger und dem Verbraucher beginnen -concepts.synchronization.description: Ein Befehl, der von einem früheren Befehl geschriebene Daten liest, hängt davon ab, dass diese Schreibvorgänge abgeschlossen und für ihn sichtbar sind. Der Schreiber ist der Erzeuger (Producer); der Leser ist der Verbraucher (Consumer). Auch die CPU benötigt einen Fertigstellungspunkt, bevor sie gemeinsame Daten liest, überschreibt oder freigibt. Zenith.NET stellt Barrieren, Texturübergänge und Zeitleisten für diese unterschiedlichen Abhängigkeiten bereit. -concepts.synchronization.layouts.context: "{undefined} bedeutet, dass die vorherigen Inhalte nicht beibehalten werden müssen. Es eignet sich für ein neues Bild oder ein Attachment, das vollständig gelöscht wird. Es ist keine Möglichkeit, die Nachverfolgung des Layouts eines Bildes zu vermeiden, dessen Inhalte geladen, abgetastet oder akkumuliert werden sollen." -concepts.synchronization.layouts.description: "Verwendungs-Flags beschreiben, welche Rollen eine Textur unterstützt. {textureLayout} beschreibt, wie auf eine bestimmte Unterressource für eine Operation zugegriffen wird. Eine Unterressource ist ein ausgewählter Mip-Level und Array-Layer. Das Ändern ihres Layouts bereitet diesen Zugriff vor; es konvertiert die Textur nicht in ein anderes Pixelformat. Das Compute-Beispiel schreibt beispielsweise eine Ausgabetextur im Layout {storage} und tastet sie dann in einem Grafikpass ab. Zwischen diesen Verwendungen zeichnet es Folgendes auf:" -concepts.synchronization.layouts.details: Dieses Fragment setzt voraus, dass {outputTexture} mit der Nutzung {sampledStorage} erstellt wurde und sich seine ausgewählte Unterressource im Layout {storage} befindet. {default} wählt Mip-Level 0 und Array-Layer 0 aus. Die Operation überführt nicht jeden Mip-Level oder Layer einer Textur. -concepts.synchronization.layouts.guidance: Die Anwendung stellt das vorherige Layout bereit. {transition} führt keinen für die Anwendung sichtbaren Layout-Tracker und leitet diesen Wert nicht aus früheren Befehlen ab. Verfolgen Sie das Layout überall dort nach, wo eine Ressource zwischen Rendering-Stufen übergeben wird. -concepts.synchronization.layouts.title: Das Layout jeder Textur-Unterressource nachverfolgen -concepts.synchronization.readback.description: "{isCompleted} fragt nur ab, ob die GPU-Zeitleiste einen Wert erreicht hat. Es fordert nicht selbst Befehlspuffer zurück und kopiert keine zwischengespeicherten Downloads in den Zielzeiger der Anwendung." -concepts.synchronization.readback.details: "{commandBufferDownload} zeichnet zunächst eine Kopie in den internen Rücklesespeicher auf. Beim Zurücksetzen des abgeschlossenen Befehlspuffers zur Wiederverwendung werden die Daten per CPU-Kopie an den angegebenen Zeiger übertragen. Halten Sie das Ziel gültig und verwalteten Speicher fixiert, bis {wait} für die Download-Übermittlung zurückkehrt. Erst danach dürfen Sie die Daten lesen oder den Speicher freigeben. Das Warten auf eine spätere Übermittlung einer anderen Warteschlange fragt die zuständige Warteschlange des Downloads nicht selbst ab." -concepts.synchronization.readback.guidance: Aus diesem Grund reicht das Abfragen von {isCompleted} und das sofortige Lesen eines asynchronen Download-Ziels nicht aus. {link} behandelt die direkten Kopier- und gestuften Transferpfade. +concepts.synchronization.dependencies.title: "Zugriffsabhängigkeiten" +concepts.synchronization.description: "Synchronisation legt die Reihenfolge von Zugriffen auf gemeinsam verwendete Daten fest und stellt sicher, dass spätere Operationen die benötigten Ergebnisse sehen. Bei einer Schreib-Lese-Abhängigkeit ist die schreibende Operation der Erzeuger und die lesende der Verbraucher. Barrieren und Texturübergänge koordinieren GPU-Zugriffe; Timelines verbinden Einreichungen und ermöglichen es der CPU, auf GPU-Arbeit zu warten." +concepts.synchronization.layouts.context: "Verwenden Sie {undefined} als vorheriges Layout, wenn der bestehende Inhalt verworfen werden darf, etwa bei einem neuen Bild oder einem vollständig neu gefüllten Attachment. Soll der Inhalt geladen, abgetastet oder zur Akkumulation weiterverwendet werden, ist das Layout des vorherigen Zugriffs anzugeben." +concepts.synchronization.layouts.description: "Die Nutzungsflags einer Textur geben ihre erlaubten Rollen an. {textureLayout} beschreibt den Zugriff auf eine bestimmte Unterressource zu einem bestimmten Zeitpunkt der Befehlsfolge. Diese Unterressource wird durch Mip-Level und Array-Layer bestimmt. Ändert sich der Zugriff, zeichnen Sie einen Übergang auf. Das Compute-Beispiel schreibt etwa in eine Ausgabetextur mit dem Layout {storage} und bereitet sie anschließend für die Abtastung in einem Grafikpass vor:" +concepts.synchronization.layouts.details: "{outputTexture} wurde mit {sampledStorage} erstellt; die gewählte Unterressource liegt in {storage}. {default} bezeichnet Mip-Level 0 und Array-Layer 0. Andere Level und Layer bleiben unverändert." +concepts.synchronization.layouts.guidance: "Geben Sie bei {transition} das Layout der vorherigen Unterressourcennutzung an. Die Anwendung verfolgt diesen Zustand beim Aufzeichnen der Befehle und bei der Übergabe von Texturen zwischen Rendering-Stufen." +concepts.synchronization.layouts.title: "Texturlayouts" +concepts.synchronization.readback.description: "{isCompleted} meldet den GPU-Abschluss. Bei einem aufgezeichneten Download steht danach noch ein Schritt aus: die Kopie aus dem internen Rücklesespeicher in den Zielspeicher der Anwendung." +concepts.synchronization.readback.details: "{commandBufferDownload} zeichnet die GPU-Kopie in diesen internen Speicher auf. Nach Abschluss der Einreichung führt die Bibliothek die CPU-Kopie aus, während sie den fertigen Befehlspuffer zurücknimmt. {wait} auf dem Abschlusswert der Download-Einreichung wartet auf die GPU und verarbeitet die abgeschlossenen Puffer dieser Warteschlange. Dadurch werden beide Schritte abgeschlossen. Bis zur Rückkehr muss der Zielspeicher erhalten und verwalteter Speicher fixiert bleiben." +concepts.synchronization.readback.guidance: "Allein das Abfragen von {isCompleted} führt die abschließende CPU-Kopie nicht aus. Auch das Warten auf eine andere Warteschlange nimmt die abgeschlossenen Puffer der Download-Warteschlange nicht zurück. Wann Uploads und Downloads direkt auf Speicher zugreifen oder einen Zwischenspeicher nutzen, beschreibt {link}." concepts.synchronization.readback.guidance.link: Ressourcenverwaltung -concepts.synchronization.readback.title: GPU-Fertigstellung und heruntergeladene CPU-Daten sind getrennte Schritte -concepts.synchronization.reuse.description: Für einen ersten Renderer ist ein sofortiges Warten nach jedem Frame unkompliziert. Um Arbeiten zu überlappen, weisen Sie ausstehenden Frames separate veränderliche Daten zu und behalten Sie den Fertigstellungswert der letzten Verwendung jedes Frames bei. Schließen Sie vor dem Aktualisieren eines Konstantenpuffers, dem Ersetzen einer Textur oder dem Freigeben einer Pipeline jeden ausstehenden Zugriff auf die betroffene Ressource ab. -concepts.synchronization.reuse.details: Stoppen Sie bei Größenänderungen oder beim Herunterfahren neue Verwendungen, bevor Sie auf alte warten. {swapChainResize}, Ressourcenfreigabe und Kontextfreigabe dienen nicht als allgemeine Warteoperationen für Anwendungsarbeiten. Das Dreieck kann die Größe zwischen Callbacks sicher anpassen, da jeder vorherige Frame seine Übermittlung bereits abgeschlossen hat. -concepts.synchronization.reuse.guidance: Das aktuelle {swapChainPresent} signalisiert und wartet nach seiner Präsentationsoperation ebenfalls auf der Grafikwarteschlange. Das Entfernen des expliziten Übermittlungswartens des Dreiecks stellt daher für sich allein noch keine überlappende Präsentationsschleife her. Ein Warten auf der Grafikwarteschlange sagt zudem nichts über unabhängige Arbeiten aus, die noch auf einer anderen Warteschlange laufen. -concepts.synchronization.reuse.title: Daten erst nach ihrem letzten Zugriff wiederverwenden -concepts.synchronization.timelines.context: "Bevor die CPU diese Ressourcen liest, überschreibt oder freigibt, warten Sie auf deren letzte Verwendung:" -concepts.synchronization.timelines.description: Eine Zeitleiste verfolgt die Fertigstellung auf einer Warteschlange anhand aufsteigender Werte. {submit} gibt einen {timelineValue} zurück, der diese Zeitleiste und den mit der Übermittlung verknüpften Wert enthält. Fertigstellungswerte aus verschiedenen Zeitleisten sind nicht allein anhand ihrer numerischen {value}-Felder vergleichbar. -concepts.synchronization.timelines.details: "Angenommen, {producer} und {consumer} sind bereits aufgezeichnete Befehlspuffer aus zwei Warteschlangen desselben Kontexts. Der Erzeuger schreibt Daten, die der Verbraucher verwendet. Reichen Sie sie wie folgt ein:" -concepts.synchronization.timelines.guidance: Das Übergeben des erzeugten Werts veranlasst die verbrauchende Warteschlange, auf der GPU darauf zu warten. Die CPU ruft hier nicht {producedWait} auf. Halten Sie die gemeinsam genutzten Ressourcen gültig, bis {consumed} abgeschlossen ist, und zeichnen Sie alle vom Verbraucher benötigten Texturlayoutänderungen auf. -concepts.synchronization.timelines.notes: "{wait} wartet auf diesen Zeitleistenwert und prüft dann die besitzende Warteschlange auf abgeschlossene Übermittlungen. Fertige Befehlspuffer werden zur Wiederverwendung zurückgesetzt, und ihre zwischengespeicherten Downloads werden in die bereitgestellten CPU-Ziele kopiert. {queueTimelineSignal} kann auch einen Fertigstellungspunkt nach bereits an diese Warteschlange übermittelter Arbeit einreihen. Das Aufrufen von {signal} bedeutet nicht, dass die GPU den Punkt bereits erreicht hat." -concepts.synchronization.timelines.title: Eine Zeitleiste für Fertigstellung und Warteschlangenübergaben verwenden +concepts.synchronization.readback.title: "Abschluss des Rücklesens" +concepts.synchronization.reuse.description: "Das Dreieck wartet auf den Abschluss jedes Frames, bevor es dessen Daten wiederverwendet. Sollen sich Frames in der Ausführung überlappen, benötigt jeder noch laufende Frame eigenen veränderlichen Speicher. Verfolgen Sie, wann dieser Speicher wieder verfügbar ist. Vor Datenänderungen müssen noch laufende GPU-Zugriffe auf dieselben Bytes, vor einer Ressourcenfreigabe alle ausstehenden Nutzungen der Ressource abgeschlossen sein." +concepts.synchronization.reuse.details: "Für Größenänderungen und das Beenden gilt dieselbe Reihenfolge: neue Nutzungen stoppen, bestehende abwarten und erst dann Ressourcen ersetzen oder freigeben. Halten Sie dies vor {swapChainResize} sowie vor der Freigabe von Ressourcen oder Kontext ein. Da das Dreieck jeden Frame abwartet, kann es die Größe zwischen den Callbacks ändern." +concepts.synchronization.reuse.guidance: "{swapChainPresent} setzt nach der Präsentation einen Abschlusspunkt in der Grafikwarteschlange und wartet darauf. Das Dreieck wartet daher auch dann bei der Präsentation, wenn die ausdrückliche Warteoperation nach der Einreichung entfällt. Unabhängig eingereichte Arbeit anderer Warteschlangen benötigt eine eigene Abschlussverfolgung." +concepts.synchronization.reuse.title: "Ressourcenwiederverwendung" +concepts.synchronization.timelines.context: "Soll die CPU nach der Weiterverarbeitung das Ergebnis lesen, gemeinsame Daten überschreiben oder Ressourcen freigeben, wartet sie auf diese Einreichung:" +concepts.synchronization.timelines.description: "Eine Timeline kennzeichnet den Warteschlangenfortschritt durch steigende Werte. {submit} liefert die Timeline und den Einreichungswert gemeinsam als {timelineValue}. Die numerischen {value}-Felder verschiedener Timelines sind nicht unmittelbar vergleichbar." +concepts.synchronization.timelines.details: "{producer} und {consumer} seien aufgezeichnete Befehlspuffer zweier Warteschlangen desselben Kontexts; der Verbraucher nutzt die Daten des Erzeugers. Ihre Einreichung erhält diese Abhängigkeit:" +concepts.synchronization.timelines.guidance: "Die weiterverarbeitende Warteschlange wartet vor der Ausführung ihrer Befehle auf den übergebenen Abschlusswert. Die CPU kann ohne {producedWait} weiterarbeiten. Erhalten Sie die gemeinsam verwendeten Ressourcen bis zum Abschluss von {consumed} und zeichnen Sie die für den nachfolgenden Zugriff erforderlichen Texturübergänge auf." +concepts.synchronization.timelines.notes: "Der Rückgabewert von {queueTimelineSignal} kann ebenso mit {wait} abgewartet oder als Abhängigkeit an eine andere Warteschlange übergeben werden. {signal} setzt diesen Abschlusspunkt hinter die zuvor eingereichte Arbeit. Die GPU erreicht ihn, sobald diese Arbeit beendet ist." +concepts.synchronization.timelines.title: "Timelines und Warteschlangenabhängigkeiten" concepts.synchronization.title: Synchronisation home.actions.reference: API durchsuchen home.actions.tutorial: Mit einem Dreieck beginnen -home.entries.description: Ein erster Frame. Ein zielgerichtetes Beispiel. Ein genauerer Blick auf die API. -home.entries.label: Dokumentation erkunden +home.entries.description: "Tutorials, Beispiele und API-Referenz" +home.entries.label: "Bereiche der Dokumentation" home.entries.reference.action: API erkunden home.entries.reference.category: Referenz -home.entries.reference.description: Finden Sie die Typen, Signaturen und Member hinter Ihrer Anwendung. +home.entries.reference.description: "API-Typen, Member und Deklarationen nachschlagen" home.entries.reference.title: API-Referenz home.entries.samples.action: Beispiele durchsuchen home.entries.samples.category: Beispiele -home.entries.samples.description: Erkunden Sie zielgerichtete Rendering- und Compute-Techniken anhand ihres Quellcodes. +home.entries.samples.description: "Ausführbare Beispiele für Grafik- und Compute-Verfahren" home.entries.samples.title: Beispiele -home.entries.title: Beginnen Sie mit der Entwicklung. +home.entries.title: "Dokumentation" home.entries.tutorial.action: Tutorial starten home.entries.tutorial.category: Tutorial -home.entries.tutorial.description: Erstellen Sie eine vollständige Rendering-Anwendung, von der Einrichtung bis zum ersten Frame. +home.entries.tutorial.description: "Vom leeren Projekt zum ersten Dreieck auf dem Bildschirm" home.entries.tutorial.title: Erstes Dreieck -home.introduction.accent: "In C#." -home.introduction.description: Erstellen Sie Ressourcen, zeichnen Sie Befehle auf und reichen Sie Grafik- oder Compute-Arbeit über eine einheitliche .NET-API ein. -home.introduction.title: Entwickeln Sie Ihren Renderer. -home.meta.description: "Eine konsistente C#-API für Grafik und Compute über DirectX, Metal und Vulkan hinweg." -home.scene.description: Studie rotierender Geometrie. Ziehen Sie mit der Maus oder verwenden Sie die Pfeiltasten, um die Ansicht anzupassen. +home.introduction.accent: "auf mehreren Plattformen" +home.introduction.description: "Zenith.NET bündelt Grafik und Compute für DirectX, Metal und Vulkan in einer gemeinsamen API" +home.introduction.title: "Grafik für .NET{lineBreak}{accent}" +home.meta.description: "Plattformübergreifende Grafik und Compute für .NET mit einer gemeinsamen API für DirectX, Metal und Vulkan" +home.scene.description: "Interaktive rotierende Geometrie. Ansicht durch Ziehen oder mit den Pfeiltasten verändern." home.scene.label: Geometrieanzeige home.scene.surface: Oberfläche home.scene.wireframe: Drahtgitter home.title: Modernes RHI für .NET -learning.concepts.description: Verstehen Sie das Zusammenspiel von Befehlen, Ressourcen, Shader-Daten und Synchronisation, bevor Sie Renderpässe kombinieren. -learning.concepts.execution.description: GPU-Arbeit aufzeichnen, einreichen und die zugehörigen Ressourcen gültig halten. -learning.concepts.platforms.description: Ein natives Fenster oder ein UI-Rendering-Steuerelement anbinden. -learning.concepts.resources.description: Ressourcennutzungen, Speicherplatzierung und Ansichten auswählen. -learning.concepts.shaders.description: "C#-Layouts und Ressourcen-Handles auf Slang abstimmen." -learning.concepts.synchronization.description: Abhängige Zugriffe ordnen und wissen, wann Arbeit abgeschlossen ist. +learning.concepts.description: "Ressourcennutzungen wählen, Shader-Daten beschreiben und GPU-Ausführung koordinieren" +learning.concepts.execution.description: "Aufzeichnung, Einreichung und Ressourcenlebensdauer" +learning.concepts.platforms.description: "Native Präsentation und UI-Rendering-Steuerelemente" +learning.concepts.resources.description: "Ressourcennutzungen, Speicherplatzierung und Ansichten" +learning.concepts.shaders.description: "Layout- und Bindungskonventionen für C# und Slang" +learning.concepts.synchronization.description: "Abhängigkeiten, Sichtbarkeit und Abschluss" learning.concepts.title: Kernkonzepte -learning.description: Beginnen Sie mit einem vollständigen Dreieck-Tutorial. Nutzen Sie anschließend die zielgerichteten Beispiele und Konzeptleitfäden, um die Ressourcen, Daten und Abhängigkeiten hinter einem größeren Renderer zu verstehen. +learning.description: "Beginnen Sie mit dem Dreieck-Tutorial und erstellen Sie Ihre erste Anwendung. Anschließend erläutern die Konzeptartikel Ressourcenverwaltung, Shader-Daten und Synchronisation. Für einzelne Grafikverfahren stehen ausführbare Beispiele bereit." learning.entries.samples.action: Beispiele durchsuchen -learning.entries.samples.description: "Finden Sie C#- und Slang-Beispiele für Geometrie, Compute, Ray-Queries und Mesh-Shading." +learning.entries.samples.description: "C#- und Slang-Implementierungen für Geometrie, Compute, Ray-Queries und Mesh-Shading" learning.entries.tutorial.action: Tutorial öffnen -learning.entries.tutorial.description: Erstellen Sie eine Konsolenanwendung, öffnen Sie ein Fenster und zeichnen Sie ein Dreieck. -learning.meta.description: Erste Schritte mit Zenith.NET und Erkundung seines Programmiermodells. +learning.entries.tutorial.description: "Eine Konsolenanwendung mit Fenster und gerendertem Dreieck" +learning.meta.description: "Tutorials und Konzepte zum Programmiermodell von Zenith.NET" learning.title: Lernen -reference.description: Schlagen Sie Ressourcentypen, Befehlssignaturen und Plattformintegrationen nach. -reference.entries.commands.description: Grafik-, Compute- und Transferbefehle aufzeichnen. -reference.entries.commands.label: Arbeit aufzeichnen -reference.entries.context.description: GPU-Ressourcen für das ausgewählte Backend erstellen. +reference.description: "Referenz zu Ressourcen, Befehlen und Plattformintegration" +reference.entries.commands.description: "Grafik-, Compute- und Transferbefehle" +reference.entries.commands.label: "Befehle aufzeichnen" +reference.entries.context.description: "GPU-Ressourcenerstellung für das gewählte Backend" reference.entries.context.label: Hier beginnen -reference.meta.description: Erkunden Sie die Typen und Member in Zenith.NET. -reference.navigation.core: Die Kern-API durchsuchen. +reference.meta.description: "Namespaces, Typen und Member von Zenith.NET" +reference.navigation.core: "Referenz der Kern-API" reference.title: API-Referenz -samples.computeShader.description: Konvertiert ein Bild mit einem Compute-Dispatch in Graustufen und zeigt die resultierende Textur an. Es demonstriert Ressourcen-Handles für eine abgetastete Eingabetextur und eine schreibbare Ausgabetextur, aufgerundete Threadgruppen-Anzahlen sowie eine Bereichsprüfung im Shader. Behalten Sie das enthaltene Asset {assetsTexturesShokoPng} bei; der Renderer verarbeitet es einmal und präsentiert das Ergebnis in nachfolgenden Frames. +samples.computeShader.description: "Das Beispiel lädt {assetsTexturesShokoPng}, wandelt das Bild mit einem Compute-Dispatch in Graustufen um und zeigt die Ausgabetextur an. Die Umwandlung erfolgt einmal; spätere Frames zeigen dasselbe Ergebnis. Der Renderer zeigt die Bindung abtastbarer und beschreibbarer Texturen, das Aufrunden der Threadgruppenanzahl zur vollständigen Bildabdeckung und die Bereichsprüfung im Shader." samples.computeShader.details: "{computeShaderRendererCs} · {computeShaderSlang}" samples.computeShader.title: Compute-Shader -samples.cube.description: Fügt indexiertes Zeichnen, Modell-, Ansichts- und Projektionsmatrizen in einem Konstantenpuffer sowie Tiefentests hinzu. Die Tiefentextur wird bei Größenänderungen neu erstellt. Nutzen Sie dieses Beispiel beim Übergang von Clip-Space-Geometrie zu einem transformierten Objekt; der Renderer verwendet ein {d32FloatS8UInt}-Tiefen-/Stencil-Attachment. +samples.cube.description: "Der Würfel ergänzt indexiertes Zeichnen, Modell-, View- und Projektionsmatrizen in einem Konstantenpuffer sowie Tiefentests. Seine Tiefen-/Stencil-Textur im Format {d32FloatS8UInt} wird bei Größenänderungen neu erstellt." samples.cube.details: "{spinningCubeRendererCs} · {spinningCubeSlang}" samples.cube.title: Rotierender Würfel -samples.description: "Wählen Sie ein zielgerichtetes Beispiel für die Funktion, die Sie untersuchen möchten. Jedes Beispiel verlinkt auf den C#-Renderer und seinen Slang-Shader. Beginnen Sie mit {link}, wenn Sie eine vollständige Anwendung von einem leeren Projekt an erklärt haben möchten." +samples.description: "Jedes Beispiel verbindet einen C#-Renderer mit seinem Slang-Shader und behandelt ein bestimmtes Verfahren. Den vollständigen Anwendungsaufbau und die Rendersequenz erläutert {link}." samples.description.link: Erstes Dreieck -samples.execution.description: "{link} enthält sechs unabhängige Renderer in einer Desktop-Anwendung. Verwenden Sie das .NET 10 SDK und ein unterstütztes Desktop-Backend, wie unten beschrieben. Erstellen Sie die Anwendung und führen Sie sie aus, und wählen Sie dann ein Beispiel aus dem Konsolenmenü:" +samples.execution.description: "Starten Sie das Projekt {link} und wählen Sie ein Beispiel im Konsolenmenü." samples.execution.description.link: ZenithTutorials -samples.execution.details: Der Host wählt DirectX 12 unter Windows, Metal unter macOS und Vulkan unter Linux. Verwenden Sie ein Gerät, einen Treiber und eine Shader-Compiler-Umgebung, die vom ausgewählten Backend unterstützt werden. Der Linux-Fensterpfad erfordert X11 oder XWayland. Die {link} deklariert Paketabhängigkeiten und kopiert die zur Laufzeit benötigten Shader- und Textur-Assets. -samples.execution.details.link: Projektdatei -samples.execution.guidance: Die Beispiele teilen sich den Code für Fensterverwaltung und Präsentation. Sie können jedes Beispiel unabhängig danach auswählen, welche Funktion Sie untersuchen möchten. -samples.execution.title: Tutorial-Beispiele ausführen -samples.host.description: "{appCs} erstellt den Kontext, das Fenster und die Swapchain. Es bezieht einen Befehlspuffer, ruft den ausgewählten Renderer auf, reicht den Frame ein und präsentiert ihn. {iRendererCs} definiert die Update-, Render-, Resize- und Freigabemethoden des Renderers." -samples.host.details: Compute und Raytracing erzeugen Offscreen-Texturen. {texturePresenterCs} und {presentTextureSlang} zeichnen diese Texturen in die Ausgabetextur des aktuellen Frames des Fensters. Der Host besitzt weiterhin das Einreichen und die Swapchain-Präsentation. -samples.host.title: Gemeinsamer Host und Präsentation -samples.indirectDrawing.description: Zeichnet mehrere Kopien eines Würfels unter Verwendung eines indexierten indirekten Argumentpuffers und Instanzdaten in einem strukturierten Puffer. Die CPU liefert die Zeichenargumente und aktualisiert die Transformationen. Nutzen Sie dies, um das Layout indirekter Argumente und den Shader-Zugriff auf Instanzdaten zu verstehen, bevor Sie GPU-generierte Argumente hinzufügen. +samples.execution.title: "Beispiele ausführen" +samples.host.description: "{appCs} initialisiert Kontext, Fenster und Swapchain. Pro Frame bezieht der Host einen Befehlspuffer, ruft den Renderer auf, reicht die Befehle ein und präsentiert das Ergebnis. {iRendererCs} definiert Aktualisierung, Rendering, Größenanpassung und Freigabe." +samples.host.details: "Die Compute- und Raytracing-Renderer erzeugen Offscreen-Texturen. {texturePresenterCs} und {presentTextureSlang} zeichnen diese in die aktuelle Ausgabetextur. Anschließend reicht der gemeinsame Host die Befehle ein und präsentiert den Frame." +samples.host.title: "Host und Präsentation" +samples.indirectDrawing.description: "Indirektes Zeichnen stellt mehrere Würfelinstanzen aus einem Puffer für indexierte Zeichenargumente und einem strukturierten Puffer mit Instanzdaten dar. Die CPU liefert die Argumente und aktualisiert die Transformationen." samples.indirectDrawing.details: "{indirectDrawingRendererCs} · {indirectDrawingSlang}" samples.indirectDrawing.title: Indirektes Zeichnen -samples.meshShading.description: "Verwendet einen Task-Shader, um Kugelinstanzen für das Zeichnen auszusortieren und die Indizes der verbleibenden Instanzen an einen Mesh-Shader weiterzugeben, der Geometrie ausgibt. Der Renderer prüft {contextCapabilitiesMeshShadingSupported}, bevor er seine Pipeline erstellt. Nutzen Sie das Beispiel, um Ressourcen-Handles und Nutzdaten durch die Task- und Mesh-Stufen zu verfolgen." +samples.meshShading.description: "Ein Task-Shader sortiert nicht sichtbare Kugelinstanzen aus und übergibt die verbleibenden Indizes an den Mesh-Shader, der die Geometrie erzeugt. Vor der Pipeline-Erstellung prüft der Renderer {contextCapabilitiesMeshShadingSupported}." samples.meshShading.details: "{meshShadingRendererCs} · {meshShadingSlang}" samples.meshShading.title: Mesh-Shading -samples.rayTracing.description: Erstellt Bottom-Level- und Top-Level-Beschleunigungsstrukturen für einen Boden und prozedurale Kugeln und führt dann Inline-Ray-Queries in einem Compute-Shader aus. Der Renderer prüft {contextCapabilitiesRayTracingSupported}, bevor er die Arbeitslast konstruiert. Nutzen Sie dieses Beispiel für Beschleunigungsstruktureingaben und shaderseitige Strahlendurchquerung. +samples.rayTracing.description: "Das Beispiel erstellt Beschleunigungsstrukturen der unteren und oberen Ebene für einen Boden und prozedurale Kugeln und führt Inline-Rayqueries in einem Compute-Shader aus. Vor der Initialisierung prüft es {contextCapabilitiesRayTracingSupported}." samples.rayTracing.details: "{rayTracingRendererCs} · {rayTracingSlang}" samples.rayTracing.title: Raytracing samples.title: Beispiele -samples.triangle.description: Erstellt einen Scheitelpunktpuffer und ein passendes Eingabelayout und zeichnet dann drei Scheitelpunkte über eine Grafikpipeline. Nutzen Sie dies, um die Ressourcenerstellung mit den Befehlen in einem Renderpass zu verknüpfen. +samples.triangle.description: "Das Dreieck verbindet einen Vertexpuffer mit dem passenden Eingabelayout und zeichnet drei Vertices durch eine Grafikpipeline." samples.triangle.details: "{helloTriangleRendererCs} · {helloTriangleSlang} · {link}" samples.triangle.details.link: Vollständiges Tutorial samples.triangle.title: Hallo Dreieck -samples.workloads.description: "Das {link} des Haupt-Repositorys enthält Anwendungen, die mehrere Funktionen kombinieren. Ihre Projekte verweisen auf den Bibliotheksquellcode. Führen Sie aus einem Checkout von Zenith.NET das gewünschte Projekt aus, zum Beispiel:" +samples.workloads.description: "Das {link} im Haupt-Repository enthält größere Anwendungen, die den Bibliotheksquellcode referenzieren." samples.workloads.description.link: Verzeichnis Experiments -samples.workloads.details: Die fensterbasierten Experimente verwenden dieselben Host-Optionen für Windows, macOS und Linux/X11. Informationen zum Zeichnen innerhalb von Avalonia, WinForms, WPF, WinUI/Uno oder MAUI sowie zum Frame-Lebenszyklus und zu Implementierungslinks finden Sie unter {link}. +samples.workloads.details: "Die Fensterexperimente nutzen dieselben Präsentationspfade für Windows, macOS und Linux/X11. UI-Steuerelemente für Avalonia, WinForms, WPF, WinUI/Uno und MAUI behandelt {link}, einschließlich Frame-Ablauf und Implementierungsquellen." samples.workloads.details.link: Plattformintegration samples.workloads.table.cornellBox.example: "{link}" samples.workloads.table.cornellBox.example.link: CornellBox -samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: Pfadverfolgung, Rauschunterdrückung, Tone-Mapping, Hochskalierung und ImGui-Steuerelemente. Erfordert Raytracing-Unterstützung und die Shader-Kompilierungsumgebung für das jeweilige Desktop-Backend. +samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: "Pathtracing, Rauschunterdrückung, Tone-Mapping, Hochskalierung und ImGui-Steuerelemente. Erfordert Raytracing-Unterstützung." samples.workloads.table.fluidTank.example: "{link}" samples.workloads.table.fluidTank.example.link: FluidTank -samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: Compute-Fluidsimulation, Abhängigkeiten zwischen Simulationsstufen und mehrpassiges Oberflächen-Rendering. Erfordert das jeweilige Desktop-Backend und die Shader-Kompilierungsumgebung. +samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: "Compute-Fluidsimulation, Abhängigkeiten zwischen Simulationsstufen und mehrpassiges Oberflächen-Rendering." samples.workloads.table.headings.example: Beispiel -samples.workloads.table.headings.whatItDemonstratesAndRequires: Was es demonstriert und erfordert +samples.workloads.table.headings.whatItDemonstratesAndRequires: "Verfahren und Voraussetzungen" samples.workloads.table.inkCanvas.example: "{link}" samples.workloads.table.inkCanvas.example.link: InkCanvas samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: Skia-Zeichnen und Eingabeverarbeitung in einem nativen Fenster. Erfordert das Backend und die native Skia-Bibliothek für die Zielplattform. samples.workloads.table.platformDetection.example: "{link}" samples.workloads.table.platformDetection.example.link: PlatformDetection -samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: Versucht die Kontexterstellung für jedes Backend und meldet Gerätefunktionen. Ein Fehler bei der Kontexterstellung wird als nicht unterstützt gemeldet; dieses Ergebnis kann auch auf einen fehlenden Treiber oder eine fehlende Laufzeitabhängigkeit hinweisen. -samples.workloads.title: Größere Arbeitslasten erkunden -tutorial.context.description: Das Fenster kann sich nun öffnen, aber wir haben noch nicht die GPU-Objekte erstellt, die darin rendern werden. Ein {graphicsContext} bietet Zugriff auf das ausgewählte Grafik-Backend und seine Befehlswarteschlangen. -tutorial.context.details: "Fügen Sie diesen Block {emphasis} ein:" +samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: "Versucht für jedes Backend einen Kontext zu erstellen und meldet die Gerätefunktionen. Ein fehlgeschlagener Versuch wird als nicht unterstützt gemeldet; Ursache können das Gerät, der Treiber oder eine fehlende Laufzeitabhängigkeit sein." +samples.workloads.title: "Umfangreichere Anwendungen" +tutorial.context.description: "Ein {graphicsContext} verbindet die Anwendung über ein Backend mit der GPU und stellt die Methoden zum Erstellen der Rendering-Ressourcen bereit." +tutorial.context.details: "Fügen Sie die Kontextinitialisierung {emphasis} ein:" tutorial.context.details.emphasis: nach den using-Direktiven, vor {iWindowWindow} -tutorial.context.guidance: Die Verzweigungen wählen DirectX 12 unter Windows, Metal unter macOS und Vulkan unter Linux aus. Der nachfolgende Rendering-Code verwendet die gemeinsame Zenith.NET-API. Wir fordern die Validierung während der Entwicklung an und geben über {validationMessage} gemeldete Meldungen aus. Die Diagnose hängt vom Backend und den auf dem Computer verfügbaren Validierungskomponenten ab. -tutorial.context.title: Grafikkontext erstellen -tutorial.description: Erstellen Sie eine .NET-Konsolenanwendung, die ein Fenster öffnet und ein Dreieck mit einem weichen Farbverlauf zeichnet. Sie lernen, wie Scheitelpunktdaten, Shader und Pipeline-Zustände zusammenwirken, und zeichnen anschließend die Befehle auf und reichen sie ein, die das Bild erzeugen. -tutorial.details: Arbeiten Sie die Abschnitte der Reihe nach durch. Sie öffnen zuerst ein leeres Fenster, zeigen dann eine Hintergrundfarbe an und zeichnen schließlich das Dreieck. Jeder Kontrollpunkt bestätigt einen Teil der Anwendung, bevor Sie den nächsten hinzufügen. Die Initialisierung wird einmal ausgeführt; der Render-Callback zeichnet bei jedem Aufruf einen neuen Frame auf. +tutorial.context.guidance: "Jeder Zweig wählt das Backend der aktuellen Plattform und fordert Validierung an. Meldungen von {validationMessage} werden in der Konsole ausgegeben." +tutorial.context.imports: "Ergänzen Sie am Anfang von {programCs} die folgenden using-Direktiven:" +tutorial.context.title: "Grafikkontext" +tutorial.description: "In diesem Tutorial entsteht aus einem leeren .NET-Konsolenprojekt eine Anwendung, die ein Fenster öffnet und ein farbiges Dreieck zeichnet." +tutorial.details: "Das Tutorial führt über drei überprüfbare Zwischenstände zum Ergebnis: ein leeres Fenster, eine einfarbige Fläche und schließlich das farbige Dreieck. Führen Sie die Anwendung nach jedem dieser Schritte aus, bevor Sie den nächsten Teil ergänzen." tutorial.draw.context: "Die Argumente für {draw} sind:" -tutorial.draw.description: "Ersetzen Sie im Callback {windowRender} den Platzhalter {addTheTriangleDrawCommandsHereLater} durch diese drei Befehle zwischen {beginRenderPass} und {endRenderPass}:" -tutorial.draw.details: "{setPipeline} wählt die soeben erstellten Shader und Zustände aus. Setzen Sie sie vor dem Binden von Scheitelpunktdaten: Das Backend verwendet das Eingabelayout der Pipeline, um die Bindung zu interpretieren." -tutorial.draw.guidance: "{setVertexBufferVertexBuffer} bindet den Puffer ab Byte-Offset 0 an Eingabeslot 0. Dieser Slot entspricht dem einzelnen Eintrag in {inputLayouts}. Die Daten werden dadurch nicht erneut kopiert oder hochgeladen." -tutorial.draw.notes: Die Befehle sind an dieser Stelle immer noch nur aufgezeichnet. Die Aufrufe von {submitWait} und {present}, die sich bereits am Ende des Render-Callbacks befinden, führen die Arbeit aus und zeigen ihr Ergebnis an. Das Löschen bleibt notwendig, da das Dreieck nur einen Teil des Bildes abdeckt; der Hintergrund muss ebenfalls in jedem Frame eine definierte Farbe erhalten. +tutorial.draw.description: "Ersetzen Sie im Callback {windowRender} den Kommentar {addTheTriangleDrawCommandsHereLater} durch folgende Befehle zwischen {beginRenderPass} und {endRenderPass}:" +tutorial.draw.details: "{setPipeline} wählt Shader und Renderzustand. Der Aufruf muss vor der Vertexbindung stehen, weil deren Interpretation vom Eingabelayout der Pipeline abhängt." +tutorial.draw.guidance: "{setVertexBufferVertexBuffer} bindet die hochgeladenen Vertexdaten ab Byte-Offset 0 an Eingabeslot 0. Dieser entspricht dem einzigen Eintrag in {inputLayouts}." +tutorial.draw.notes: "Diese Aufrufe zeichnen die Zeichenbefehle auf. Das vorhandene {submitWait} reicht sie ein und wartet auf ihren GPU-Abschluss; {present} fordert anschließend die Anzeige des fertigen Bildes an. Behalten Sie das Füllen mit der Hintergrundfarbe am Anfang des Passes bei, damit auch die Fläche außerhalb des Dreiecks einen definierten Inhalt hat." tutorial.draw.table.firstInstance.meaning: Instanznummerierung bei null beginnen. -tutorial.draw.table.firstVertex.meaning: Mit dem ersten Scheitelpunkt im Puffer beginnen. +tutorial.draw.table.firstVertex.meaning: "Mit dem ersten Vertex im Puffer beginnen." tutorial.draw.table.headings.argument: Argument tutorial.draw.table.headings.description: Wert tutorial.draw.table.headings.meaning: Bedeutung tutorial.draw.table.instanceCount.meaning: Eine Kopie des Dreiecks zeichnen. -tutorial.draw.table.vertexCount.meaning: Drei Scheitelpunkte lesen. -tutorial.draw.title: Das Dreieck innerhalb des Passes zeichnen -tutorial.execution.description: "Erstellen Sie die Anwendung und führen Sie sie aus dem Verzeichnis {firstTriangle} aus:" -tutorial.execution.details: Das Fenster sollte ein Dreieck mit einer roten oberen Ecke, einer grünen unteren rechten Ecke und einer blauen unteren linken Ecke vor einem dunklen Hintergrund anzeigen. Das Innere sollte einen weichen Übergang zwischen diesen Farben aufweisen. -tutorial.execution.guidance: Ändern Sie die Fenstergröße. Der Resize-Callback aktualisiert die Framebuffer-Abmessungen und passt die Größe der Swapchain an. Der Renderpass richtet einen Viewport ein, der diesem Bild entspricht. Da die Scheitelpunktpositionen in normalisierten Koordinaten verbleiben, behält das Dreieck denselben Bruchteil der Fensterbreite und -höhe bei; eine Änderung des Seitenverhältnisses kann seine Form verzerren. Die Beibehaltung des Seitenverhältnisses eines Objekts erfordert eine Projektions- oder Viewport-Strategie, die über diesen ersten Zeichenvorgang hinausgeht. -tutorial.execution.title: Ausführen, Größe ändern und schließen -tutorial.frame.commands.context: Nach {endRenderPass} bereitet der zweite Übergang das Bild auf die Präsentation vor. {submit} beendet die Aufzeichnung und reicht den Befehlspuffer ein; {wait} wartet darauf, dass die GPU diese Übermittlung abschließt. {present} fordert dann die Anzeige des gerenderten Bildes an. -tutorial.frame.commands.description: Ein Renderpass gruppiert Zeichenoperationen, die dieselben Attachments verwenden. Hier ist das Farb-Attachment die Ausgabetextur der Swapchain, also das Bild, das unsere Zeichnung empfängt. {colorAttachmentClear} erstellt eine Beschreibung, die den Pass anweist, auf die angegebene RGBA-Farbe zu löschen und das Ergebnis nach Beendigung des Passes beizubehalten. {beginRenderPass} zeichnet diese Anweisungen auf; die GPU führt das Löschen aus, nachdem die Befehle eingereicht wurden. -tutorial.frame.commands.details: Die eckigen Klammern enthalten unser einzelnes Farb-Attachment. Das Argument {null} bedeutet, dass kein Tiefen-/Stencil-Attachment vorhanden ist, das Tiefenwerte und Stencil-Masken für Tiefen- und Stencil-Tests speichern würde. -tutorial.frame.commands.guidance: "{beginRenderPass} legt einen Viewport und einen Scissor fest, die das Attachment abdecken. Der Viewport bildet die gerenderten Koordinaten auf Pixel ab, und der Scissor schränkt ein, welche Pixel beschrieben werden dürfen. Diese Standardeinstellungen decken die gesamte Ausgabetextur ab, was für dieses Dreieck genau richtig ist." -tutorial.frame.commands.title: Löschen, einreichen und präsentieren -tutorial.frame.description: Füllen Sie das Bild zunächst mit einer einzigen Hintergrundfarbe. Dieser Vorgang wird als Löschen (Clear) bezeichnet. Wenn diese Farbe im Fenster erscheint, arbeiten die Oberfläche, das Einreichen von Befehlen und der Präsentationspfad zusammen. Mit diesem Kontrollpunkt können Sie die Frame-Schleife überprüfen, bevor Sie Geometrie und Shader hinzufügen. -tutorial.frame.details: "Ein Render-Callback ist Code, den Silk.NET aufruft, wenn ein Frame gezeichnet werden soll. Dieser Callback benötigt das Argument für die vergangene Zeit des Ereignisses nicht, daher wird es {value} genannt. Registrieren Sie ihn {emphasis}:" +tutorial.draw.table.vertexCount.meaning: "Drei Vertices lesen." +tutorial.draw.title: "Zeichenbefehle" +tutorial.execution.description: "Erstellen und starten Sie das Projekt {firstTriangle}." +tutorial.execution.details: "Auf dem dunklen Hintergrund erscheint ein Dreieck: oben rot, rechts unten grün und links unten blau. Durch Interpolation gehen die Vertexfarben im Inneren fließend ineinander über." +tutorial.execution.guidance: "Beim Ändern der Fenstergröße ändern sich die Pixelmaße des Bildes, während die Vertexkoordinaten gleich bleiben. Der Viewport bildet sie auf die neue Breite und Höhe ab. Das Dreieck wird deshalb gestreckt, wenn sich das Seitenverhältnis des Fensters ändert." +tutorial.execution.title: "Anwendung ausführen" +tutorial.frame.commands.context: "Nach {endRenderPass} bereitet der zweite Übergang die Präsentation vor. {submit} beendet die Aufzeichnung und reicht den Befehlspuffer ein; {wait} blockiert bis zu dessen Abschluss. Danach fordert {present} die Bildanzeige an." +tutorial.frame.commands.description: "Ein Renderpass fasst Zeichenoperationen zusammen, die in dieselben Attachments schreiben. Hier nimmt die Ausgabetextur der Swapchain die Farbausgabe auf. {colorAttachmentClear} legt fest, dass dieses Attachment zu Beginn mit einer RGBA-Farbe gefüllt und sein Inhalt am Ende erhalten wird. {beginRenderPass} zeichnet den Beginn des Passes mit diesen Einstellungen auf." +tutorial.frame.commands.details: "Die Sammlung enthält ein Farb-Attachment. {null} gibt an, dass der Pass kein Tiefen-/Stencil-Attachment verwendet." +tutorial.frame.commands.guidance: "{beginRenderPass} setzt Viewport und Scissor auf die gesamte Attachment-Fläche. Der Viewport bildet Renderkoordinaten auf Pixelpositionen ab; der Scissor begrenzt den Bereich, in den geschrieben werden darf." +tutorial.frame.commands.title: "Löschen, Einreichung und Präsentation" +tutorial.frame.description: "Füllen Sie das Fenster zunächst mit einer Hintergrundfarbe. Diese Operation heißt Löschen. Sobald die Farbe sichtbar ist, arbeiten das native Präsentationsziel, die Befehlseinreichung und die Präsentation zusammen. Darauf bauen die Vertices und Shader des Dreiecks auf." +tutorial.frame.details: "Silk.NET ruft den Render-Callback auf, sobald ein Frame ansteht. Das Zeitargument wird nicht verwendet und erhält den Namen {value}. Registrieren Sie den Callback {emphasis}:" tutorial.frame.details.emphasis: vor {windowRun} -tutorial.frame.target.description: "{graphicsQueueCommandBuffer} bezieht einen Befehlspuffer, dessen Aufzeichnung bereits begonnen hat. Das Aufzeichnen beschreibt Arbeit für die GPU; es führt diese Arbeit nicht sofort aus." -tutorial.frame.target.details: Der erste {transition}-Aufruf bereitet die Ausgabetextur für den Zugriff als Farb-Attachment vor. {default} wählt Mip-Level 0 und Array-Layer 0 aus. Wir verwenden {undefined} als vorheriges Layout, da wir das gesamte Bild löschen und seinen vorherigen Inhalt verwerfen. Ein Pass, der vorhandene Inhalte beibehalten muss, muss stattdessen sein tatsächliches vorheriges Layout verwenden. -tutorial.frame.target.guidance: Verwenden Sie in jedem Frame die aktuelle Ausgabetextur der Swapchain. Die Präsentation kann ändern, welches Bild verfügbar ist; daher ist eine aus einem früheren Frame gespeicherte Textur kein dauerhaftes Fenster-Renderziel. +tutorial.frame.target.description: "{graphicsQueueCommandBuffer} liefert einen aufzeichnungsbereiten Befehlspuffer. Die Aufzeichnung beschreibt GPU-Arbeit; ausgeführt wird sie erst nach der Einreichung." +tutorial.frame.target.details: "Ein Texturlayout beschreibt, welchen Zugriff eine Operation benötigt. Der erste Aufruf von {transition} bereitet die Ausgabetextur als Farb-Attachment vor. {default} wählt Mip-Level 0 und Array-Layer 0, also das Basisbild dieser Textur. Da der Pass das gesamte Bild mit einer Hintergrundfarbe füllt, darf {undefined} den bisherigen Inhalt verwerfen." +tutorial.frame.target.guidance: "Verwenden Sie in jedem Frame die aktuelle Ausgabetextur, da die Präsentation zum nächsten Bild wechseln kann." tutorial.frame.target.title: Ausgabetextur vorbereiten -tutorial.frame.title: Eine Hintergrundfarbe anzeigen -tutorial.geometry.data.description: Fügen Sie dieses Array {emphasis} hinzu. Die folgenden Schritte zur Ressourcenerstellung gehören ebenfalls vor diesen Callback, in der gezeigten Reihenfolge. +tutorial.frame.title: "Der erste Frame" +tutorial.geometry.data.description: "Fügen Sie das Vertexarray {emphasis} ein. Auch die anschließende Ressourceninitialisierung steht in der angegebenen Reihenfolge vor diesem Callback." tutorial.geometry.data.description.emphasis: vor {windowRender} -tutorial.geometry.data.details: "Jeder Array-Eintrag erstellt einen {vertex}. Die beiden inneren {new}-Ausdrücke erstellen seine {vector3}-Position und {vector4}-Farbe. Die Scheitelpunkte beschreiben die obere, untere rechte und untere linke Ecke. Der Vertex-Shader liefert eine vierte Positionskoordinate, {w}. Wenn w gleich 1 ist, beschreiben x und y direkt normalisierte Gerätekoordinaten: -1 und +1 sind die Bildränder und 0 ist das Zentrum. Diese Koordinaten hängen nicht von den Pixelabmessungen des Fensters ab." -tutorial.geometry.data.guidance: Jede Farbe enthält Rot-, Grün-, Blau- und Alpha-Komponenten. Alpha ist an allen drei Ecken 1. Alle drei Positionen haben z = 0 und liegen damit in derselben Ebene. Diese Positionen benötigen keine Kamera- oder Transformationsmatrix, da sie bereits die Koordinaten beschreiben, die wir rendern möchten. Für dieses einzelne flache Dreieck deaktivieren wir außerdem Blending und Tiefentests und verzichten auf einen Tiefenpuffer. -tutorial.geometry.data.title: Die Ecken auswählen -tutorial.geometry.description: Ein Scheitelpunkt (Vertex) ist ein Punkt zusammen mit den zu seinem Zeichnen verwendeten Daten. Unser Dreieck hat drei Scheitelpunkte, einen für jede Ecke. Jeder enthält eine Position und eine Farbe. Die GPU interpoliert die Farben und berechnet Zwischenwerte über das gesamte Dreieck hinweg. -tutorial.geometry.format.description: "Fügen Sie diese Deklaration {emphasis} an:" +tutorial.geometry.data.details: "Jeder Eintrag erstellt einen {vertex}; die beiden inneren {new}-Ausdrücke liefern {vector3}-Position und {vector4}-Farbe. Die Positionen bilden die obere, rechte untere und linke untere Ecke. Der Vertex-Shader ergänzt {w} als vierte Koordinate. Bei w = 1 sind x und y zugleich normalisierte Gerätekoordinaten: -1 und +1 markieren die Bildgrenzen, 0 die Mitte, unabhängig von Pixelmaßen." +tutorial.geometry.data.guidance: "Jede Farbe hat Rot-, Grün-, Blau- und Alpha-Komponenten; Alpha ist 1. Alle drei Vertices liegen mit z = 0 in derselben Ebene." +tutorial.geometry.data.title: "Vertexpositionen und Farben" +tutorial.geometry.description: "Jeder der drei Vertices besitzt eine Position und eine Farbe. Aus den Positionen ergibt sich die Form des Dreiecks; die GPU interpoliert die Farben über dessen Fläche." +tutorial.geometry.format.description: "Ergänzen Sie die Vertexdeklaration {emphasis}:" tutorial.geometry.format.description.emphasis: am Ende von {programCs}, nach den Bereinigungsanweisungen -tutorial.geometry.format.details: "{file} beschränkt diesen Typ auf {programCs}, und der Konstruktor initialisiert seine Positions- und Farbfelder. {layoutKindSequential} behält die Deklarationsreihenfolge der Felder bei. {position} enthält drei 32-Bit-Gleitkommazahlen und {color} vier. In dieser Struktur beginnt die Position bei Byte 0, die Farbe bei Byte 12, und der gesamte Scheitelpunkt belegt 28 Bytes. Dasselbe Layout werden wir der Grafikpipeline beschreiben." -tutorial.geometry.format.title: Einen Scheitelpunkt definieren -tutorial.geometry.title: Der GPU drei Scheitelpunkte übergeben -tutorial.geometry.upload.context: "{fixed} verhindert, dass der Garbage Collector das Array verschiebt, während seine Adresse verwendet wird. Bei diesem CPU-beschreibbaren Puffer mappt {upload} den Speicher, kopiert die Daten und hebt das Mapping vor der Rückkehr auf. Das Array muss danach nicht fixiert bleiben. Der Puffer muss während des gesamten Renderings gültig bleiben. Da sich die Scheitelpunkte nicht ändern, genügt ein einmaliger Upload." -tutorial.geometry.upload.description: "Das verwaltete Array besteht aus CPU-Daten. Ein {buffer} stellt der GPU Speicherplatz zur Verfügung, aus dem sie die Scheitelpunkte lesen kann. Fügen Sie nach dem Array Folgendes hinzu:" -tutorial.geometry.upload.details: "Die Gesamtgröße beträgt {sizeofVertexVerticesLength}: 28 Bytes pro Scheitelpunkt, drei Scheitelpunkte, insgesamt 84 Bytes. {bufferUsagesVertex} erlaubt den Zugriff als Scheitelpunkteingabe. {cpuWriteOnly} ermöglicht es der CPU, diesen kleinen Puffer direkt zu initialisieren. Der Stride des Deskriptors erfasst die Elementgröße; das weiter unten erstellte Eingabelayout teilt dem Scheitelpunktabruf mit, wie die einzelnen Attribute zu lesen sind." -tutorial.geometry.upload.guidance: Das Erstellen eines Puffers befüllt ihn nicht. {upload} kopiert das Array ab dem Ziel-Byte-Offset 0 in diese Zuweisung. Seine Quellbeschreibung liefert einen Zeiger und die Anzahl der zu kopierenden Bytes. -tutorial.geometry.upload.notes: Fügen Sie {vertexBufferDispose} unmittelbar vor {swapChainDispose} in die Bereinigung am Ende von {programCs} ein. Für größere statische Geometrien erklärt {link}, wann stattdessen reiner GPU-Speicher und Transfer-Uploads gewählt werden sollten. +tutorial.geometry.format.details: "{file} beschränkt den Typ auf {programCs}, und {layoutKindSequential} erhält die Deklarationsreihenfolge seiner Felder. {position} enthält drei 32-Bit-Gleitkommazahlen und beginnt am Byte-Offset 0; {color} enthält vier und beginnt am Byte-Offset 12. Ein Vertex belegt damit 28 Bytes. Das Eingabelayout beschreibt diese Anordnung, damit die GPU die Felder korrekt liest." +tutorial.geometry.format.imports: "Ergänzen Sie am Anfang von {programCs} diese using-Direktiven für die Vektortypen und das Attribut zur Festlegung des Strukturlayouts:" +tutorial.geometry.format.title: "Vertexdarstellung" +tutorial.geometry.title: "Vertexdaten" +tutorial.geometry.upload.context: "{fixed} verhindert, dass die Garbage Collection das Array verschiebt, solange dessen Adresse verwendet wird. Bei diesem CPU-beschreibbaren Puffer mappt {upload} den Speicher, kopiert die Daten und hebt das Mapping vor der Rückkehr auf. Das Array muss daher nur während des Aufrufs fixiert bleiben. Laden Sie die Vertices einmal bei der Initialisierung hoch und geben Sie den Puffer erst nach Abschluss des Renderings frei." +tutorial.geometry.upload.description: "Speichern Sie die Vertices in einem {buffer}, damit die GPU sie beim Zeichnen lesen kann. Fügen Sie Allokation und Upload direkt nach dem Array ein:" +tutorial.geometry.upload.details: "{sizeofVertexVerticesLength} ergibt drei Vertices zu 28 Bytes, insgesamt 84 Bytes. {bufferUsagesVertex} deklariert Vertex-Eingabezugriff, {cpuWriteOnly} ermöglicht die direkte CPU-Initialisierung. Der Stride beschreibt die Elementgröße; das anschließende Eingabelayout bestimmt die Interpretation jedes Attributs." +tutorial.geometry.upload.guidance: "Die Allokation initialisiert den Inhalt nicht. {upload} kopiert das Array ab Ziel-Byte-Offset 0 mit dem Quellzeiger und der Bytezahl der Datenbeschreibung." +tutorial.geometry.upload.imports: "Ergänzen Sie {bufferAlias} bei den using-Direktiven in {programCs}, um den Puffertyp von Zenith.NET von {systemBuffer} zu unterscheiden." +tutorial.geometry.upload.notes: "Setzen Sie {vertexBufferDispose} direkt vor {swapChainDispose} in die Bereinigung am Ende von {programCs}. GPU-only-Speicher und Transfer-Uploads für größere Geometrie erläutert {link}." tutorial.geometry.upload.notes.link: Ressourcenverwaltung -tutorial.geometry.upload.title: Einen Puffer zuweisen und das Array hochladen -tutorial.input.description: "Die Scheitelpunkt-Bytes und Shader sind bereit. Beschreiben Sie als Nächstes, wie die GPU jeden Scheitelpunkt lesen soll. Ein Attribut ist ein einzelner Wert, wie etwa Position oder Farbe. Das Eingabelayout weist jedem Attribut ein Format und einen Byte-Offset zu; der Stride gibt den Abstand in Bytes von einem Scheitelpunkt zum nächsten an. Fügen Sie diesen Initialisierungsblock nach der Shader-Erstellung ein:" -tutorial.input.details: "{inputLayoutAdd} hängt ein Element am aktuellen Stride an und erhöht diesen Stride um die Größe des Elements. Es überprüft die C#-Struktur nicht. Hier erzeugt es die folgende Übereinstimmung zwischen CPU-Speicher und Shader-Eingaben:" -tutorial.input.guidance: "Eine Änderung der C#-Feldreihenfolge oder des Paddings ohne Anpassung dieser Beschreibung würde die GPU falsche Bytes lesen lassen. Der Standardwert von {semanticIndex} ist 0 und entspricht {pOSITION0} und {cOLOR0}. Beide Elemente gehören zum selben Puffer. Deshalb enthält die Pipeline ein Eingabelayout, und wir binden den Puffer an Slot 0." +tutorial.geometry.upload.title: "Pufferallokation und Upload" +tutorial.input.description: "Die GPU muss wissen, wo Attribute wie Position und Farbe gespeichert sind. Das Eingabelayout gibt Format und Byte-Offset jedes Attributs sowie den Stride an, also den Byte-Abstand zum nächsten Vertex. Fügen Sie diesen Code nach der Shader-Erstellung ein:" +tutorial.input.details: "{inputLayoutAdd} fügt jedes Attribut unmittelbar nach dem vorherigen ein und erhöht den Stride um die Größe des neu hinzugefügten Attributs. Die Offsets ergeben sich aus den angegebenen Formaten; die C#-Struktur wird dabei nicht untersucht. Für diese beiden Felder entsteht folgendes Layout:" +tutorial.input.guidance: "Der Standardwert von {semanticIndex} ist 0 und entspricht damit {pOSITION0} und {cOLOR0} im Shader. Position und Farbe stehen gemeinsam in einem Vertexpuffer, weshalb die Pipeline ein Eingabelayout an Slot 0 verwendet. Passen Sie dieses Layout an, wenn sich Feldreihenfolge oder Auffüllung der C#-Struktur ändern." tutorial.input.table.headings.byteOffset: Byte-Offset tutorial.input.table.headings.cField: "C#-Feld" tutorial.input.table.headings.format: Format tutorial.input.table.headings.shaderInput: Shader-Eingabe -tutorial.input.table.nextVertex.cField: Nächster Scheitelpunkt +tutorial.input.table.nextVertex.cField: "Nächster Vertex" tutorial.input.table.nextVertex.format: "Gesamter Stride: 28 Bytes" tutorial.input.table.nextVertex.shaderInput: Nächster Eingabedatensatz tutorial.input.table.vertexColor.format: "{float4} (16 Bytes)" tutorial.input.table.vertexPosition.format: "{float3} (12 Bytes)" -tutorial.input.title: Das Scheitelpunkteingabelayout beschreiben -tutorial.lifecycle.description: "Die fertige Anwendung wiederholt diese Abfolge:" -tutorial.lifecycle.details: "Das Schließen des Fensters beendet {run}. Jeder gerenderte Frame hat bereits darauf gewartet, dass seine GPU-Arbeit abgeschlossen ist, sodass wir nun die von ihm verwendeten Ressourcen freigeben können. Die Bereinigung nach {windowRun} sollte wie folgt aussehen:" -tutorial.lifecycle.guidance: "Geben Sie die Swapchain vor ihrem nativen Fenster und den Kontext nach all seinen Ressourcen frei. Die Warteschlange besitzt und recycelt eingereichte Befehlspuffer; die Swapchain besitzt ihre Ausgabetextur. Für diese Befehlspuffer und die Ausgabetextur ist in dieser Anwendung kein eigener {dispose}-Aufruf nötig." -tutorial.lifecycle.title: Den Lebenszyklus eines Frames verfolgen -tutorial.pipeline.behavior: "Fügen Sie nach dem Eingabelayout Folgendes hinzu:" -tutorial.pipeline.context: "{cullNone} füllt das Dreieck aus, ohne eine der beiden Flächenorientierungen zu verwerfen. Die Reihenfolge seiner Scheitelpunkte bestimmt die Flächenwindung; durch Deaktivieren des Cullings wird verhindert, dass diese Reihenfolge unser erstes Dreieck verbirgt." -tutorial.pipeline.description: Wir haben nun Scheitelpunktdaten, ein Eingabelayout und zwei Shader. Die {graphicsPipeline} verbindet sie und gibt an, wie die GPU Scheitelpunkte zu Primitiven zusammensetzt und das Ergebnis in ein Attachment schreibt. -tutorial.pipeline.details: "Eine Pipeline kombiniert programmierbare Shader-Stufen mit Festfunktionseinstellungen, die GPU-Operationen wie Dreieckszusammensetzung, Face-Culling und Blending steuern. Wählen Sie für dieses Dreieck die folgenden Einstellungen:" -tutorial.pipeline.guidance: Das Farbformat stammt aus {swapChainDescFormat}. Es muss mit dem vom Renderpass verwendeten Bild übereinstimmen. {count1} bedeutet ein Sample pro Pixel. -tutorial.pipeline.item: "{triangleList} setzt jeweils drei aufeinanderfolgende Scheitelpunkte zu einem Dreieck zusammen. Wir übergeben drei Scheitelpunkte und zeichnen einmal, sodass kein Indexpuffer benötigt wird." -tutorial.pipeline.notes: "{depthNone} deaktiviert Tiefentests und -schreiben, passend zum Pass ohne Tiefen-Attachment." -tutorial.pipeline.reference: "{opaque} deaktiviert das Blending, sodass die Farbe des Fragment-Shaders den Hintergrund innerhalb des Dreiecks ersetzt." -tutorial.pipeline.title: Shader und Scheitelpunktlayout verbinden -tutorial.pipeline.usage: Die Shader-Objekte können nach dem Erstellen der Pipeline freigegeben werden, wie im Beispiel-Renderer gezeigt. Halten Sie die Pipeline selbst für jeden Frame gültig, der mit ihr zeichnet. Fügen Sie {pipelineDispose} vor {vertexBufferDispose} in die Bereinigung ein. Die Pipeline-Erstellung ist der letzte Initialisierungsschritt vor dem Render-Callback. -tutorial.pipeline.validation: Die Pipeline-Beschreibung deklariert die Attachment-Konfiguration; sie erstellt kein weiteres Bild. {inputLayouts} enthält einen Eintrag, da Position und Farbe zusammen in einem Puffer gespeichert sind. -tutorial.presentation.title: Die GPU mit dem Fenster verbinden -tutorial.project.context: Aktivieren Sie {emphasis} ({allowUnsafeBlocks}) in den Buildeinstellungen des Projekts. Wir verwenden dies, um Scheitelpunktdaten an die GPU zu übergeben, sowie für die nativen Aufrufe des Fenster-Helpers. +tutorial.input.title: "Vertex-Eingabelayout" +tutorial.lifecycle.description: "Jeder Frame folgt dieser Sequenz:" +tutorial.lifecycle.details: "Nach dem Schließen des Fensters kehrt {run} zurück, und die Ausführung wird mit der Bereinigung fortgesetzt. Da jeder Frame bereits auf den Abschluss seiner eingereichten Befehle gewartet hat, können die dafür verwendeten Ressourcen nun freigegeben werden. Nach {windowRun} steht die vollständige Bereinigung:" +tutorial.lifecycle.guidance: "Geben Sie die Swapchain vor ihrem nativen Fenster und den Kontext nach seinen Ressourcen frei. Eingereichte Befehlspuffer werden von der Warteschlange wiederverwendet; die Ausgabetextur wird von der Swapchain verwaltet. Beide benötigen daher keinen eigenen {dispose}-Aufruf." +tutorial.lifecycle.title: "Frame-Ablauf und Bereinigung" +tutorial.pipeline.behavior: "Erstellen Sie nach dem Eingabelayout die Pipeline:" +tutorial.pipeline.context: "{cullNone} deaktiviert das Face-Culling. Das Dreieck wird dadurch gezeichnet, unabhängig davon, ob seine Vertices im oder gegen den Uhrzeigersinn angeordnet erscheinen." +tutorial.pipeline.description: "Eine {graphicsPipeline} verbindet das Vertexlayout und die beiden Shader mit den Einstellungen für die Zusammenstellung der Primitive und die Ausgabe in Attachments." +tutorial.pipeline.details: "Die Shader verarbeiten Vertices und Fragmente. Die übrigen Pipeline-Einstellungen bestimmen die Primitivzusammenstellung, das Face-Culling, den Tiefentest und das Blending:" +tutorial.pipeline.guidance: "Das Farbformat muss dem Renderpass-Attachment entsprechen und wird deshalb aus {swapChainDescFormat} übernommen. {count1} legt ein Sample pro Pixel fest." +tutorial.pipeline.item: "{triangleList} setzt jeweils drei aufeinanderfolgende Vertices zu einem Dreieck zusammen." +tutorial.pipeline.notes: "{depthNone} deaktiviert Tiefentest und Tiefenschreiben entsprechend dem fehlenden Tiefen-Attachment." +tutorial.pipeline.reference: "{opaque} deaktiviert Blending. Die Fragmentfarbe ersetzt damit den Hintergrund innerhalb des Dreiecks." +tutorial.pipeline.title: "Grafikpipeline" +tutorial.pipeline.usage: "Shader-Objekte dürfen nach der Pipeline-Erstellung freigegeben werden. Geben Sie die Pipeline dagegen erst nach Abschluss des Renderings frei und ergänzen Sie dafür {pipelineDispose} vor {vertexBufferDispose} in der Bereinigung." +tutorial.presentation.title: "Grafikkontext und Präsentation" +tutorial.project.context: "Aktivieren Sie {emphasis} ({allowUnsafeBlocks}) in den Buildeinstellungen. Die nativen Fensteraufrufe und der Vertexupload benötigen unsicheren Code." tutorial.project.context.emphasis: Unsicheren Code zulassen -tutorial.project.description: "Erstellen Sie das Projekt und wechseln Sie in dessen Verzeichnis:" -tutorial.project.details: "Installieren Sie die Pakete:" -tutorial.project.guidance: "{zenithNET} stellt die gemeinsame Rendering-API bereit. Die drei Backend-Pakete ermöglichen es demselben Programm, die Implementierung für seine Plattform auszuwählen. {zenithNETCompiler} kompiliert Slang-Shader – die kleinen GPU-Programme, die wir später schreiben – für diese Implementierung. Silk.NET liefert das Fenster und die Ereignisschleife." -tutorial.project.title: Konsolenprojekt erstellen -tutorial.requirements.context: Sie können dieser Seite von einem leeren Projekt aus folgen. Das {link} und sein {detail} stehen als Referenz für die hier verwendeten Rendering- und Fenster-APIs zur Verfügung. +tutorial.project.description: "Erstellen Sie ein C#-Konsolenprojekt namens {firstTriangle} mit .NET 10 als Zielframework." +tutorial.project.details: "Fügen Sie dem Projekt die folgenden NuGet-Pakete hinzu:" +tutorial.project.guidance: "{zenithNET} liefert die gemeinsame API, die drei Backend-Pakete ihre Plattformimplementierungen. {zenithNETCompiler} übersetzt die unten eingeführten Slang-Shader für das Backend. Silk.NET übernimmt Fenster und Ereignisse." +tutorial.project.title: "Projekteinrichtung" +tutorial.requirements.context: "Das {link} und sein {detail} dienen als Referenzimplementierungen für dieses Tutorial." tutorial.requirements.context.detail: gemeinsamer Host tutorial.requirements.context.link: Hallo-Dreieck-Beispiel -tutorial.requirements.description: "Sie benötigen das {emphasis}, einen Code-Editor oder eine IDE sowie einen Desktop-PC mit einer GPU und einem Treiber, die von einem Zenith.NET-Backend unterstützt werden. Grundlegende Vertrautheit mit C# genügt; die Grafikkonzepte werden bei ihrer ersten Verwendung eingeführt. Dies ist ein gewöhnliches {net10}-Konsolenprojekt. Ein Backend übersetzt Zenith.NET-Operationen in Aufrufe einer Grafik-API wie DirectX 12, Metal oder Vulkan. Die Anwendung wählt beim Start eines davon aus:" +tutorial.requirements.description: "Sie benötigen das {emphasis} und C#-Grundkenntnisse. Die Anwendung verwendet das Zielframework {net10}. GPU und Treiber müssen das für Ihre Plattform gewählte Backend unterstützen:" tutorial.requirements.description.emphasis: .NET 10 SDK -tutorial.requirements.details: Linux benötigt eine X11-kompatible Fenstersitzung für den hier verwendeten Fensterpfad. Optionale Raytracing- und Mesh-Shading-Funktionen sind für dieses Dreieck nicht erforderlich. -tutorial.requirements.guidance: Zenith.NET rendert in eine von der Anwendung bereitgestellte Oberfläche. Silk.NET.Windowing erstellt das Desktop-Fenster und verarbeitet dessen Ereignisse. Unter macOS ist das Präsentationsziel ein Metal-Layer ({cAMetalLayerCs}); der Fenster-Helper des Tutorials bindet diesen Layer für uns ein. +tutorial.requirements.guidance: "Zenith.NET rendert in ein von der Anwendung bereitgestelltes Präsentationsziel. Silk.NET.Windowing erstellt das Fenster und verarbeitet Ereignisse. Unter macOS dient ein in {cAMetalLayerCs} repräsentierter Metal-Layer als Ziel; der Fenster-Helper verbindet ihn mit dem Fenster." tutorial.requirements.table.headings.graphicsBackend: Grafik-Backend tutorial.requirements.table.headings.platform: Plattform -tutorial.requirements.table.headings.windowSurface: Fensteroberfläche tutorial.requirements.table.linux.graphicsBackend: Vulkan 1.4 -tutorial.requirements.table.linux.platform: Linux -tutorial.requirements.table.linux.windowSurface: X11-Fenster und Display; XWayland ist ebenfalls geeignet +tutorial.requirements.table.linux.platform: "Linux (X11 oder XWayland)" tutorial.requirements.table.macOS.graphicsBackend: Metal 4 tutorial.requirements.table.macOS.platform: macOS -tutorial.requirements.table.macOS.windowSurface: An das Fenster angebundener Metal-Layer tutorial.requirements.table.windows.graphicsBackend: DirectX 12 tutorial.requirements.table.windows.platform: Windows -tutorial.requirements.table.windows.windowSurface: Win32-Fenster-Handle -tutorial.requirements.title: Bevor Sie beginnen -tutorial.resize.context: "Führen Sie {dotnetRun} erneut aus. Das Fenster sollte nun einen einheitlichen dunklen Hintergrund haben, der es auch nach einer Größenänderung weiterhin vollständig ausfüllt. Behalten Sie diesen Callback bei: Das Dreieck wird innerhalb seines bestehenden Renderpasses gezeichnet." -tutorial.resize.description: "Die Bilder der Swapchain müssen den Framebuffer-Abmessungen folgen. Verwenden Sie {framebufferResize}, um auf Änderungen der Pixelgröße zu reagieren, einschließlich Änderungen durch Anzeigeskalierung. Fügen Sie nach dem Render-Callback, weiterhin vor {windowRun}, Folgendes hinzu:" -tutorial.resize.details: Silk.NET unterscheidet Fenstergrößenänderungen von {link}. Wir benötigen Letzteres, da die Swapchain Pixel speichert. Ein minimiertes Fenster kann einen Framebuffer der Größe null haben. Beide Callbacks überspringen in diesem Fall ihre GPU-Arbeit. Nach einer Größenänderung verwendet der Renderpass die neuen Attachment-Abmessungen für seinen Viewport und Scissor. +tutorial.requirements.title: "Voraussetzungen" +tutorial.resize.context: "Erstellen und starten Sie die Anwendung erneut. Auch beim Ändern der Fenstergröße sollte der Hintergrund das gesamte Fenster ausfüllen: Jeder neue Renderpass übernimmt die Abmessungen des angepassten Attachments für Viewport und Scissor. Behalten Sie den Render-Callback bei; in diesem Pass wird später das Dreieck gezeichnet." +tutorial.resize.description: "Die Swapchain muss Änderungen der Framebuffer-Größe übernehmen. Registrieren Sie nach dem Render-Callback und vor {windowRun} einen Callback für {framebufferResize}:" +tutorial.resize.details: "Reagieren Sie auf {link}, die in Pixeln angegeben werden, statt auf Änderungen der logischen Fenstergröße. Wird beim Minimieren eine der beiden Framebuffer-Abmessungen null, lässt der Resize-Callback die Swapchain unverändert. Auch der Render-Callback kehrt bei einer Nullgröße sofort zurück. Das Rendering wird erst fortgesetzt, wenn wieder eine nutzbare Größe vorliegt." tutorial.resize.details.link: Framebuffer-Größenänderungen -tutorial.resize.guidance: Wir warten nach jeder Übermittlung, sodass kein früherer Frame die Bilder mehr verwendet, wenn der Resize-Handler sie ersetzt. Die aktuelle Implementierung von {present} wartet ebenfalls auf der Grafikwarteschlange. Diese einfache Schleife stellt sicher, dass die Arbeit eines Frames abgeschlossen ist, bevor der nächste beginnt; {link} behandelt fortgeschrittenere Ablaufsteuerungen. +tutorial.resize.guidance: "Der Render-Callback wartet vor {present}, bis die eingereichten Befehle des Frames abgeschlossen sind. Der Resize-Callback kann die Swapchain-Bilder daher ersetzen, ohne noch laufende Arbeit eines früheren Frames zu beeinträchtigen. Der Artikel {link} erläutert den Zusammenhang zwischen GPU-Abschluss und Ressourcenlebensdauer." tutorial.resize.guidance.link: Synchronisation -tutorial.resize.title: Auf Größenänderungen reagieren -tutorial.shaders.compilation.context: Die Kompilierung erfolgt einmalig während der Initialisierung. {appContextBaseDirectory} findet den kopierten Shader neben der ausführbaren Datei, unabhängig vom aktuellen Arbeitsverzeichnis. Diese Shader verarbeiten nur Scheitelpunkteingaben, daher müssen noch keine Konstantenpuffer, Texturen oder Ressourcen-Handles gebunden werden. -tutorial.shaders.compilation.description: Legen Sie in den Dateieigenschaften für {triangleSlang} die Option {emphasis} auf {detail} fest. Dadurch wird der Shader neben der ausführbaren Datei verfügbar gemacht. +tutorial.resize.title: "Größenänderungen" +tutorial.shaders.compilation.context: "Mit {appContextBaseDirectory} wird die kopierte Shader-Datei aus dem Ausgabeverzeichnis der Anwendung geladen. Ihr Speicherort wird deshalb auch dann korrekt ermittelt, wenn die Anwendung aus einem anderen Arbeitsverzeichnis gestartet wird." +tutorial.shaders.compilation.description: "Setzen Sie für {triangleSlang} die Dateieigenschaft {emphasis} auf {detail}. Der Build kopiert die Shader-Datei damit neben die ausführbare Datei." tutorial.shaders.compilation.description.detail: Kopieren, wenn neuer tutorial.shaders.compilation.description.emphasis: In Ausgabeverzeichnis kopieren -tutorial.shaders.compilation.details: "Kehren Sie zu {programCs} zurück. Fügen Sie nach dem Scheitelpunkt-Upload diese Initialisierungsanweisungen vor dem Render-Callback ein:" -tutorial.shaders.compilation.guidance: "{zenithCompiler} gibt eine Shader-Beschreibung zurück, die Code für die angeforderte Grafik-API enthält. {createShader} erstellt das entsprechende Backend-Objekt. Sowohl die Grafik-API als auch die Namen der Einstiegspunkte sind wichtig: Verwenden Sie {contextGraphicsApi} und schreiben Sie {vSMain} und {fSMain} exakt so wie in der Slang-Datei." -tutorial.shaders.compilation.title: Für das ausgewählte Backend kompilieren -tutorial.shaders.context: "{fSInput} verbindet die Ausgabe des Vertex-Shaders mit der Eingabe des Fragment-Shaders. Wenn es vom Vertex-Shader geschrieben wird, liefert {sVPOSITION} eine Clip-Space-Position: die vier Koordinaten, anhand derer die GPU bestimmt, was innerhalb des sichtbaren Bildes liegt. {cOLOR0} überträgt die zwischen den Scheitelpunkten zu interpolierende Farbe. Beide Stufen müssen hinsichtlich Typ und Semantik übereinstimmen." -tutorial.shaders.description: Ein Shader ist ein von der GPU ausgeführtes Programm. Dieser Zeichenvorgang benötigt einen Vertex-Shader zur Positionierung der Scheitelpunkte und einen Fragment-Shader zur Erzeugung der Farben innerhalb des Dreiecks. Wir werden sie in Slang schreiben, einer Shader-Sprache, und zwei Einstiegspunkte aus derselben Datei kompilieren. Ein Einstiegspunkt ist die Funktion, an der die Ausführung einer Shader-Stufe beginnt. -tutorial.shaders.details: "Erstellen Sie {triangleSlang}, beginnend mit diesen beiden Strukturen:" -tutorial.shaders.fragment.description: "Fügen Sie den Fragment-Einstiegspunkt an dieselbe Datei an:" -tutorial.shaders.fragment.details: Die Rasterung bestimmt, welche Bildbereiche das Dreieck abdeckt. Sie erzeugt Fragmente – die vom Fragment-Shader verarbeiteten Daten – mit über den abgedeckten Bereich interpolierten Scheitelpunktfarben. {fSMain} gibt diese interpolierte Farbe über {sVTARGET} zurück, was das erste Farb-Attachment identifiziert. -tutorial.shaders.fragment.guidance: Die Interpolation der Scheitelpunktfarben ist getrennt vom Blending der Attachments zu betrachten. Blending kombiniert die Ausgabe eines Fragments mit der bereits im Attachment gespeicherten Farbe. Unser opaker Blend-Zustand deaktiviert diese Kombination, sodass die interpolierte Farbe den Hintergrund innerhalb des Dreiecks ersetzt. -tutorial.shaders.fragment.title: Die Fragmente einfärben -tutorial.shaders.guidance: "{vSInput} beschreibt, was der Vertex-Shader aus dem Scheitelpunktpuffer empfängt. Die Semantiken {pOSITION0} und {cOLOR0} identifizieren die Eingaben; C#-Feldnamen allein begründen diese Zuordnung nicht." -tutorial.shaders.title: Die beiden Shader-Stufen schreiben -tutorial.shaders.vertex.description: "Fügen Sie den Vertex-Einstiegspunkt an {triangleSlang} an:" -tutorial.shaders.vertex.details: Die GPU ruft diesen Einstiegspunkt für jeden Eingabescheitelpunkt auf. Er fügt der Position die homogene Koordinate {w} hinzu und leitet die Farbe weiter. Nach der Vertex-Stufe wird die Position durch w geteilt; hier lässt diese Division x, y und z unverändert. Aus diesem Grund können die oben gewählten Positionen direkt als normalisierte Gerätekoordinaten verstanden werden. -tutorial.shaders.vertex.title: Jeden Scheitelpunkt positionieren -tutorial.surface.description: "Der Kontext muss auch wissen, wo er seine Ausgabe anzeigen soll. Fügen Sie Folgendes {emphasis} hinzu:" +tutorial.shaders.compilation.details: "Fügen Sie in {programCs} nach dem Vertexupload und vor dem Render-Callback die Shader-Initialisierung ein:" +tutorial.shaders.compilation.guidance: "{zenithCompiler} kompiliert den Quelltext für {contextGraphicsApi}; {createShader} erstellt aus der kompilierten Beschreibung ein Shader-Objekt. Die Einstiegspunktnamen {vSMain} und {fSMain} wählen die beiden Funktionen aus der Slang-Datei aus." +tutorial.shaders.compilation.title: "Shader kompilieren" +tutorial.shaders.context: "{fSInput} verbindet die beiden Shader-Stufen. Der Vertex-Shader schreibt eine Position im Clipraum nach {sVPOSITION}; daraus ermittelt die GPU den sichtbaren Teil des Dreiecks. {cOLOR0} enthält die Vertexfarbe, die vor der Übergabe an den Fragment-Shader über das Dreieck interpoliert wird. Typ und Semantik dieses Feldes müssen zwischen den Stufen übereinstimmen." +tutorial.shaders.description: "Shader sind Programme, die auf der GPU laufen. Der Vertex-Shader bestimmt die Position jedes Vertex, der Fragment-Shader die Farbe an den vom Dreieck bedeckten Bildpositionen. Beide Stufen stehen in einer Slang-Datei und haben jeweils einen eigenen Einstiegspunkt, also eine Funktion, mit der die Ausführung beginnt." +tutorial.shaders.details: "Erstellen Sie {triangleSlang} mit diesen Eingabe- und Ausgabestrukturen:" +tutorial.shaders.fragment.description: "Ergänzen Sie den Fragment-Einstiegspunkt in derselben Datei:" +tutorial.shaders.fragment.details: "Die Rasterisierung ermittelt die vom Dreieck bedeckten Bildpositionen und erzeugt dort Fragmente. Jedes Fragment erhält eine aus den drei Vertexfarben interpolierte Farbe. {fSMain} gibt diese Farbe zurück; {sVTARGET} leitet das Ergebnis an das erste Farb-Attachment weiter." +tutorial.shaders.fragment.title: "Fragment-Shading" +tutorial.shaders.guidance: "{vSInput} definiert die Vertex-Shader-Eingaben. {pOSITION0} und {cOLOR0} identifizieren Attribute über ihre Semantik; C#-Feldnamen stellen diese Zuordnung nicht her." +tutorial.shaders.title: "Shader-Stufen" +tutorial.shaders.vertex.description: "Ergänzen Sie den Vertex-Einstiegspunkt in {triangleSlang}:" +tutorial.shaders.vertex.details: "Die GPU ruft den Einstiegspunkt für jeden Vertex auf, ergänzt die homogene Koordinate {w} und übergibt die Farbe. Nach der Vertexverarbeitung wird die Position durch w geteilt. Hier ist w = 1; x, y und z bleiben unverändert und entsprechen normalisierten Gerätekoordinaten." +tutorial.shaders.vertex.title: "Vertex-Shading" +tutorial.surface.description: "Definieren Sie das native Präsentationsziel {emphasis}:" tutorial.surface.description.emphasis: nach {windowCenter} und vor {windowRun} -tutorial.surface.details: "{surface} beschreibt ein natives Präsentationsziel und seine Pixelabmessungen. Der Framebuffer ist das mit dem Fenster verknüpfte Pixelbild. {framebufferSize} gibt seine Abmessungen in Pixeln an; die logischen Abmessungen des Fensters können abweichen, wenn die Anzeigeskalierung aktiviert ist." -tutorial.surface.guidance: Die Oberfläche entspricht dem oben ausgewählten Backend. Windows liefert ein Fenster-Handle, Linux liefert ein X11-Display und -Fenster, und der macOS-Helper stellt den angebundenen Metal-Layer bereit. Dies ist der einzige plattformspezifische Teil der Verbindung unseres Fensters mit dem Rendering. -tutorial.surface.title: Die native Oberfläche beschreiben -tutorial.swapChain.context: "Die Swapchain verwendet sowohl den Kontext als auch das native Fenster. Ersetzen Sie die Zeile {windowDispose} am Ende von {programCs} durch diese Bereinigungsreihenfolge:" -tutorial.swapChain.description: "Verwenden Sie die Oberflächenbeschreibung, um die Bilder zu erstellen, die präsentiert werden sollen. Fügen Sie unmittelbar nach dem Oberflächenblock Folgendes hinzu:" -tutorial.swapChain.details: Die {swapChain} verwaltet die im Fenster angezeigten Bilder. In jedem Frame liefert uns {drawable} das aktuelle Bild als {texture}, den API-Typ für Bilddaten. Nach dem Zeichnen fordert {present} die Anzeige des Ergebnisses an und wechselt zum nächsten Drawable. -tutorial.swapChain.guidance: "{b8G8R8A8UNorm} speichert vier 8-Bit-Farbkanäle in der Reihenfolge Blau, Grün, Rot und Alpha. {uNorm} bedeutet, dass ganzzahlige Werte von 0 bis 255 Werte von 0 bis 1 darstellen. Der Shader gibt weiterhin einen logischen RGBA-Wert zurück; dieses Format bestimmt, wie diese Kanäle im Bild gespeichert werden. Später wird die Grafikpipeline {swapChainDescFormat} verwenden, um dieses Attachment abzugleichen." -tutorial.swapChain.title: Die Swapchain erstellen +tutorial.surface.details: "Der Framebuffer ist das Fensterbild in Pixeln. {surface} beschreibt das native Präsentationsziel und seine Abmessungen; {framebufferSize} liefert die Pixelgröße. Bei aktiver Anzeigeskalierung kann sie von der logischen Fenstergröße abweichen." +tutorial.surface.guidance: "Die Oberflächenbeschreibung liefert die nativen Handles des gewählten Backends: ein Win32-Fenster unter Windows, X11-Display und -Fenster unter Linux oder den angebundenen Metal-Layer unter macOS." +tutorial.surface.title: "Native Oberfläche" +tutorial.swapChain.context: "Die Swapchain hängt von Kontext und Fenster ab. Ersetzen Sie {windowDispose} am Ende von {programCs} durch diese Freigabereihenfolge:" +tutorial.swapChain.description: "Erstellen Sie unmittelbar nach der Oberflächenbeschreibung die Swapchain:" +tutorial.swapChain.details: "Die {swapChain} verwaltet die angezeigten Bilder. {drawable} liefert das aktuelle Bild als {texture}, den Bildressourcentyp der API. Nach dem Rendering fordert {present} die Anzeige an und wechselt zur nächsten Ausgabetextur." +tutorial.swapChain.guidance: "{b8G8R8A8UNorm} speichert vier 8-Bit-Kanäle in Blau-, Grün-, Rot- und Alpha-Reihenfolge. {uNorm} bildet die Ganzzahlen von 0 bis 255 auf den Bereich von 0 bis 1 ab. Der Shader gibt die Farbe weiterhin in der logischen RGBA-Reihenfolge aus; das Format bestimmt ihre Speicherung. Die Pipeline übernimmt das Farbformat aus {swapChainDescFormat}, damit es zum Attachment passt." +tutorial.swapChain.title: "Swapchain" tutorial.title: Erstes Dreieck -tutorial.troubleshooting.description: "Lesen Sie zuerst jeden Fehler in der Konsole und nutzen Sie dann die früheren Kontrollpunkte, um die fehlgeschlagene Stufe zu identifizieren:" -tutorial.troubleshooting.details: "Verwenden Sie den {link} und den {detail}, um Scheitelpunktdaten, Eingabelayout und Zeichenoperation zu vergleichen. Das Beispiel organisiert Fensterverwaltung und Einreichung in einem gemeinsamen Host; dieses Tutorial hält den Anwendungsablauf in {programCs}. Fahren Sie mit {context} fort, um indexiertes Zeichnen, Transformationen und Tiefentests kennenzulernen." +tutorial.troubleshooting.description: "Konsolendiagnosen und die drei Kontrollpunkte grenzen den Fehler ein:" +tutorial.troubleshooting.details: "Der {link} und der {detail} dienen als Referenz für Vertexdaten, Eingabelayout und Zeichenbefehle. Das Beispiel verwaltet Fenster und Befehlseinreichung in einem gemeinsamen Host; dieses Tutorial belässt den Anwendungsablauf in {programCs}. Das Beispiel {context} ergänzt indexiertes Zeichnen, Transformationen und Tiefentests." tutorial.troubleshooting.details.context: Rotierender Würfel tutorial.troubleshooting.details.detail: Slang-Shader tutorial.troubleshooting.details.link: Beispiel-Renderer @@ -508,18 +497,17 @@ tutorial.troubleshooting.table.drawing.symptom: Der Hintergrund erscheint, aber tutorial.troubleshooting.table.headings.check: Prüfung tutorial.troubleshooting.table.headings.symptom: Symptom tutorial.troubleshooting.table.input.check: Überprüfen Sie den Stride von 28 Bytes und die Positions-/Farboffsets von 0 und 12. -tutorial.troubleshooting.table.input.symptom: Scheitelpunktpositionen oder -farben sind fehlerhaft +tutorial.troubleshooting.table.input.symptom: "Vertexpositionen oder -farben sind fehlerhaft" tutorial.troubleshooting.table.shaders.check: Überprüfen Sie die kopierte Datei {triangleSlang}, die Schreibweise des Einstiegspunkts und die vom Compiler gemeldete Diagnose. tutorial.troubleshooting.table.shaders.symptom: Der Schritt mit der Hintergrundfarbe funktioniert, aber das Laden der Shader schlägt fehl tutorial.troubleshooting.table.window.check: Bestätigen Sie, dass das .NET-Projekt kompiliert wird und der reine Fensterschritt in einer Desktop-Sitzung ausgeführt wird. Überprüfen Sie unter Linux, ob X11 oder XWayland verfügbar ist. tutorial.troubleshooting.table.window.symptom: Es öffnet sich kein Fenster -tutorial.troubleshooting.title: Die fehlgeschlagene Stufe überprüfen -tutorial.window.context: "{usingZenithTutorials} importiert den Namespace des Helpers. Jede C#-Datei verwendet ihre eigenen gewöhnlichen using-Direktiven, sodass der Interop-Import in beiden Dateien benötigt wird. Der Alias {buffer} verweist auf den Zenith.NET-Puffertyp und unterscheidet ihn von {systemBuffer}." -tutorial.window.description: Fügen Sie dem Projekt {cocoaHelperCs} hinzu und behalten Sie dessen Namespace bei. Fügen Sie {interopUsing} ganz oben in dieser Datei vor der Namespace-Deklaration ein. Der Helper bindet unter macOS einen Metal-Layer an das Fenster an; die anderen Plattformzweige rufen ihn nicht auf. -tutorial.window.details: "Ersetzen Sie die generierte {programCs} durch den folgenden Code. Sie verwendet Top-Level-Anweisungen, die der Reihe nach ohne explizite {main}-Methode ausgeführt werden. Spätere Abschnitte erläutern, an welchen Stellen Sie dieser Datei weiteren Code hinzufügen:" -tutorial.window.guidance: "{graphicsAPINone} weist Silk.NET an, ein Fenster ohne eigenen Grafikkontext zu erstellen. Wir werden diesen Kontext mit Zenith.NET erstellen. {initialize} erstellt das native Fenster und macht dessen Handles verfügbar. Ein Handle ist ein vom Fenstersystem bereitgestellter Bezeichner. {center} zentriert das Fenster, und {run} verarbeitet Ereignisse, bis es geschlossen wird. Die Ausführung fährt dann mit {dispose} fort, wodurch das Fenster freigegeben wird." -tutorial.window.notes: Führen Sie {dotnetRun} aus. Ein leeres Fenster sollte sich öffnen und auf Verschieben, Größenänderungen und Schließen reagieren. Sein Inhalt ist noch nicht definiert, da wir noch keine Rendering-Befehle eingereicht haben. Schließen Sie es, bevor Sie fortfahren. -tutorial.window.title: Ein Fenster öffnen +tutorial.troubleshooting.title: "Fehlerdiagnose" +tutorial.window.description: "Laden Sie {cocoaHelperCs} in das Projekt herunter. Die Hilfsklasse bindet den Metal-Layer an das macOS-Fenster." +tutorial.window.details: "Ersetzen Sie den erzeugten Inhalt von {programCs} durch den folgenden Code. Er verwendet Top-Level-Anweisungen, die ohne explizite {main}-Methode der Reihe nach laufen. Die folgenden Abschnitte geben jeweils die Stelle für zusätzlichen Code an:" +tutorial.window.guidance: "{graphicsAPINone} überlässt den Grafikkontext Zenith.NET. {initialize} erstellt das native Fenster und macht die Handles des Fenstersystems verfügbar. {center} platziert das Fenster in der Bildschirmmitte. {run} verarbeitet Ereignisse bis zum Schließen; danach gibt {dispose} das Fenster frei." +tutorial.window.notes: "Erstellen und starten Sie die Anwendung. Prüfen Sie, ob sich das Fenster öffnen, verschieben, in der Größe ändern und schließen lässt. Sein Inhalt ist noch nicht definiert, da keine Renderbefehle eingereicht wurden. Schließen Sie das Fenster, bevor Sie fortfahren." +tutorial.window.title: "Fenstererstellung" ui.action.copy: Kopieren ui.action.navigate: Navigieren ui.action.open: Öffnen @@ -542,12 +530,12 @@ ui.content.tutorial: Tutorial ui.contents.close: Inhaltsverzeichnis schließen ui.contents.open: Inhaltsverzeichnis öffnen ui.contents.title: Inhalt -ui.footer.caption: Modernes RHI für .NET. +ui.footer.caption: "Modernes RHI für .NET" ui.footer.label: Fußzeile ui.language.label: Sprache ui.language.unavailable: Nicht übersetzt ui.members.clear: Membersuche löschen -ui.members.close: Member-Suche schließen +ui.members.close: "Membersuche schließen" ui.members.empty: Keine passenden Member. ui.members.open: Zum Member wechseln ui.members.placeholder: Name oder Signatur… diff --git a/documents/locales/de-DE/translation.md b/documents/locales/de-DE/translation.md index a0d8b60a..243dac9d 100644 --- a/documents/locales/de-DE/translation.md +++ b/documents/locales/de-DE/translation.md @@ -8,6 +8,16 @@ Navigation, Kapitelreihenfolge, Anker, Links, Formatierung, Code und Bilder werd Bei der Übersetzung nur die Werte der eigenen `strings.yml` ändern. Die Schlüsselmenge muss exakt der englischen entsprechen. Keine Schlüssel eigenständig hinzufügen, löschen oder umbenennen, auch nicht bei ähnlich lautenden oder noch nicht gesehenen Oberflächentexten. Fehler im Original mit dem betroffenen Schlüssel an die Projektverantwortlichen melden. Zuerst die englische Quelle und die gemeinsamen Seiten berichtigen, dann die Übersetzungen nachziehen. +## Stil und Kontext + +Der Text soll wie eine technische Einführung lesbar sein: präzise, sachlich und zusammenhängend. Zuerst die Beziehung zwischen Vorgängen erklären, dann die Bedingungen und Grenzen. In Tutorials klare Arbeitsschritte und überprüfbare Ergebnisse nennen. Ein wissenschaftlicher Stil verlangt weder Passivkonstruktionen noch unnötig lange Sätze. + +Jeden Artikel in seiner Lesereihenfolge bearbeiten, mit angrenzenden Absätzen, Tabellen und Code. Ressourcenschlüssel sind Speichergrenzen, keine isolierten Übersetzungseinheiten. Linktexte und hervorgehobene Fragmente müssen im vollständigen Satz grammatisch passen. + +Überschriften, Bedienelemente sowie die sichtbaren Kurztexte der Startseite und die Fußzeilenbeschriftung erhalten keinen Schlusspunkt. Fließtext, Diagnosen und Bedienhinweise für assistive Technik behalten reguläre Satzzeichen. Pro Begriff eine etablierte Bezeichnung verwenden; englische Entsprechungen nicht vereinzelt in Klammern ergänzen. API-Namen, Dateien und Bezeichner tatsächlicher Einstellungen bleiben unverändert. + +Ein Satz sollte die aktuelle Handlung, eine Entwurfsentscheidung, ein überprüfbares Ergebnis oder eine notwendige Bedingung erklären. Aufzählungen ungenutzter Funktionen, pauschale Plattformhinweise und wiederholte Voraussetzungen entfallen. Überschriften und stilistisch aufgeteilte Sätze werden als Ganzes in natürlicher deutscher Wortstellung übersetzt. Die Slots `{accent}` und `{lineBreak}` des Startseitentitels sind verschiebbar; Gestaltung legt keine englische Wortstellung fest. Entfernte Passagen und ihre Schlüssel werden von der Projektpflege in Ausgangstext, gemeinsamem Markup und allen Wörterbüchern zusammen bereinigt. + ## Texte und Platzhalter Ganze Sätze oder Absätze in natürliches, sachliches Deutsch übersetzen. Voraussetzungen, Verneinungen, Einheiten, Handlungsschritte und Lebensdauerbedingungen erhalten. Keine zusätzlichen technischen Zusagen, Plattformanforderungen, Paketversionen oder Versionshinweise einführen. Produkt- und Paketnamen, Dateinamen sowie C#- und Slang-Bezeichner einschließlich Groß- und Kleinschreibung unverändert lassen. @@ -71,5 +81,5 @@ Vor der Abgabe Schlüssel und Platzhalter abgleichen. Startseite, Learn-Einstieg | shader | Shader | | swap chain | Swapchain | | texture | Textur | -| timeline | Zeitleiste | +| timeline | Timeline | | upload | Hochladen von Daten | diff --git a/documents/locales/en-US/strings.yml b/documents/locales/en-US/strings.yml index 8e4cc3d0..5ca2bb34 100644 --- a/documents/locales/en-US/strings.yml +++ b/documents/locales/en-US/strings.yml @@ -1,26 +1,25 @@ ### YamlMime:Resources -concepts.execution.context.description: A {graphicsContext} represents one backend device and provides its graphics, - compute and transfer queues. Create the buffers, textures, shaders and pipelines for a workload through the same - context. A resource or handle created by another context cannot simply be bound to this one's command buffers. -concepts.execution.context.details: Choose the backend for the platform and presentation surface. The API remains - shared, but device support still matters. {capabilities} exposes the device name and the {rayTracingSupported} - and {meshShadingSupported} flags. Check the corresponding flag before creating an optional workload, as the {link} - and {detail} samples do. These flags are not a complete list of format, memory or platform restrictions. +concepts.execution.context.description: A {graphicsContext} connects the application to a GPU device through a particular + backend and provides its graphics, compute, and transfer queues. Resources used together must belong to the same + context; buffers, textures, shaders, pipelines, and their handles cannot be bound across contexts. +concepts.execution.context.details: '{capabilities} reports the device name and supported features. Use {rayTracingSupported} + and {meshShadingSupported} to check support before creating the resources for those workloads. The {link} and + {detail} samples show these checks during initialization.' concepts.execution.context.details.detail: mesh shading concepts.execution.context.details.link: ray tracing -concepts.execution.context.title: The context connects resources and queues -concepts.execution.description: A Zenith.NET application creates GPU resources, records commands that use them, - and submits those commands to a queue. The CPU can continue while the GPU executes the submission. Keep resources - valid until that work finishes, even after the recording calls have returned. -concepts.execution.ownership.description: Here, ownership means responsibility for disposal. A C# reference keeps - a managed object reachable; it does not prevent an explicit {dispose} from destroying the native resource. Likewise, - submitting a command that uses a buffer does not transfer ownership of that buffer to the queue. -concepts.execution.ownership.details: On shutdown, stop submitting new work, wait for the last uses on every queue - involved, release the application's resources, then dispose the context. Context disposal releases its own queues - and internal helpers; it does not wait for all application work or dispose every resource the application created. -concepts.execution.ownership.guidance: Apply the same lifetime rules during rendering. Retain the completion value - for a resource's last use so you know when its bytes can be overwritten or the resource can be replaced. See - {link} for views and backing-resource lifetimes. +concepts.execution.context.title: Graphics context +concepts.execution.description: 'GPU work begins on the CPU: the application creates resources, records commands + that use them, and submits those commands to a queue. Submission allows the CPU to continue while the GPU executes + the work. The resources must remain available until that execution finishes.' +concepts.execution.ownership.description: Ownership determines who releases an object; GPU completion determines + when it can be released. Calling {dispose} releases native resources even if C# references to the object remain. + Submitting commands does not transfer ownership of their resources to the queue. +concepts.execution.ownership.details: At shutdown, stop submitting work and wait for the last resource use on every + participating queue. Then release the application's resources and dispose the context. The context releases its + queues and internal helpers, so this final step belongs after application work has completed. +concepts.execution.ownership.guidance: During rendering, track the completion of work that uses data you intend + to overwrite or resources you intend to replace. Wait for those uses to finish before modifying or releasing the + affected storage. {link} describes how views and their backing resources fit into this lifetime model. concepts.execution.ownership.guidance.link: Resource Management concepts.execution.ownership.table.applicationResources.object: Resources created by the application concepts.execution.ownership.table.applicationResources.ownership: The application disposes them after their last @@ -28,93 +27,89 @@ concepts.execution.ownership.table.applicationResources.ownership: The applicati concepts.execution.ownership.table.commandBuffers.object: Borrowed command buffers concepts.execution.ownership.table.commandBuffers.ownership: The queue manages and recycles them. concepts.execution.ownership.table.headings.object: Object -concepts.execution.ownership.table.headings.ownership: Who releases it? +concepts.execution.ownership.table.headings.ownership: Disposal responsibility concepts.execution.ownership.table.queues.object: Context queues and their timelines concepts.execution.ownership.table.queues.ownership: The context and queues manage them. concepts.execution.ownership.table.swapChainDrawable.ownership: The swap chain manages it. -concepts.execution.ownership.title: Keep ownership separate from GPU completion -concepts.execution.pipelines.description: A graphics pipeline combines shaders, the vertex input layout, the rule - for assembling vertices into primitives, attachment formats and render state. Set it before binding vertex, index - or constant data and issuing draw commands. Its attachment formats and sample count must match the render pass's - attachments. -concepts.execution.pipelines.details: A compute pipeline supplies the shader entry point for a dispatch, which launches - groups of GPU threads. Set it and its constants before dispatching. Compute dispatches belong outside graphics - render passes. Changing the pipeline is a change in how subsequent commands interpret their inputs; bind the data - required by the selected pipeline before using it. -concepts.execution.pipelines.guidance: The {link} shows the full graphics sequence. The {detail} records a dispatch - followed by a graphics pass that displays the result. +concepts.execution.ownership.title: Ownership and lifetime +concepts.execution.pipelines.description: A graphics pipeline defines the shaders, vertex input layout, primitive + assembly, attachment formats, and render state used by draw commands. Select the pipeline before binding vertex, + index, or constant data. Its attachment formats and sample count must agree with those of the render pass. +concepts.execution.pipelines.details: A compute pipeline selects the shader entry point for a dispatch. Bind the + pipeline and its constants before dispatching, outside a graphics render pass. +concepts.execution.pipelines.guidance: The {link} illustrates the graphics sequence. The {detail} adds a compute + dispatch before the graphics pass that displays its output. concepts.execution.pipelines.guidance.detail: compute sample concepts.execution.pipelines.guidance.link: triangle's render callback -concepts.execution.pipelines.title: A pipeline determines how commands interpret data -concepts.execution.queues.description: Start with {graphicsQueue} when a frame combines drawing, compute and copies. - Keeping dependent work on one queue makes its ordering easier to follow. -concepts.execution.queues.details: A queue accepts batches of commands for execution. Separate queues do not necessarily - correspond to separate hardware engines, so their work may not run simultaneously. Use another queue when the - workload can benefit from overlap, and add an explicit dependency when one queue consumes another queue's results. -concepts.execution.queues.guidance: When later commands depend on earlier writes, the application must also ensure - that those writes are available to the later commands. Submitting both command buffers to the same queue does - not establish every such dependency automatically. Commands can use different GPU stages, and later accesses may - need a barrier or texture transition. {link} explains the distinction between submission order and resource visibility. +concepts.execution.pipelines.title: Pipeline state +concepts.execution.queues.description: '{graphicsQueue} is the usual starting point for a frame that combines drawing, + computation, and copies. Keeping dependent operations on one queue simplifies their ordering.' +concepts.execution.queues.details: Separate queues allow independent workloads to be submitted separately, but they + do not necessarily correspond to independent hardware engines. Use additional queues when the work can benefit + from overlapping execution. When one queue uses data produced by another, connect their submissions with an explicit + dependency. +concepts.execution.queues.guidance: Within a queue, dependent operations can also require barriers or texture transitions + so that later accesses observe earlier writes. These memory dependencies are distinct from submission order; {link} + explains how to express them. concepts.execution.queues.guidance.link: Synchronization concepts.execution.queues.table.computeQueue.workToRecord: Compute dispatches and compatible transfer work, without graphics render passes. concepts.execution.queues.table.graphicsQueue.workToRecord: Render passes and drawing, plus compute and transfer operations used by the frame. concepts.execution.queues.table.headings.queue: Queue -concepts.execution.queues.table.headings.workToRecord: Work to record +concepts.execution.queues.table.headings.workToRecord: Supported work concepts.execution.queues.table.transferQueue.workToRecord: Upload, download and copy work, without drawing or compute dispatches. -concepts.execution.queues.title: Choose a queue for the work it will execute -concepts.execution.recording.context: The queue polls for completion and recycles finished command buffers. Call - {queueCommandBuffer} for each new recording; it may return a recycled instance. Do not dispose a borrowed command - buffer, submit it twice, or keep recording into it after submission. Record a given command buffer from one thread - at a time; the queue's internal locking does not protect concurrent edits to a command buffer. +concepts.execution.queues.title: Queue selection +concepts.execution.recording.context: 'The queue reclaims completed command buffers for reuse. Obtain one with {queueCommandBuffer} + for each recording, record from one thread at a time, and submit it once. After submission, leave the buffer to + the queue: do not modify, resubmit, or dispose it.' concepts.execution.recording.description: '{queueCommandBuffer} returns a {commandBuffer} with recording already - begun. Record the commands and their dependencies, then call {submit} once. Submission ends recording and returns - a {timelineValue} identifying a completion point on that queue.' -concepts.execution.recording.details: 'For example, after recording a frame into {commandBuffer}, the triangle submits - it and waits for completion with:' -concepts.execution.recording.guidance: '{submit} schedules the work; {wait} keeps the CPU from continuing until - that submission has completed. Recording a draw, ending a render pass and submitting a command buffer are separate - operations. Neither recording the draw nor ending the pass waits for the GPU.' -concepts.execution.recording.title: Recording does not execute commands + in progress. After recording the operations and their dependencies, call {submit} once. Submission ends recording + and returns a {timelineValue} that identifies the completion point on that queue.' +concepts.execution.recording.details: 'After recording a frame in {commandBuffer}, the triangle tutorial submits + it and waits for completion:' +concepts.execution.recording.guidance: Recording builds the command sequence; {submit} schedules that sequence for + execution. Calling {wait} then blocks the CPU thread until the submission completes. This makes the tutorial's + frame loop easy to follow, because each frame finishes before the next begins. +concepts.execution.recording.title: Recording and submission concepts.execution.title: Execution Model -concepts.platforms.description: Choose whether your application owns the native window and frame loop or uses - a UI rendering control. That choice determines who obtains the drawable, submits commands and presents the result. - The drawable is the texture used as the current frame's output. Offscreen graphics and compute work do not need - a window or swap chain. -concepts.platforms.frame.context: Add your pipeline bindings and draw commands inside that pass. End the pass before - returning. Do not submit the supplied command buffer or present independently, and do not dispose the command - buffer or drawable. If your handler uses the drawable in another layout, return it to {colorAttachment} for the - control's final transition. -concepts.platforms.frame.description: The integrations implement {iZenithView}. The application supplies its {graphicsContext}, - updates scene data in {updateRequested}, and records rendering in {renderRequested} using {renderEventArgs}. -concepts.platforms.frame.details: The control owns the frame boundary. It obtains the drawable and command buffer, - transitions the drawable to {colorAttachment}, invokes the handlers, then performs the submission and presentation - steps required by that framework. -concepts.platforms.frame.guidance: 'For an initialized {iZenithView} named {view}, with a context assigned, this - handler records a complete clear pass. It requires {usingZenithNET}:' -concepts.platforms.frame.notes: The controls transition from {undefined} at the start of each frame, so applications - cannot rely on the drawable's previous contents being preserved. Clear or render the required image each frame. - Keep persistent accumulation or cached rendering in an application-owned texture, then display that texture through - the view. -concepts.platforms.frame.reference: '{zenithViewHelperDrawableFormat} supplies the integrations'' default color - format. Check the actual event drawable when matching attachment formats, sample counts and dimensions.' -concepts.platforms.frame.title: Record into the frame supplied by a UI control -concepts.platforms.integration.context: WinForms, WPF and the Windows WinUI path require Windows. MAUI applications - need their target platform's workload and must register the control handler with {useZenithView}; see {extensionsCs}. - Framework support and backend support must both be satisfied. -concepts.platforms.integration.description: 'The controls share the event interface, but they do not all present - in the same way:' -concepts.platforms.integration.details: Bitmap readback copies rendered pixels into CPU memory before the UI displays - them. Shared-texture interop avoids that readback but may still require GPU copies and synchronization. The - shared {renderRequested} interface therefore does not imply identical presentation costs or native interop requirements. -concepts.platforms.integration.guidance: 'Use the package for the application''s framework; for example:' +concepts.platforms.description: Presentation can be managed by the application or by a UI rendering control. This + determines who acquires the current frame's output texture, records and submits the frame, and presents the result. + That output texture is called the drawable. +concepts.platforms.frame.context: Record pipeline bindings and draw commands inside the pass, then end it before + the handler returns. The control submits the commands and presents the result. The handler must not submit the + command buffer or dispose either supplied object. If it changes the drawable's layout, restore {colorAttachment} + before returning so the control can perform its final transition. +concepts.platforms.frame.description: The controls implement {iZenithView}. The application assigns {graphicsContext}, + updates scene data in {updateRequested}, and records commands in {renderRequested} using the supplied {renderEventArgs}. +concepts.platforms.frame.details: For each frame, the control acquires a drawable and a command buffer, transitions + the drawable to {colorAttachment}, and calls the update and render handlers. It then submits the recorded work + and presents the image using the framework's presentation mechanism. +concepts.platforms.frame.guidance: 'Add {usingZenithNET} to the file. For an initialized {iZenithView} named {view} + with a graphics context assigned, register this handler to clear its drawable:' +concepts.platforms.frame.notes: The initial transition uses {undefined}, which allows the previous image contents + to be discarded. Draw or clear the full image on each frame. Keep accumulated or cached rendering in an application-owned + texture, then draw that texture into the control's drawable. +concepts.platforms.frame.reference: '{zenithViewHelperDrawableFormat} provides the default color format used by + these integrations.' +concepts.platforms.frame.title: Rendering through a UI control +concepts.platforms.integration.context: WinForms, WPF, and the Windows WinUI integration run on Windows. For MAUI, + install the workload for the target platform and register the control handler with {useZenithView}, as shown in + {extensionsCs}. +concepts.platforms.integration.description: 'The event interface is shared, but the presentation mechanism depends + on the framework:' +concepts.platforms.integration.details: These implementations differ in how the GPU image reaches the UI. Bitmap + readback copies pixels into CPU memory before display. Shared-texture interop avoids that CPU copy but can still + require GPU copies and synchronization. Consider this presentation path, as well as the shared {renderRequested} + event, when choosing an integration. +concepts.platforms.integration.guidance: Add the integration package for your UI framework through NuGet. For Avalonia, + use {avaloniaPackage}. concepts.platforms.integration.table.avalonia.integration: Avalonia concepts.platforms.integration.table.avalonia.presentation: Renders to a texture and downloads pixels into a {writeableBitmap}. See {zenithViewCs} and {surfaceCs}. concepts.platforms.integration.table.headings.integration: Integration -concepts.platforms.integration.table.headings.presentation: How its image reaches the UI +concepts.platforms.integration.table.headings.presentation: Presentation mechanism concepts.platforms.integration.table.maui.integration: .NET MAUI concepts.platforms.integration.table.maui.presentation: Uses native surfaces on Android, iOS and Mac Catalyst, and shared-texture composition on Windows. See the {link}. @@ -130,49 +125,46 @@ concepts.platforms.integration.table.winUI.presentation: Renders into an importe concepts.platforms.integration.table.wpf.integration: WPF concepts.platforms.integration.table.wpf.presentation: Imports a shared Direct3D 11 texture, then copies through Direct3D interop to a surface displayed by {d3DImage}. See {surfaceCs}. -concepts.platforms.integration.title: Choose the presentation path as well as the framework -concepts.platforms.lifecycle.context: For a UI view, use the event drawable's {descWidth}, {descHeight}, {descFormat} - and {descSampleCount} when creating matching rendering resources. The control determines that drawable's resolution; - do not assume its logical dimensions or display scale always equal the texture dimensions. -concepts.platforms.lifecycle.description: For a native swap chain, pass framebuffer dimensions in pixels. Window - sizes expressed in logical units can differ when display scaling is enabled. Skip zero-size framebuffers, resize - the swap chain when its pixel size changes, and obtain {swapChainDrawable} for each frame. The drawable is owned - by the swap chain and can change after presentation or resize. -concepts.platforms.lifecycle.details: '{swapChainResize} changes the dimensions of the existing surface. {swapChainRefresh} - replaces the surface description, including its native handles. Before either operation, complete outstanding - uses of the affected resources. Dispose the swap chain before destroying its native presentation target.' -concepts.platforms.lifecycle.guidance: Recreate application-owned depth or offscreen textures whose size follows - the window, and update constants containing their handles. A pipeline can remain in use across a size change when - its attachment formats and sample count remain compatible. The {link} keeps its pipeline while replacing its depth - texture. +concepts.platforms.integration.title: Framework and presentation path +concepts.platforms.lifecycle.context: Use {descWidth}, {descHeight}, {descFormat}, and {descSampleCount} from the + drawable supplied by the render event when creating matching attachments. The event texture gives the render target's + actual dimensions; they should not be inferred from the control's layout size or display scale. +concepts.platforms.lifecycle.description: 'The swap chain uses the framebuffer''s width and height in pixels, which + can differ from the window''s logical dimensions under display scaling. Defer rendering and swap-chain resizing + while either dimension is zero. Obtain {swapChainDrawable} for each frame: the swap chain owns this texture and + may replace it after presentation or resizing.' +concepts.platforms.lifecycle.details: When framebuffer dimensions change, wait for outstanding GPU uses of the old + images before calling {swapChainResize}. To replace the native presentation target, pass its new surface description + and handles to {swapChainRefresh} after those uses finish. At shutdown, release the swap chain before destroying + its native presentation target. +concepts.platforms.lifecycle.guidance: If application-owned depth or offscreen textures follow the window size, + recreate them when that size changes and update constants that contain their handles. The pipeline can be reused + as long as the attachment formats and sample counts still match. The {link} demonstrates this separation between + resized textures and a reusable pipeline. concepts.platforms.lifecycle.guidance.link: spinning cube renderer -concepts.platforms.lifecycle.title: Keep the drawable's size and lifetime with its host -concepts.platforms.ownership.description: The application owns the context it assigns and the resources it creates - for rendering. The control owns its own presentation resources. Changing the view's {graphicsContext} property - makes the scheduler recreate the control's resources; it does not recreate the application's pipelines, buffers - or textures for the new context. -concepts.platforms.ownership.details: Coordinate resource replacement with the view's frame lifecycle. Stop the - view's frame activity and finish outstanding GPU uses before disposing application resources or the assigned context. - Removing a view does not transfer context ownership to the control. -concepts.platforms.ownership.guidance: The shared {frameSchedulerCs} dispatches frame work through the view's UI - dispatcher. Keep frame handlers focused on updating and recording the frame; lengthy CPU work there also delays - the UI. -concepts.platforms.ownership.title: Keep application resources outside the control's ownership -concepts.platforms.surface.context: A windowing library or UI framework supporting an operating system does not - guarantee that the selected GPU backend is available there. Device features, drivers and native surface support - still have to match. Check optional ray tracing and mesh shading through {contextCapabilities} before creating - those workloads. -concepts.platforms.surface.description: The {link} uses Silk.NET to create a window and process events. Zenith.NET - connects to that window through a {surface} description and a {swapChain}. A surface contains native handles and - dimensions; constructing the description does not create or own the operating-system window. -concepts.platforms.surface.description.link: triangle -concepts.platforms.surface.details: 'The handle must match the selected backend:' -concepts.platforms.surface.guidance: The tutorial's {appCs} shows the Windows, macOS and X11 choices. Its Linux - host supplies Xlib handles; using it in a Wayland session requires XWayland. A native Wayland application would - supply different handles through {surfaceWayland}. +concepts.platforms.lifecycle.title: Swap-chain dimensions and lifetime +concepts.platforms.ownership.description: The application owns the assigned context and its rendering resources; + the control owns its presentation resources. When the view's {graphicsContext} changes, the scheduler recreates + the control's resources for the new context. Recreate the application's pipelines, buffers, and textures for that + context as well. +concepts.platforms.ownership.details: Before replacing rendering resources, stop the view's frame activity and wait + for the GPU work that uses them. Only then release the old resources or context. The application remains responsible + for releasing the assigned context when the view is removed. +concepts.platforms.ownership.guidance: The shared {frameSchedulerCs} runs frame handlers through the view's UI dispatcher. + Keep those handlers focused on updating scene data and recording commands; lengthy CPU work there also delays + the interface. +concepts.platforms.ownership.title: Application and control ownership +concepts.platforms.surface.description: The {link} uses Silk.NET to create the window and process its events. Zenith.NET + receives the native window handles and dimensions through a {surface} description, which it uses to create a {swapChain}. + The application remains responsible for the operating-system window. +concepts.platforms.surface.description.link: triangle tutorial +concepts.platforms.surface.details: 'Surface handles must match the selected backend:' +concepts.platforms.surface.guidance: The sample host in {appCs} supports Windows, macOS, and X11. Its Linux window + supplies Xlib handles, so a Wayland session needs XWayland to run it. A native Wayland application supplies its + display and surface handles through {surfaceWayland}. concepts.platforms.surface.table.android.backend: Vulkan on Android. concepts.platforms.surface.table.apple.backend: Metal on Apple platforms. -concepts.platforms.surface.table.headings.backend: Backend path +concepts.platforms.surface.table.headings.backend: Backend and platform concepts.platforms.surface.table.headings.factory: Surface factory concepts.platforms.surface.table.headings.handles: Handles supplied by the host concepts.platforms.surface.table.wayland.backend: Vulkan with a native Wayland host. @@ -180,22 +172,21 @@ concepts.platforms.surface.table.wayland.handles: Wayland display and surface concepts.platforms.surface.table.win32.backend: DirectX 12 or Vulkan on Windows. concepts.platforms.surface.table.xlib.backend: Vulkan on Linux with X11 or XWayland. concepts.platforms.surface.table.xlib.handles: X11 display and window -concepts.platforms.surface.title: Supply a native surface when the application owns presentation +concepts.platforms.surface.title: Native presentation surfaces concepts.platforms.title: Platform Integration -concepts.resources.allocation.context: Start with context-created resources unless you need an allocator of your - own. When using a heap, dispose its placed resources before the heap itself, after all GPU work that uses them - finishes. -concepts.resources.allocation.description: A {heap} supplies memory in which you place resources at explicit byte - offsets. The application chooses those offsets and tracks which regions are in use. -concepts.resources.allocation.details: Use {contextGetSizeAndAlignment} with the exact buffer or texture description - before placing it. Choose an offset that is a multiple of the returned alignment, reserve the returned size, and - keep the resource inside the heap's total byte size. Keep live allocations in non-overlapping regions. Texture - storage can include backend-specific padding and alignment, so pixel count multiplied by bytes per pixel is not - an allocation-size calculation. -concepts.resources.allocation.guidance: For placed buffers, keep the buffer's residency consistent with the heap's - residency. Use GPU-only heaps for the ordinary GPU textures described here. Size and alignment are placement requirements, - not a promise that any resource can be placed into any heap on every backend. -concepts.resources.allocation.title: Place resources in a heap when allocation control is needed +concepts.resources.allocation.context: Resources placed in a heap depend on its storage for their entire lifetime. + After their final GPU use, release the resources before releasing the heap. +concepts.resources.allocation.description: Use a {heap} when the application needs to manage allocation itself. + A heap provides storage in which resources are placed at explicit byte offsets; the application chooses those + offsets and tracks the occupied regions. +concepts.resources.allocation.details: For each resource, call {contextGetSizeAndAlignment} with the buffer or texture + description that will be used to create it. Reserve the returned size at an offset that is a multiple of the returned + alignment, within the heap's bounds and without overlapping another live allocation. Texture sizes may include + backend-specific padding, so pixel count and bytes per pixel alone are insufficient to calculate their allocation + size. +concepts.resources.allocation.guidance: A buffer placed in a heap must specify the same residency as that heap. + For texture storage, use a GPU-only heap. +concepts.resources.allocation.title: Heap allocation concepts.resources.bufferUsages.table.constant.role: Shader parameters read through a constant-buffer binding. concepts.resources.bufferUsages.table.headings.role: Role concepts.resources.bufferUsages.table.headings.usage: Usage @@ -208,35 +199,34 @@ concepts.resources.bufferUsages.table.transferDst.role: Destination storage for concepts.resources.bufferUsages.table.transferSrc.role: Source data for a GPU copy. concepts.resources.bufferUsages.table.vertex.role: Vertex attributes fetched for drawing. concepts.resources.bufferUsages.title: Buffer usages -concepts.resources.description: Choose a resource description from the operations that will use it. A texture rendered - into, sampled by a shader and downloaded to the CPU needs all three uses declared, along with the synchronization - between them. Memory placement and resource lifetime are additional decisions. -concepts.resources.memory.context: For a CPU-accessible buffer, {map} gives the CPU an address. It does not wait - for the GPU to stop accessing the same bytes. {unmap} likewise does not submit work or wait for completion. Before - overwriting CPU-writable data, finish the GPU reads that still need its old contents. -concepts.resources.memory.description: 'A {bufferDesc} has a {residency} field. Choose it according to how the CPU - and GPU will access the data:' -concepts.resources.memory.details: Residency describes the intended CPU access to the allocation. It does not imply - that every device has separate physical CPU and GPU memory. The triangle uses {cpuWriteOnly} to initialize a small - vertex buffer directly. A large static mesh may instead benefit from GPU-only storage with a one-time upload. -concepts.resources.memory.guidance: '{textureDesc} has no residency field. Ordinary context-created textures use - GPU storage. Their public API provides upload and download operations for CPU data transfers, without exposing - a direct mapping method. Explicit heaps provide placement control, described below.' -concepts.resources.memory.table.cpuReadOnly.cPUAccess: Read mapped memory after the GPU copy finishes. +concepts.resources.description: A resource's description establishes how the application may use its storage. For + example, a texture used as a render target, sampled by a shader, and copied back to the CPU needs the usage flags + for all three operations. Memory placement determines CPU access, while synchronization and lifetime management + determine when the data can be accessed or the storage released. +concepts.resources.memory.context: 'For CPU-accessible buffers, {map} provides the address through which the CPU + reads or writes data. Mapping and {unmap} do not wait for GPU work: the application must wait for a GPU write + before reading its result, or for outstanding GPU accesses before modifying the same bytes.' +concepts.resources.memory.description: 'The {residency} field of {bufferDesc} specifies the intended CPU access + to the allocation:' +concepts.resources.memory.details: Residency expresses CPU access requirements, including on systems where the CPU + and GPU share physical memory. The triangle uses {cpuWriteOnly} to initialize its small vertex buffer directly. + For larger static geometry, an upload into GPU-only storage may be more suitable. +concepts.resources.memory.guidance: Textures created directly through the context use GPU storage. {textureDesc} + therefore has no residency field; the application exchanges texture data with CPU memory through uploads and downloads. +concepts.resources.memory.table.cpuReadOnly.cPUAccess: Read-only concepts.resources.memory.table.cpuReadOnly.typicalRole: Readback data produced by the GPU -concepts.resources.memory.table.cpuWriteOnly.cPUAccess: Write mapped memory after previous GPU readers finish. +concepts.resources.memory.table.cpuWriteOnly.cPUAccess: Write-only concepts.resources.memory.table.cpuWriteOnly.typicalRole: Data supplied or updated by the CPU -concepts.resources.memory.table.gpuOnly.cPUAccess: Transfer bytes through an upload or readback buffer. +concepts.resources.memory.table.gpuOnly.cPUAccess: None concepts.resources.memory.table.gpuOnly.typicalRole: Static geometry and GPU working data -concepts.resources.memory.table.headings.cPUAccess: CPU access +concepts.resources.memory.table.headings.cPUAccess: Intended CPU access concepts.resources.memory.table.headings.residency: Residency concepts.resources.memory.table.headings.typicalRole: Typical role -concepts.resources.memory.title: Choose memory for the CPU access you need -concepts.resources.textureUsages.description: Transfer usage flags describe the direction of GPU copies. CPU access - is a separate memory-placement choice, described below. -concepts.resources.textureUsages.details: Combining usage flags declares several roles; it does not perform the - operations or order their accesses. Textures still need the appropriate {link}, and their formats must support - the requested uses on the selected device. +concepts.resources.memory.title: CPU access and memory placement +concepts.resources.textureUsages.description: The transfer flags describe a resource's role as the source or destination + of a GPU copy. Whether the CPU can access the storage directly is a separate memory-placement choice. +concepts.resources.textureUsages.details: Usage flags declare the roles a texture may have. Moving between those + roles requires the corresponding {link}, and its format must support the requested uses on the selected device. concepts.resources.textureUsages.details.link: layout and synchronization concepts.resources.textureUsages.table.colorAttachment.role: A color attachment in a render pass. concepts.resources.textureUsages.table.depthStencilAttachment.role: A depth/stencil attachment in a render pass. @@ -250,173 +240,160 @@ concepts.resources.textureUsages.table.transferDst.role: Destination image stora concepts.resources.textureUsages.table.transferSrc.role: Source image data for a GPU copy. concepts.resources.textureUsages.title: Texture usages concepts.resources.title: Resource Management -concepts.resources.transfers.context: A download records a GPU copy into internal readback storage. The library - copies those bytes into the supplied CPU destination when it resets the completed command buffer for reuse. Keep - the destination allocated, and keep managed memory pinned, until the submission value's {wait} returns. -concepts.resources.transfers.description: 'An upload copies CPU data toward a GPU resource; a download copies resource - data back to CPU memory. The resource-level methods complete that transfer before returning:' -concepts.resources.transfers.details: Those waits cover the transfer they submit. They do not discover dependencies - on a different queue that was already reading or writing the resource. Establish those dependencies before calling - the resource-level method. A direct mapped copy also relies on the caller to ensure GPU completion. -concepts.resources.transfers.guidance: 'Use {commandBufferUpload} or {commandBufferDownload} when copies should - be recorded with other work. Their pointer lifetimes differ:' -concepts.resources.transfers.item: An upload copies the CPU source into an internal upload buffer, also called staging - memory, during the call. The source pointer only needs to remain valid for that call. -concepts.resources.transfers.notes: For a texture, a row stride is the byte distance between successive rows of - CPU data, and a slice stride is the byte distance between successive depth slices. They are not the texture's - internal GPU memory layout. See {link} for the completion and readback distinction. +concepts.resources.transfers.context: A download first copies GPU data into internal readback storage. The library + then copies it to the supplied CPU destination when it reclaims the completed command buffer. Calling {wait} on + the download's submission value completes both steps. Keep the destination allocated, and managed memory pinned, + until that call returns. +concepts.resources.transfers.description: 'Uploads copy CPU data into a GPU resource; downloads copy resource data + into CPU memory. The methods on buffers and textures complete this transfer before returning:' +concepts.resources.transfers.details: Before calling these methods, resolve any conflicting accesses on other queues. + A wait inside the method covers its own transfer; it does not establish a dependency on another queue. The direct + mapped-memory paths rely entirely on the caller to wait for conflicting GPU accesses. +concepts.resources.transfers.guidance: "To submit transfers together with other GPU work, record them with {commandBufferUpload} or {commandBufferDownload}. Upload sources and download destinations have different lifetime requirements:" +concepts.resources.transfers.item: During an upload call, the library copies the source data into temporary upload + storage, called staging memory. The GPU later reads from this storage, so the application's source pointer is + needed only until the call returns. +concepts.resources.transfers.notes: For texture transfers, row stride is the byte distance between successive rows + of CPU data; slice stride is the distance between successive depth slices. These values let the transfer copy + the CPU data into or out of the texture's GPU storage. {link} explains why GPU completion and delivery to a download + destination are separate steps. concepts.resources.transfers.notes.link: Synchronization -concepts.resources.transfers.table.bufferDownload.transfer: Direct CPU copy for {cpuReadOnly}; otherwise submits - a transfer-queue download and waits. -concepts.resources.transfers.table.bufferUpload.transfer: Direct CPU copy for {cpuWriteOnly}; otherwise submits - a transfer-queue upload and waits. +concepts.resources.transfers.table.bufferDownload.transfer: Copies directly from mapped memory for {cpuReadOnly}. + Otherwise, submits the download to the transfer queue and waits for it to finish. +concepts.resources.transfers.table.bufferUpload.transfer: Copies directly into mapped memory for {cpuWriteOnly}. + Otherwise, submits the upload to the transfer queue and waits for it to finish. concepts.resources.transfers.table.headings.method: Method -concepts.resources.transfers.table.headings.transfer: How it transfers data +concepts.resources.transfers.table.headings.transfer: Transfer behavior concepts.resources.transfers.table.textureTransfers.method: '{textureUpload} / {textureDownload}' -concepts.resources.transfers.table.textureTransfers.transfer: Use the graphics queue, transition the selected subresource - for the copy, transition to the requested final layout, and wait. -concepts.resources.transfers.title: Choose between an immediate transfer and recorded transfers -concepts.resources.usages.description: '{bufferUsages} and {textureUsages} are flag enums that declare a resource''s - intended roles. They are assigned to {bufferDescUsages} and {textureDescUsages}, respectively. A flag enum allows - several members to be combined with {value} when a resource has more than one role.' -concepts.resources.usages.title: Declare the required uses before creating a resource -concepts.resources.views.description: A {bufferView} describes a buffer region and its interpretation. A {textureView} - selects a compatible texture type, format and subresource range. A view shares the backing storage; it does not - copy the data or add usages that were missing when the resource was created. Its range is also not a portable - guarantee of shader bounds checking. -concepts.resources.views.details: Use the resource's own handle for its default view, or create a view when a different - region or compatible interpretation is needed. Keep C# references to the view and its backing resource while GPU - work can use them; a resource handle alone does not keep either object alive. Dispose them only after their last - GPU use has completed. After replacing either one, update constants that contain its old {link}. +concepts.resources.transfers.table.textureTransfers.transfer: Submits the copy and its texture transitions to the + graphics queue, then waits for completion. The selected subresource is left in the requested final layout. +concepts.resources.transfers.title: Immediate and recorded transfers +concepts.resources.usages.description: '{bufferUsages} and {textureUsages} are flag enums for declaring resource + roles. Assign them to {bufferDescUsages} and {textureDescUsages}, respectively. When a resource serves several + roles, combine the required members with {value}.' +concepts.resources.usages.title: Resource usages +concepts.resources.views.description: A {bufferView} describes a region of a buffer and how its data is interpreted. + A {textureView} selects a subresource range and a compatible texture type and format. Both refer to existing storage, + with the usages declared when that storage was created. View ranges describe access; they do not provide consistent + shader bounds checking across backends. +concepts.resources.views.details: A resource's own handle provides its default view. Create a separate view to select + a different region or compatible interpretation. Keep both the view and its backing resource alive until the GPU + has finished using them; a resource handle does not retain either object. When replacing either one, update any + constants containing the old {link}. concepts.resources.views.details.link: resource handle -concepts.resources.views.guidance: The {link} shows a depth texture replaced on resize. The {detail} shows an input - texture kept separate from its writable output. Both make the resource's lifetime follow the work that actually - uses it. -concepts.resources.views.guidance.detail: compute sample -concepts.resources.views.guidance.link: spinning cube -concepts.resources.views.title: Keep views and their backing resources usable together -concepts.shaders.binding.context: 'In the compute sample, {input} is filled with {inputTextureSampledHandle} and - {output} with {outputTextureStorageHandle}. Slang''s typed {descriptorHandle} tells the shader how to access each - resource:' -concepts.shaders.binding.description: '{setConstantBuffer} binds a buffer and byte offset for the current pipeline''s - constant data. It binds existing GPU-visible storage; it does not upload a C# value. Fill the buffer first, and - ensure earlier GPU readers have finished before overwriting its bytes.' -concepts.shaders.binding.details: 'Set the pipeline before its constant buffer. For a compute workload with resources - already created and uploaded, recording uses this order:' -concepts.shaders.binding.guidance: This fragment assumes a recording {commandBuffer}, a {computePipeline}, an - uploaded {constantBuffer} with {bufferUsagesConstant} usage, and the thread-group counts for the workload. Offset - 0 binds the start of the buffer. If several constant-data records share one buffer, each record's starting offset - must meet the backend's binding alignment. That requirement is separate from the field layout inside the record. -concepts.shaders.binding.notes: '{resourceHandle} stores two 32-bit fields, but its interpretation belongs to the - backend. Do not treat it as a universal descriptor index, address or value that can be transferred between contexts. - A handle does not create a resource, add a missing usage or perform synchronization.' -concepts.shaders.binding.reference: Keep references to the resource and any view used to obtain its handle, and - dispose them only after the shader's last use completes. When replacing a texture or view, update the constants - that contain its old handle. {link} explains that lifetime relationship. +concepts.resources.views.title: Views and backing resources +concepts.shaders.binding.context: 'The compute sample assigns {inputTextureSampledHandle} to {input} and {outputTextureStorageHandle} + to {output}. In Slang, the type parameter of {descriptorHandle} defines how the shader accesses each resource:' +concepts.shaders.binding.description: '{setConstantBuffer} selects an existing buffer and byte offset from which + the current pipeline reads its constants. Upload the parameter data into that storage before it is used by the + shader. If the same bytes are still being read by earlier GPU work, wait for that work before updating them.' +concepts.shaders.binding.details: 'With a command buffer, compute pipeline, populated constant buffer, and thread-group + counts ready, record the dispatch in this order. Select the pipeline first, because the constant-buffer binding + applies to that pipeline:' +concepts.shaders.binding.guidance: Here, {commandBuffer} records a dispatch using {computePipeline} and the parameters + stored in {constantBuffer}. The buffer requires {bufferUsagesConstant} usage, and offset 0 selects its beginning. + If several constant records share one buffer, each record's starting offset must also meet the backend's binding + alignment, independently of the layout of fields within the record. +concepts.shaders.binding.notes: '{resourceHandle} contains two 32-bit fields whose interpretation depends on the + backend. Its values are valid only within the context that created the resource.' +concepts.shaders.binding.reference: Retain the resource and any view used to obtain its handle until the shader's + final access completes. Replacing a texture or view requires updating constants that still contain the old handle. + The ownership rules are described in {link}. concepts.shaders.binding.reference.link: Resource Management -concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: Read structured elements of shader type {t}. -concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: Read or write structured elements of shader - type {t}. +concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: Reads of structured elements of shader type {t} +concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: Reads and writes of structured elements of shader + type {t} concepts.shaders.binding.table.headings.access: Intended access concepts.shaders.binding.table.headings.cHandle: C# handle concepts.shaders.binding.table.headings.slangFieldType: Slang field type -concepts.shaders.binding.table.samplerHandle.access: Supply texture sampling state. -concepts.shaders.binding.table.textureSampledHandle.access: Read a texture. -concepts.shaders.binding.table.textureStorageHandle.access: Read or write a storage texture. -concepts.shaders.binding.title: Bind the constant buffer and the resources it describes -concepts.shaders.compilation.description: '{zenithCompiler} compiles a named Slang entry point and returns a {shaderDesc}. - Use the context''s {graphicsApi} so the result targets the backend that will create the shader: DXIL for DirectX - 12, a Metal library for Metal, or SPIR-V for Vulkan.' -concepts.shaders.compilation.details: 'For example, with an existing {context} and the triangle''s shader copied - beside the executable:' -concepts.shaders.compilation.guidance: '{vSMain} must exactly match the entry-point name in the shader file. Keep - shader objects valid while creating the pipeline, then dispose them after pipeline creation, as shown in {link}. - Perform this initialization once rather than recompiling for every frame.' +concepts.shaders.binding.table.samplerHandle.access: Texture sampling state +concepts.shaders.binding.table.textureSampledHandle.access: Texture reads +concepts.shaders.binding.table.textureStorageHandle.access: Storage-texture reads and writes +concepts.shaders.binding.title: Constant buffers and resource handles +concepts.shaders.compilation.description: '{zenithCompiler} compiles a named Slang entry point into a {shaderDesc}. + The context''s {graphicsApi} selects the required target: DXIL for DirectX 12, a Metal library for Metal, or SPIR-V + for Vulkan.' +concepts.shaders.compilation.details: 'With a graphics context named {context} already created, compile the triangle + shader from the copy placed beside the executable:' +concepts.shaders.compilation.guidance: The entry-point name {vSMain} must match the declaration in the shader file. + Compile shaders and create pipelines during initialization, then reuse the pipelines while rendering. Once pipeline + creation has completed, the shader objects may be released, as shown in {link}. concepts.shaders.compilation.guidance.link: First Triangle -concepts.shaders.compilation.title: Compile an entry point for the selected context -concepts.shaders.description: 'A shader receives data supplied by the application. Vertex attributes describe individual - vertices; buffers hold parameters or arrays; resource handles identify other resources the shader will access. - The C# declarations and Slang declarations must agree on what those values mean. Matching a field name is not - enough: layout, resource access and binding all need to match.' -concepts.shaders.dispatch.description: '{dispatch} takes the number of thread groups. The compute sample''s {numthreads} - entry point runs 16 × 16 threads per group. Divide the image dimensions by 16 and round up to find the group counts. - For example, a 17 × 19 image needs 2 × 2 groups. The shader checks its pixel coordinates against the image dimensions - because the last groups can contain threads outside the image.' -concepts.shaders.dispatch.details: The compiler stores the entry point's declared group size in {shaderDescThreadGroupSize}; - it does not convert pixel dimensions supplied to {dispatch} into group counts. Use {computeShaderRendererCs} with - its shader for the complete binding and dispatch example, and {link} before another pass consumes the output. +concepts.shaders.compilation.title: Shader compilation +concepts.shaders.description: The C# and Slang declarations must agree on where each value is stored and how the + shader accesses it. Vertex input layouts describe vertex attributes; shader buffer declarations describe parameters + and arrays; resource handles identify the resources used by a shader. +concepts.shaders.dispatch.description: '{dispatch} specifies how many thread groups to execute. The compute sample + declares {numthreads}, so each group contains 16 × 16 threads. To cover an image, divide its width and height + by 16 and round each result up: a 17 × 19 image requires 2 × 2 groups. The shader checks each thread''s coordinates + and skips those outside the image.' +concepts.shaders.dispatch.details: The declared group size is available in {shaderDescThreadGroupSize} and can be + used to calculate the group counts passed to {dispatch}. {computeShaderRendererCs} shows the complete calculation. + After the dispatch, access to the resulting image must follow the requirements described in {link}. concepts.shaders.dispatch.details.link: Synchronization -concepts.shaders.dispatch.title: Dispatch thread groups, not pixels -concepts.shaders.layout.context: 'The {link} make their offsets explicit. This declaration needs {systemRuntimeInteropServices} - and {zenithNET} in scope:' +concepts.shaders.dispatch.title: Thread groups +concepts.shaders.layout.context: 'The {link} illustrate this arrangement with image dimensions and two texture handles. + Explicit offsets specify where each field begins. The declaration uses {systemRuntimeInteropServices} and {zenithNET}:' concepts.shaders.layout.context.link: compute sample's C# constants -concepts.shaders.layout.description: For vertex input, the pipeline's {inputLayout} describes formats, offsets, - stride and semantics. The triangle's {float3} position followed by a {float4} color occupies 28 bytes, with color - at byte 12. {inputLayoutAdd} computes this packed layout; it does not inspect the C# struct. If the C# fields - contain padding, supply a matching layout instead of assuming the fields are packed. -concepts.shaders.layout.details: Constant buffers hold shader parameters, while structured buffers hold arrays of - elements of a declared type. Both are read according to their Slang declarations. They do not use {inputLayout}. - Verify field offsets and element sizes for the compiled shader representation, including padding. An unmanaged - C# type is suitable for copying as bytes, but that alone does not prove it matches a shader type. In particular, - do not apply a vertex's tightly packed {float3} layout to every shader buffer. -concepts.shaders.layout.guidance: A resource handle is a small value that refers to an existing resource. Copying - the handle into a constant buffer does not copy the resource's contents. -concepts.shaders.layout.notes: 'The corresponding declaration in {computeShaderSlang} is:' -concepts.shaders.layout.reference: The dimensions occupy the first eight bytes, followed by two eight-byte resource - handles. The C# sample reserves 256 bytes in total. That size is the sample's chosen storage size, not a rule - that all Slang structs or constant payloads occupy 256 bytes. Padding the total size also does not correct a field - at the wrong offset. -concepts.shaders.layout.title: Vertex input and shader data have different layout rules -concepts.shaders.matrices.description: The compiler requests row-major matrix storage, which stores each row's elements - together. The {link} places three {matrix4x4} values at offsets 0, 64 and 128. Its {detail} uses {mulVectorMatrix} - in model, view and projection order. +concepts.shaders.layout.description: 'For vertex input, {inputLayout} describes each attribute''s format, offset, + and semantic, together with the stride between vertices. The triangle places a {float3} position before a {float4} + color: the color starts at byte offset 12, and each vertex occupies 28 bytes. {inputLayoutAdd} calculates this + packed layout from the element formats. If the C# struct contains padding, supply offsets and a stride that account + for it.' +concepts.shaders.layout.details: "Constant buffers hold shader parameters, and structured buffers hold arrays of typed elements. Their layouts follow the Slang declarations rather than {inputLayout}. Match the C# field offsets, element sizes, and padding to the compiled shader layout. A C# unmanaged type can be copied as bytes, but its memory layout does not necessarily match the shader's layout; the tightly packed {float3} used for a vertex may require different alignment in a shader buffer." +concepts.shaders.layout.guidance: Shader parameters can include resource handles as well as ordinary values. A handle + identifies storage that already exists, so copying the handle into a constant buffer does not copy the resource's + contents. +concepts.shaders.layout.notes: 'The matching declaration in {computeShaderSlang} is:' +concepts.shaders.layout.reference: The two dimensions occupy the first eight bytes, followed by two eight-byte handles. + The C# sample reserves 256 bytes for the complete record. For another record, determine its size from its own + fields and the required layout and alignment. +concepts.shaders.layout.title: Data layout +concepts.shaders.matrices.description: The compiler selects row-major matrix storage, keeping each row contiguous. + The {link} stores three {matrix4x4} values at offsets 0, 64, and 128. Its {detail} applies {mulVectorMatrix} in + model, view, and projection order. concepts.shaders.matrices.description.detail: shader concepts.shaders.matrices.description.link: spinning cube renderer -concepts.shaders.matrices.details: Storage order determines how matrix elements occupy memory; multiplication order - determines the transformation. Keep both sides consistent. Adding a transpose without checking those two choices - can conceal one mismatch while introducing another. -concepts.shaders.matrices.title: Keep matrix storage and multiplication consistent +concepts.shaders.matrices.details: Storage order specifies how matrix elements are arranged in memory; multiplication + order specifies the transformation. Use matching conventions in C# and Slang. +concepts.shaders.matrices.title: Matrix conventions concepts.shaders.title: Shader Data and Binding -concepts.synchronization.backends.description: DirectX 12 and Vulkan encode texture transitions with layout and - access information. Metal has no operation in Zenith.NET's {transition} implementation. Metal groups recorded - work into render and compute encoders. The backend inserts visibility barriers when it ends these groups, making - earlier writes available to later work. Explicit {barrier} calls handle dependencies such as successive compute - dispatches within the same encoder. -concepts.synchronization.backends.details: This distinction matters when changing a workload. In the {link}, the - dispatch is followed by a graphics render pass, which also creates an encoder boundary on Metal. Two dependent - compute dispatches do not create that boundary merely by changing the texture's declared layout. Keep the transitions - required by the shared API, and separately identify the dependency between the actual producing and consuming - commands. +concepts.synchronization.backends.description: DirectX 12 and Vulkan encode texture transitions as layout and access + changes. Metal has no equivalent operation in Zenith.NET's {transition} implementation. The Metal backend instead + groups commands into render and compute encoders and inserts visibility barriers when an encoder ends. Dependent + operations within one encoder, such as successive compute dispatches, use explicit {barrier} calls. +concepts.synchronization.backends.details: In the {link}, starting the graphics render pass ends the compute encoder, + making its output visible to the graphics work. Two successive compute dispatches remain in the same encoder, + so their dependency needs a barrier even if a texture transition is recorded between them. This is why portable + command sequences account for access dependencies as well as texture layouts. concepts.synchronization.backends.details.link: compute sample -concepts.synchronization.backends.title: A transition is not identical on every backend -concepts.synchronization.barriers.context: '{barrierStagesAll} is a broader scope, not an automatic dependency detector. - Select stages that actually cover the work, and use them only on a queue that supports those operations.' -concepts.synchronization.barriers.description: 'Consider two compute dispatches: the first writes simulation data, - and the second reads that data to perform the next step. Both use storage buffers, so there is no texture layout - to change. Insert this between the dispatches on their command buffer:' -concepts.synchronization.barriers.details: The first argument identifies the producing stage and the second the - consuming stage. The barrier establishes the corresponding execution and memory dependency on the GPU. The backend - translates those stages into its execution and memory-access rules. This barrier does not change a texture's layout - or wait for all work on the device. -concepts.synchronization.barriers.guidance: The {link} uses this pattern between dependent dispatches. Place a barrier - where the dependency occurs. A barrier after the consumer has already been recorded cannot order that consumer - after an earlier producer. +concepts.synchronization.backends.title: Backend behavior +concepts.synchronization.barriers.context: Choose stages that include the relevant accesses and are supported by + the queue. {barrierStagesAll} includes every supported stage; select a narrower set when the dependency only involves + those stages. +concepts.synchronization.barriers.description: 'Consider two compute dispatches recorded into the same command buffer, + where the first writes simulation data and the second reads it. Place a barrier between them so that the second + dispatch sees the completed writes. For a storage buffer, this orders the accesses without a texture layout transition:' +concepts.synchronization.barriers.details: The first argument identifies the stages that produced the data; the + second identifies the stages that will consume it. Together they describe the execution order and memory visibility + required between the two dispatches. +concepts.synchronization.barriers.guidance: The {link} uses this pattern between simulation steps. Each barrier + follows the dispatch that produces the data and precedes the dispatch that uses it. concepts.synchronization.barriers.guidance.link: FluidTank simulation -concepts.synchronization.barriers.title: Order dependent commands with a barrier -concepts.synchronization.dependencies.description: For each shared resource, identify the operation that accesses - it first, the operation that follows, and whether either access writes. Reading the same data twice does not require - ordering to protect its contents, although layout changes or presentation can impose other requirements. A write - followed by a read, a read followed by an overwrite, or two writes can require a dependency. -concepts.synchronization.dependencies.details: 'Then choose the mechanism for where those operations execute:' -concepts.synchronization.dependencies.guidance: These mechanisms are related, but not interchangeable. Submitting - commands in order does not replace every memory dependency. A queue wait does not declare a new texture layout, - and a command barrier does not wait on the calling CPU thread. +concepts.synchronization.barriers.title: Pipeline barriers +concepts.synchronization.dependencies.description: For each resource, identify the accesses that touch the same + data. If either access writes, preserve the required order between them. Two reads do not conflict, although texture + layout and presentation requirements still apply. CPU updates and resource disposal also need to wait until the + GPU has finished using the affected storage. +concepts.synchronization.dependencies.details: 'The appropriate mechanism depends on where the operations execute:' +concepts.synchronization.dependencies.guidance: A workload may need more than one mechanism. For example, a texture + produced on another queue needs a submission dependency and the appropriate layout for its next use. Neither operation + requires blocking the CPU unless the CPU itself needs to access or release the data. concepts.synchronization.dependencies.table.cpuAccess.mechanism: Call {wait} on the relevant completion value. -concepts.synchronization.dependencies.table.cpuAccess.situation: The CPU must wait before accessing or releasing - data -concepts.synchronization.dependencies.table.crossQueue.mechanism: Pass its {timelineValue} to the consuming command - buffer's {submit}. -concepts.synchronization.dependencies.table.crossQueue.situation: A submission on another queue produces the data +concepts.synchronization.dependencies.table.cpuAccess.situation: CPU access or resource release depends on GPU completion +concepts.synchronization.dependencies.table.crossQueue.mechanism: Pass the producer's {timelineValue} to the consumer's + {submit}. +concepts.synchronization.dependencies.table.crossQueue.situation: One queue consumes data produced on another queue concepts.synchronization.dependencies.table.headings.mechanism: Mechanism concepts.synchronization.dependencies.table.headings.situation: Situation concepts.synchronization.dependencies.table.layoutChange.mechanism: '{commandBufferTransition} with its previous @@ -425,222 +402,202 @@ concepts.synchronization.dependencies.table.layoutChange.situation: A texture su concepts.synchronization.dependencies.table.pipelineStages.mechanism: '{commandBufferBarrier} with the producing and consuming stages.' concepts.synchronization.dependencies.table.pipelineStages.situation: Dependent GPU stages in a command stream -concepts.synchronization.dependencies.title: Start with the producer and the consumer -concepts.synchronization.description: A command that reads data written by an earlier command depends on those - writes being finished and visible to it. The writer is the producer; the reader is the consumer. The CPU also - needs a completion point before reading, overwriting or releasing shared data. Zenith.NET provides barriers, - texture transitions and timelines for these different dependencies. -concepts.synchronization.layouts.context: '{undefined} means the previous contents need not be preserved. It is - suitable for a new image or an attachment that will be fully cleared. It is not a way to avoid tracking the layout - of an image whose contents will be loaded, sampled or accumulated into.' -concepts.synchronization.layouts.description: 'Usage flags describe which roles a texture supports. {textureLayout} - describes how a particular subresource will be accessed for an operation. A subresource is a selected mip level - and array layer. Changing its layout prepares that access; it does not convert the texture to a different pixel - format. For example, the compute sample writes an output texture in {storage} layout and then samples it in a - graphics pass. Between those uses it records:' -concepts.synchronization.layouts.details: This fragment assumes that {outputTexture} was created with {sampledStorage} - usage and that its selected subresource is in {storage} layout. {default} selects mip level 0 and array layer - 0. The operation does not transition every mip or layer of a texture. -concepts.synchronization.layouts.guidance: The application supplies the previous layout. {transition} does not maintain - an application-visible layout tracker or infer that value from earlier commands. Track the layout wherever a resource - passes between rendering stages. -concepts.synchronization.layouts.title: Track the layout of each texture subresource -concepts.synchronization.readback.description: '{isCompleted} only queries whether the GPU timeline has reached - a value. It does not itself reclaim command buffers or copy staged downloads into the application''s destination - pointer.' -concepts.synchronization.readback.details: '{commandBufferDownload} first records a copy into internal readback - storage. Resetting the completed command buffer for reuse performs the CPU copy to the supplied pointer. Keep - that destination valid, and managed storage pinned, through the download submission''s {wait} before reading it - or releasing the memory. Waiting on another queue''s later submission does not itself poll the download''s owning - queue.' -concepts.synchronization.readback.guidance: This is why polling {isCompleted} and immediately reading an asynchronous - download destination is insufficient. {link} covers the direct-copy and staged-transfer paths. +concepts.synchronization.dependencies.title: Access dependencies +concepts.synchronization.description: Synchronization establishes the order in which operations access shared data + and ensures that later operations see the results they need. In a write-to-read dependency, the writer is the + producer and the reader is the consumer. Barriers and texture transitions coordinate GPU accesses; timelines connect + submissions and let the CPU wait for GPU work to finish. +concepts.synchronization.layouts.context: Use {undefined} as the previous layout when the existing contents can + be discarded, such as for a new image or an attachment that will be cleared completely. To preserve the contents + for loading, sampling, or accumulation, use the layout from the preceding access. +concepts.synchronization.layouts.description: 'A texture''s usage flags declare its permitted roles. {textureLayout} + describes how a particular subresource, identified by a mip level and array layer, is accessed at a given point + in the command sequence. When that access changes, record a transition. For example, the compute sample writes + an output texture in {storage} layout, then prepares it for sampling in a graphics pass:' +concepts.synchronization.layouts.details: Here, {outputTexture} was created with {sampledStorage} usage and the + selected subresource is in {storage} layout. {default} selects mip level 0 and array layer 0. Other mip levels + and layers are unaffected by this transition. +concepts.synchronization.layouts.guidance: For {transition}, supply the layout from the subresource's previous use. + The application tracks this state as it records commands and passes textures between rendering stages. +concepts.synchronization.layouts.title: Texture layouts +concepts.synchronization.readback.description: '{isCompleted} reports GPU completion. A recorded download has one + further step: copying the result from internal readback storage into the application''s destination memory.' +concepts.synchronization.readback.details: '{commandBufferDownload} records the GPU copy into that internal storage. + After the submission finishes, the library performs the CPU copy while reclaiming the completed command buffer. + Calling {wait} on the download''s submission value waits for the GPU and processes that queue''s completed buffers, + completing both steps. Keep the destination allocated, and managed memory pinned, until the call returns.' +concepts.synchronization.readback.guidance: Polling {isCompleted} alone does not perform the final CPU copy. A wait + on another queue does not reclaim the download queue's completed buffers either. {link} describes when uploads + and downloads use direct memory access or staging storage. concepts.synchronization.readback.guidance.link: Resource Management -concepts.synchronization.readback.title: GPU completion and downloaded CPU data are separate steps -concepts.synchronization.reuse.description: For a first renderer, an immediate wait after each frame is straightforward. - To overlap work, give outstanding frames separate mutable data and retain the completion value of each frame's - final use. Before updating a constant buffer, replacing a texture or disposing a pipeline, finish every outstanding - access to the affected resource. -concepts.synchronization.reuse.details: On resize or shutdown, stop new uses before waiting for old ones. {swapChainResize}, - resource disposal and context disposal do not serve as general waits for application work. The triangle can resize - safely between callbacks because each preceding frame has already completed its submission. -concepts.synchronization.reuse.guidance: The current {swapChainPresent} also signals and waits on the graphics queue - after its presentation operation. Removing the triangle's explicit submission wait therefore does not by itself - establish an overlapping presentation loop. A graphics-queue wait also says nothing about independent work still - running on another queue. -concepts.synchronization.reuse.title: Reuse data only after its final access -concepts.synchronization.timelines.context: 'Before the CPU reads, overwrites or releases those resources, wait - for their final use:' -concepts.synchronization.timelines.description: A timeline tracks completion on a queue using increasing values. - {submit} returns a {timelineValue} containing that timeline and the value associated with the submission. Completion - values from different timelines are not comparable just by their numeric {value} fields. -concepts.synchronization.timelines.details: 'Suppose {producer} and {consumer} are already-recorded command buffers - from two queues of the same context. The producer writes data that the consumer uses. Submit them like this:' -concepts.synchronization.timelines.guidance: Passing the produced value makes the consuming queue wait for it - on the GPU. The CPU does not call {producedWait} here. Keep the shared resources valid until {consumed} completes, - and record any texture layout changes required by the consumer. -concepts.synchronization.timelines.notes: '{wait} waits for that timeline value and then checks its owning queue - for completed submissions. Finished command buffers are reset for reuse, and their staged downloads are copied - into the supplied CPU destinations. {queueTimelineSignal} can also enqueue a completion point after work already - submitted to that queue. Calling {signal} does not mean the GPU has already reached the point.' -concepts.synchronization.timelines.title: Use a timeline for completion and queue handoffs +concepts.synchronization.readback.title: Readback completion +concepts.synchronization.reuse.description: The triangle waits for each frame to finish before reusing its data. + To overlap frames, give each in-flight frame its own mutable storage and track when that storage becomes available + again. Before changing data, wait for GPU work that still accesses the affected bytes; before releasing a resource, + wait for all of its outstanding uses. +concepts.synchronization.reuse.details: 'Resizing and shutdown follow the same rule: stop new uses, wait for existing + uses to finish, then replace or release the resources. Establish this order before calling {swapChainResize} or + disposing resources or the context. The triangle already waits for each frame, so it can resize between callbacks.' +concepts.synchronization.reuse.guidance: '{swapChainPresent} signals and waits on the graphics queue after presentation. + The triangle therefore waits at presentation even if its explicit submission wait is removed. Work submitted independently + to other queues requires its own completion tracking.' +concepts.synchronization.reuse.title: Resource reuse +concepts.synchronization.timelines.context: 'If the CPU needs to read the result, overwrite the shared data, or + release the resources after the consumer finishes, wait for that submission:' +concepts.synchronization.timelines.description: A timeline identifies queue completion with increasing values. {submit} + returns a {timelineValue} containing the timeline and the submission's value. Numeric {value} fields from different + timelines cannot be compared directly. +concepts.synchronization.timelines.details: 'Let {producer} and {consumer} be recorded command buffers from two + queues in the same context, with the consumer using data written by the producer. Submit them with this dependency:' +concepts.synchronization.timelines.guidance: The consuming queue waits for the supplied completion value before + executing its commands. The CPU can continue without calling {producedWait}. Keep the shared resources alive until + {consumed} completes, and record the texture transitions required by the consumer's access. +concepts.synchronization.timelines.notes: The value returned by {queueTimelineSignal} can likewise be waited on + with {wait} or used as a dependency for another queue. {signal} places this completion point after previously + submitted work; the GPU reaches it once that work has finished. +concepts.synchronization.timelines.title: Timelines and queue dependencies concepts.synchronization.title: Synchronization home.actions.reference: Browse API home.actions.tutorial: Start with a triangle -home.entries.description: A first frame. A focused example. A closer look at the API. -home.entries.label: Explore the documentation +home.entries.description: Tutorials, examples, and API reference +home.entries.label: Documentation sections home.entries.reference.action: Explore the API home.entries.reference.category: Reference -home.entries.reference.description: Find the types, signatures, and members behind your application. +home.entries.reference.description: Look up API types, members, and declarations home.entries.reference.title: API Reference home.entries.samples.action: Browse samples home.entries.samples.category: Examples -home.entries.samples.description: Explore focused rendering and compute techniques through their source code. +home.entries.samples.description: Working examples of graphics and compute techniques home.entries.samples.title: Samples -home.entries.title: Start building. +home.entries.title: Documentation home.entries.tutorial.action: Start tutorial home.entries.tutorial.category: Tutorial -home.entries.tutorial.description: Build a complete rendering application, from setup to the first frame. +home.entries.tutorial.description: From an empty project to your first triangle on screen home.entries.tutorial.title: First Triangle -home.introduction.accent: In C#. -home.introduction.description: Create resources, record commands, and submit graphics or compute work through one - .NET API. -home.introduction.title: Build your renderer. -home.meta.description: A consistent C# API for graphics and compute across DirectX, Metal, and Vulkan. -home.scene.description: Rotating geometry study. Drag or use the arrow keys to adjust the view. +home.introduction.accent: for .NET +home.introduction.description: Zenith.NET provides one API for graphics and compute across DirectX, Metal, and Vulkan +home.introduction.title: Cross-platform graphics{lineBreak}{accent} +home.meta.description: Cross-platform graphics and compute for .NET with one API for DirectX, Metal, and Vulkan +home.scene.description: Interactive rotating geometry. Drag or use the arrow keys to adjust the view. home.scene.label: Geometry display home.scene.surface: Surface home.scene.wireframe: Wireframe home.title: Modern RHI for .NET -learning.concepts.description: Understand how commands, resources, shader data, and synchronization fit together - before combining rendering passes. -learning.concepts.execution.description: Record GPU work, submit it, and keep its resources alive. -learning.concepts.platforms.description: Connect a native window or a UI rendering control. -learning.concepts.resources.description: Choose resource usages, memory placement, and views. -learning.concepts.shaders.description: Match C# layouts and resource handles to Slang. -learning.concepts.synchronization.description: Order dependent accesses and know when work completes. +learning.concepts.description: How to choose resource usages, describe shader data, and coordinate GPU execution +learning.concepts.execution.description: Command recording, submission, and resource lifetime +learning.concepts.platforms.description: Native presentation and UI rendering controls +learning.concepts.resources.description: Resource usages, memory placement, and views +learning.concepts.shaders.description: Data-layout and binding conventions for C# and Slang +learning.concepts.synchronization.description: Dependencies, visibility, and completion learning.concepts.title: Core concepts -learning.description: Start with a complete triangle tutorial. Then use the focused samples and concept guides - to understand the resources, data and dependencies behind a larger renderer. +learning.description: Start with the triangle tutorial to build your first application. Then explore resource management, + shader data, and synchronization in the concept articles, or choose a sample for the technique you want to implement. learning.entries.samples.action: Browse samples -learning.entries.samples.description: Find C# and Slang examples for geometry, compute, ray queries, and mesh shading. +learning.entries.samples.description: C# and Slang implementations of geometry, compute, ray queries, and mesh shading learning.entries.tutorial.action: Open tutorial -learning.entries.tutorial.description: Create a console application, open a window, and draw a triangle. -learning.meta.description: Get started with Zenith.NET and explore its programming model. +learning.entries.tutorial.description: A console application that opens a window and renders a triangle +learning.meta.description: Tutorials and conceptual guidance for the Zenith.NET programming model learning.title: Learn -reference.description: Look up resource types, command signatures, and platform integrations. -reference.entries.commands.description: Record graphics, compute, and transfer commands. -reference.entries.commands.label: Record work -reference.entries.context.description: Create GPU resources for the selected backend. +reference.description: Reference documentation for resources, commands, and platform integrations +reference.entries.commands.description: Graphics, compute, and transfer commands +reference.entries.commands.label: Record commands +reference.entries.context.description: GPU resource creation for the selected backend reference.entries.context.label: Start here -reference.meta.description: Explore the types and members in Zenith.NET. -reference.navigation.core: Browse the core API. +reference.meta.description: Namespaces, types, and members of Zenith.NET +reference.navigation.core: Core API reference reference.title: API Reference -samples.computeShader.description: Converts an image to grayscale with a compute dispatch and displays the resulting - texture. It shows resource handles for a sampled input texture and a writable output texture, rounded-up thread-group - counts and a shader bounds check. Keep the included {assetsTexturesShokoPng} asset; the renderer processes it - once and presents the result on subsequent frames. +samples.computeShader.description: The sample loads {assetsTexturesShokoPng}, converts it to grayscale in a compute + dispatch, and displays the output texture. The conversion runs once; later frames display the same result. The + renderer shows how to bind sampled and writable textures, round up thread-group counts to cover the image, and + check image bounds in the shader. samples.computeShader.details: '{computeShaderRendererCs} · {computeShaderSlang}' samples.computeShader.title: Compute Shader -samples.cube.description: Adds indexed drawing, model, view and projection matrices in a constant buffer and depth - testing. The depth texture is recreated on resize. Use it when moving from clip-space geometry to a transformed - object; the renderer uses a {d32FloatS8UInt} depth/stencil attachment. +samples.cube.description: The cube adds indexed drawing, model, view, and projection matrices in a constant buffer, + and depth testing. Its {d32FloatS8UInt} depth/stencil texture is recreated on resize. samples.cube.details: '{spinningCubeRendererCs} · {spinningCubeSlang}' samples.cube.title: Spinning Cube -samples.description: Choose a focused example for the feature you want to study. Each example links to the C# - renderer and its Slang shader. Start with {link} if you want a complete application explained from an empty - project. +samples.description: Each example pairs a C# renderer with its Slang shader and concentrates on a particular technique. + For the complete application setup and rendering sequence, begin with {link}. samples.description.link: First Triangle -samples.execution.description: '{link} contains six independent renderers in one desktop application. Use the - .NET 10 SDK and a supported desktop backend, as described below. Build and run the application, then choose - an example from the console menu:' +samples.execution.description: Run the {link} project and choose an example from its console menu. samples.execution.description.link: ZenithTutorials -samples.execution.details: The host selects DirectX 12 on Windows, Metal on macOS and Vulkan on Linux. Use a device, - driver and shader compiler environment supported by the selected backend. The Linux window path requires X11 or - XWayland. The {link} declares package dependencies and copies the shader and texture assets needed at runtime. -samples.execution.details.link: project file -samples.execution.guidance: The samples share windowing and presentation code. You can choose any example independently - according to the feature you want to study. -samples.execution.title: Run the tutorial samples -samples.host.description: '{appCs} creates the context, window and swap chain. It obtains a command buffer, calls - the selected renderer, submits the frame and presents it. {iRendererCs} defines the renderer''s update, render, - resize and disposal methods.' -samples.host.details: Compute and ray tracing produce offscreen textures. {texturePresenterCs} and {presentTextureSlang} - draw those textures into the window's drawable. The host still owns submission and swap-chain presentation. -samples.host.title: Shared host and presentation -samples.indirectDrawing.description: Draws several copies of a cube using an indexed indirect argument buffer and - per-instance data in a structured buffer. The CPU supplies the draw arguments and updates the transforms. Use - it to understand the indirect argument layout and shader access to instance data before adding GPU-generated arguments. +samples.execution.title: Running the examples +samples.host.description: '{appCs} initializes the context, window, and swap chain. On each frame it obtains a command + buffer, invokes the selected renderer, submits the commands, and presents the result. {iRendererCs} defines the + renderer''s update, render, resize, and disposal operations.' +samples.host.details: The compute and ray tracing renderers produce offscreen textures. {texturePresenterCs} and + {presentTextureSlang} draw those textures into the current drawable; the shared host then submits the commands + and presents the frame. +samples.host.title: Host and presentation +samples.indirectDrawing.description: Indirect drawing renders multiple cube instances from a buffer of indexed draw + arguments and a structured buffer of per-instance data. The CPU supplies the arguments and updates the transforms. samples.indirectDrawing.details: '{indirectDrawingRendererCs} · {indirectDrawingSlang}' samples.indirectDrawing.title: Indirect Drawing -samples.meshShading.description: Uses a task shader to cull sphere instances and pass their indices to a mesh shader - that emits geometry. The renderer checks {contextCapabilitiesMeshShadingSupported} before creating its pipeline. - Use it to follow resource handles and payload data through the task and mesh stages. +samples.meshShading.description: A task shader culls sphere instances and passes the retained indices to a mesh + shader that emits geometry. The renderer checks {contextCapabilitiesMeshShadingSupported} before creating the + pipeline. samples.meshShading.details: '{meshShadingRendererCs} · {meshShadingSlang}' samples.meshShading.title: Mesh Shading -samples.rayTracing.description: Builds bottom-level and top-level acceleration structures for a floor and procedural - spheres, then traces inline ray queries in a compute shader. The renderer checks {contextCapabilitiesRayTracingSupported} - before constructing the workload. Use this example for acceleration-structure inputs and shader-side ray traversal. +samples.rayTracing.description: This example builds bottom-level and top-level acceleration structures for a floor + and procedural spheres, then performs inline ray queries in a compute shader. It checks {contextCapabilitiesRayTracingSupported} + before initialization. samples.rayTracing.details: '{rayTracingRendererCs} · {rayTracingSlang}' samples.rayTracing.title: Ray Tracing samples.title: Samples -samples.triangle.description: Creates a vertex buffer and matching input layout, then draws three vertices through - a graphics pipeline. Use it to connect resource creation with the commands in a render pass. +samples.triangle.description: The triangle associates a vertex buffer with a matching input layout and draws three + vertices through a graphics pipeline. samples.triangle.details: '{helloTriangleRendererCs} · {helloTriangleSlang} · {link}' samples.triangle.details.link: Complete tutorial samples.triangle.title: Hello Triangle -samples.workloads.description: 'The main repository''s {link} contains applications that combine several features. - Their projects reference the library source. From a checkout of Zenith.NET, run the chosen project, for example:' +samples.workloads.description: The main repository's {link} contains larger applications that reference the library + source. samples.workloads.description.link: Experiments directory -samples.workloads.details: The windowed experiments use the same Windows, macOS and Linux/X11 host choices. For - drawing inside Avalonia, WinForms, WPF, WinUI/Uno or MAUI, see {link} for the control's frame lifecycle and implementation - links. +samples.workloads.details: The windowed experiments use the same Windows, macOS, and Linux/X11 presentation paths. + UI controls for Avalonia, WinForms, WPF, WinUI/Uno, and MAUI are covered in {link}, including their frame lifecycle + and implementation sources. samples.workloads.details.link: Platform Integration samples.workloads.table.cornellBox.example: '{link}' samples.workloads.table.cornellBox.example.link: CornellBox -samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: Path tracing, denoising, tone mapping, upscaling - and ImGui controls. Requires ray tracing support and the shader compilation environment for its desktop backend. +samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: Path tracing, denoising, tone mapping, upscaling, + and ImGui controls. Requires ray tracing support. samples.workloads.table.fluidTank.example: '{link}' samples.workloads.table.fluidTank.example.link: FluidTank samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: Compute fluid simulation, dependencies between - simulation stages and multipass surface rendering. Requires its desktop backend and shader compilation environment. + simulation stages, and multipass surface rendering. samples.workloads.table.headings.example: Example -samples.workloads.table.headings.whatItDemonstratesAndRequires: What it demonstrates and requires +samples.workloads.table.headings.whatItDemonstratesAndRequires: Techniques and requirements samples.workloads.table.inkCanvas.example: '{link}' samples.workloads.table.inkCanvas.example.link: InkCanvas samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: Skia drawing and input handling in a native window. Requires the backend and Skia native library for the target platform. samples.workloads.table.platformDetection.example: '{link}' samples.workloads.table.platformDetection.example.link: PlatformDetection -samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: Attempts context creation for each backend - and reports device capabilities. A context-creation failure is reported as unsupported; that result can also indicate - a missing driver or runtime dependency. -samples.workloads.title: Explore larger workloads -tutorial.context.description: The window can now open, but we have not created the GPU objects that will render - into it. A {graphicsContext} provides access to the selected graphics backend and its command queues. -tutorial.context.details: 'Insert this block {emphasis}:' +samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: Attempts to create a context for each backend + and reports device capabilities. It reports a failed attempt as unsupported; the failure may be due to the device, + driver, or a missing runtime dependency. +samples.workloads.title: Larger applications +tutorial.context.description: A {graphicsContext} connects the application to the GPU through a backend and provides + the methods used to create rendering resources. +tutorial.context.details: 'Insert the context initialization {emphasis}:' tutorial.context.details.emphasis: after the using directives, before {iWindowWindow} -tutorial.context.guidance: The branches select DirectX 12 on Windows, Metal on macOS and Vulkan on Linux. The - rendering code that follows uses the shared Zenith.NET API. We request validation during development and print - messages reported through {validationMessage}. Diagnostics depend on the backend and the validation components - available on the machine. -tutorial.context.title: Create the graphics context -tutorial.description: Build a .NET console application that opens a window and draws a triangle with a smooth - color gradient. You will learn how vertex data, shaders and pipeline state work together, then record and submit - the commands that produce the image. -tutorial.details: Work through the sections in order. You will first open an empty window, then display a background - color, and finally draw the triangle. Each checkpoint confirms one part of the application before you add the - next. Initialization runs once; the render callback records a new frame each time it is called. +tutorial.context.guidance: Each branch selects a backend for the current platform and requests validation. Messages + from {validationMessage} are printed in the console. +tutorial.context.imports: "Add the following using directives at the top of {programCs}:" +tutorial.context.title: Graphics context +tutorial.description: In this tutorial, you will build a .NET console application that opens a window and draws + a colored triangle, starting from an empty project. +tutorial.details: 'The tutorial has three checkpoints: an empty window, a solid background color, and the colored + triangle. Run the application at each checkpoint before adding the next part.' tutorial.draw.context: 'The arguments to {draw} are:' -tutorial.draw.description: 'In the {windowRender} callback, replace {addTheTriangleDrawCommandsHereLater} with these - three commands, between {beginRenderPass} and {endRenderPass}:' -tutorial.draw.details: '{setPipeline} selects the shaders and state we just created. Set it before binding vertex - data: the backend uses the pipeline''s input layout to interpret the binding.' -tutorial.draw.guidance: '{setVertexBufferVertexBuffer} binds the buffer starting at byte offset 0 to input slot - 0. That slot corresponds to the single entry in {inputLayouts}. It does not copy or upload the data again.' -tutorial.draw.notes: The commands are still only recorded at this point. The {submitWait} and {present} calls already - at the end of the render callback execute the work and display its result. Clearing remains necessary because - the triangle covers only part of the image; the background must also receive a defined color each frame. +tutorial.draw.description: 'In the {windowRender} callback, replace {addTheTriangleDrawCommandsHereLater} with the + following commands, between {beginRenderPass} and {endRenderPass}:' +tutorial.draw.details: '{setPipeline} selects the shaders and render state. It must precede vertex binding because + the backend interprets that binding using the pipeline''s input layout.' +tutorial.draw.guidance: '{setVertexBufferVertexBuffer} binds the uploaded vertex data at byte offset 0 to input + slot 0, corresponding to the single entry in {inputLayouts}.' +tutorial.draw.notes: These calls record the draw commands. The existing {submitWait} submits them and waits for + the GPU to finish; {present} then requests display of the completed image. Keep the clear operation at the start + of the pass so the area outside the triangle has a defined background color. tutorial.draw.table.firstInstance.meaning: Start instance numbering at zero. tutorial.draw.table.firstVertex.meaning: Start with the first vertex in the buffer. tutorial.draw.table.headings.argument: Argument @@ -648,98 +605,90 @@ tutorial.draw.table.headings.description: Value tutorial.draw.table.headings.meaning: Meaning tutorial.draw.table.instanceCount.meaning: Draw one copy of the triangle. tutorial.draw.table.vertexCount.meaning: Read three vertices. -tutorial.draw.title: Draw the triangle inside the pass -tutorial.execution.description: 'Build and run from the {firstTriangle} directory:' -tutorial.execution.details: The window should display a triangle with a red upper corner, green lower-right corner - and blue lower-left corner against a dark background. The interior should show a smooth gradient between those - colors. -tutorial.execution.guidance: Resize the window. The resize callback updates the framebuffer dimensions and resizes - the swap chain. The render pass establishes a viewport matching that image. Because the vertex positions remain - in normalized coordinates, the triangle keeps the same fraction of the window's width and height; changing the - aspect ratio can stretch its shape. Preserving an object's aspect ratio requires a projection or viewport policy, - which is beyond this first draw. -tutorial.execution.title: Run, resize and close -tutorial.frame.commands.context: After {endRenderPass}, the second transition prepares the image for presentation. - {submit} finishes recording and submits the command buffer; {wait} waits for the GPU to complete that submission. - {present} then requests display of the rendered image. -tutorial.frame.commands.description: A render pass groups drawing operations that use the same attachments. Here, - the color attachment is the swap chain's drawable, the image that receives our drawing. {colorAttachmentClear} - creates a description telling the pass to clear to the given RGBA color and keep the result when the pass ends. - {beginRenderPass} records those instructions; the GPU performs the clear after the commands are submitted. -tutorial.frame.commands.details: The brackets contain our single color attachment. The {null} argument means that - there is no depth/stencil attachment, which would store depth values and stencil masks for depth and stencil tests. -tutorial.frame.commands.guidance: '{beginRenderPass} sets a viewport and scissor covering the attachment. The viewport - maps the rendered coordinates to pixels, and the scissor limits which pixels can be written. These defaults cover - the whole drawable, which is what this triangle needs.' -tutorial.frame.commands.title: Clear, submit and present -tutorial.frame.description: First fill the image with one background color. This operation is called a clear. - If that color appears in the window, the surface, command submission and presentation path are working together. - This checkpoint lets you verify the frame loop before adding geometry and shaders. -tutorial.frame.details: 'A render callback is code that Silk.NET calls when it is time to draw a frame. This callback - does not need the event''s elapsed-time argument, so it is named {value}. Register it {emphasis}:' +tutorial.draw.title: Drawing commands +tutorial.execution.description: Build and run the {firstTriangle} project. +tutorial.execution.details: You should see a triangle on a dark background, with red at the top, green at the lower + right, and blue at the lower left. Interpolation creates smooth transitions between the vertex colors across the + triangle. +tutorial.execution.guidance: Resizing changes the image's pixel dimensions while the vertex coordinates stay the + same. The viewport maps those coordinates to the new width and height, so the triangle stretches when the window's + width-to-height ratio changes. +tutorial.execution.title: Running the application +tutorial.frame.commands.context: After {endRenderPass}, the second transition prepares the drawable for presentation. + {submit} ends recording and submits the command buffer; {wait} blocks until that submission completes. {present} + then requests display of the rendered image. +tutorial.frame.commands.description: A render pass groups drawing operations that write to the same attachments. + In this pass, the swap chain's drawable receives the color output. {colorAttachmentClear} describes how to initialize + that attachment with an RGBA clear color and preserve its contents when the pass ends. {beginRenderPass} records + the start of the pass with those settings. +tutorial.frame.commands.details: The collection contains one color attachment. {null} specifies that the pass has + no depth/stencil attachment. +tutorial.frame.commands.guidance: '{beginRenderPass} sets the viewport and scissor to cover the whole attachment. + The viewport maps rendering coordinates to pixel positions; the scissor limits where pixels can be written.' +tutorial.frame.commands.title: Clear, submission, and presentation +tutorial.frame.description: Start by filling the window with a single background color. This operation is called + clearing. Once the background appears, the surface, command submission, and presentation are working together, + ready for the triangle's geometry and shaders. +tutorial.frame.details: 'Silk.NET invokes the render callback when a frame is due. This example does not use the + elapsed-time argument, so the parameter is named {value}. Register the callback {emphasis}:' tutorial.frame.details.emphasis: before {windowRun} -tutorial.frame.target.description: '{graphicsQueueCommandBuffer} obtains a command buffer with recording already - begun. Recording describes work for the GPU; it does not execute that work immediately.' -tutorial.frame.target.details: The first {transition} prepares the drawable for color-attachment access. {default} - selects mip level 0 and array layer 0. We use {undefined} as the previous layout because we will clear the entire - image and discard its previous contents. A pass that needs to preserve existing content must use its actual previous - layout instead. -tutorial.frame.target.guidance: Use the swap chain's current drawable each frame. Presentation can change which - image is available, so a texture saved from an earlier frame is not a permanent window render target. -tutorial.frame.target.title: Prepare the drawable -tutorial.frame.title: Display a background color -tutorial.geometry.data.description: Add this array {emphasis}. The following resource-creation steps also belong - before that callback, in the order shown. +tutorial.frame.target.description: '{graphicsQueueCommandBuffer} returns a command buffer ready for recording. Recording + defines the GPU workload; execution begins only after submission.' +tutorial.frame.target.details: A texture layout describes the kind of access an operation requires. The first {transition} + prepares the drawable for use as a color attachment. Here, {default} selects mip level 0 and array layer 0, the + drawable's base image. Specifying {undefined} allows the previous contents to be discarded because this pass clears + the entire image. +tutorial.frame.target.guidance: Use the current drawable on each frame because presentation can advance to a different + image. +tutorial.frame.target.title: Drawable preparation +tutorial.frame.title: The first frame +tutorial.geometry.data.description: Add the vertex array {emphasis}. Keep the subsequent resource initialization + before this callback as well, in the order presented. tutorial.geometry.data.description.emphasis: before {windowRender} -tutorial.geometry.data.details: 'Each array entry creates a {vertex}. The two inner {new} expressions create its - {vector3} position and {vector4} color. The vertices describe the top, lower-right and lower-left corners. The - vertex shader will supply a fourth position coordinate, {w}. With w equal to 1, x and y directly describe normalized - device coordinates: -1 and +1 are the image edges, and 0 is the center. These coordinates do not depend on the - window''s pixel dimensions.' -tutorial.geometry.data.guidance: Each color contains red, green, blue and alpha components. Alpha is 1 at all three - corners. All three positions have z = 0, placing them in the same plane. These positions need no camera or transformation - matrix because they already describe the coordinates we want to render. For this single flat triangle, we will - also disable blending and depth testing and omit a depth buffer. -tutorial.geometry.data.title: Choose the corners -tutorial.geometry.description: A vertex is a point together with the data used to draw it. Our triangle has three - vertices, one for each corner. Each contains a position and a color. The GPU will interpolate the colors, calculating - intermediate values across the triangle. -tutorial.geometry.format.description: 'Append this declaration {emphasis}:' +tutorial.geometry.data.details: 'Each entry constructs a {vertex}; the two inner {new} expressions provide its {vector3} + position and {vector4} color. The positions form the upper, lower-right, and lower-left corners. The vertex shader + adds {w} as the fourth position coordinate. With w equal to 1, x and y are also normalized device coordinates: + -1 and +1 mark the image boundaries, and 0 marks the center. Their interpretation is independent of pixel dimensions.' +tutorial.geometry.data.guidance: Each color has red, green, blue, and alpha components, with alpha set to 1. All + three vertices have z = 0 and lie in the same plane. +tutorial.geometry.data.title: Vertex positions and colors +tutorial.geometry.description: Each of the triangle's three vertices has a position and a color. The GPU uses the + positions to determine the triangle's shape and interpolates the colors across its surface. +tutorial.geometry.format.description: 'Append the vertex declaration {emphasis}:' tutorial.geometry.format.description.emphasis: at the end of {programCs}, after the cleanup statements -tutorial.geometry.format.details: '{file} limits this type to {programCs}, and the constructor initializes its position - and color fields. {layoutKindSequential} keeps the fields in declaration order. {position} contains three 32-bit - floats and {color} contains four. In this struct, position begins at byte 0, color begins at byte 12, and the - complete vertex occupies 28 bytes. We will describe that same layout to the graphics pipeline.' -tutorial.geometry.format.title: Define a vertex -tutorial.geometry.title: Give the GPU three vertices +tutorial.geometry.format.details: '{file} limits the type to {programCs}, and {layoutKindSequential} keeps its fields + in declaration order. {position} contains three 32-bit floats and starts at byte offset 0; {color} contains four + and starts at byte offset 12. Each vertex therefore occupies 28 bytes. The input layout will describe this arrangement + so the GPU can read the fields correctly.' +tutorial.geometry.format.imports: "Add these using directives at the top of {programCs} for the vector types and the struct layout attribute:" +tutorial.geometry.format.title: Vertex representation +tutorial.geometry.title: Vertex data tutorial.geometry.upload.context: '{fixed} prevents the garbage collector from moving the array while its address - is used. For this CPU-writable buffer, {upload} maps, copies and unmaps the memory before returning, so the array - does not need to stay pinned afterward. The buffer must remain alive throughout rendering, and the upload only - needs to happen once because the vertices do not change.' -tutorial.geometry.upload.description: 'The managed array is CPU data. A {buffer} gives the GPU storage from which - it can read the vertices. After the array, add:' -tutorial.geometry.upload.details: 'The total size is {sizeofVertexVerticesLength}: 28 bytes per vertex, three vertices, - 84 bytes in all. {bufferUsagesVertex} permits vertex-input access. {cpuWriteOnly} lets the CPU initialize this - small buffer directly. The descriptor''s stride records the element size; the input layout we create below will - tell vertex fetching how to read the individual attributes.' -tutorial.geometry.upload.guidance: Creating a buffer does not populate it. {upload} copies the array into that allocation - starting at destination byte offset 0. Its source description supplies a pointer and the number of bytes to copy. + is in use. For this CPU-writable buffer, {upload} maps the memory, copies the bytes, and unmaps it before returning, + so the array only needs to remain pinned during the call. Upload these vertices once during initialization, and + keep the buffer alive until rendering has finished.' +tutorial.geometry.upload.description: 'Store the vertices in a {buffer} so the GPU can read them during drawing. + Add the allocation and upload immediately after the array:' +tutorial.geometry.upload.details: 'The allocation size is {sizeofVertexVerticesLength}: three 28-byte vertices, + or 84 bytes. {bufferUsagesVertex} declares vertex-input access, while {cpuWriteOnly} permits direct initialization + by the CPU. The descriptor''s stride records the element size. The input layout defined below specifies how vertex + fetching interprets each attribute.' +tutorial.geometry.upload.guidance: Allocation does not initialize the buffer's contents. {upload} copies the array + to destination byte offset 0 using the source pointer and byte count supplied in the data description. +tutorial.geometry.upload.imports: "In {programCs}, add {bufferAlias} to the using directives to distinguish the Zenith.NET buffer type from {systemBuffer}." tutorial.geometry.upload.notes: Add {vertexBufferDispose} immediately before {swapChainDispose} in the cleanup at - the bottom of {programCs}. For larger static geometry, {link} explains when to choose GPU-only memory and transfer - uploads instead. + the end of {programCs}. For larger static geometry, {link} discusses GPU-only storage and transfer uploads. tutorial.geometry.upload.notes.link: Resource Management -tutorial.geometry.upload.title: Allocate a buffer and upload the array -tutorial.input.description: 'The vertex bytes and shaders are ready. Next, describe how the GPU should read each - vertex. An attribute is one value, such as position or color. The input layout gives each attribute a format - and byte offset; the stride gives the distance in bytes from one vertex to the next. Add this initialization - block after shader creation:' -tutorial.input.details: '{inputLayoutAdd} appends an element at the current stride and increases that stride by - the element''s size. It does not inspect the C# struct. Here it produces the following agreement between CPU memory - and shader inputs:' -tutorial.input.guidance: Changing the C# field order or padding without updating this description would make the - GPU read the wrong bytes. The default {semanticIndex} is zero, matching {pOSITION0} and {cOLOR0}. Both elements - belong to the same buffer, so the pipeline will contain one input layout and we will bind that buffer to slot - 0. +tutorial.geometry.upload.title: Buffer allocation and upload +tutorial.input.description: 'The GPU needs to know where each vertex attribute, such as position or color, is stored. + The input layout supplies its format and byte offset. It also sets the stride: the number of bytes from one vertex + to the next. Add this code after creating the shaders:' +tutorial.input.details: '{inputLayoutAdd} appends each attribute after the previous one and adds its size to the + stride. The offsets come from the formats supplied here, rather than from inspection of the C# struct. For these + two fields, the resulting layout is:' +tutorial.input.guidance: The default {semanticIndex} is zero, matching {pOSITION0} and {cOLOR0} in the shader. Position + and color are stored together in one vertex buffer, so the pipeline uses one input layout at slot 0. Keep this + layout consistent with the C# struct if its field order or padding changes. tutorial.input.table.headings.byteOffset: Byte offset tutorial.input.table.headings.cField: C# field tutorial.input.table.headings.format: Format @@ -749,151 +698,133 @@ tutorial.input.table.nextVertex.format: 'Total stride: 28 bytes' tutorial.input.table.nextVertex.shaderInput: Next input record tutorial.input.table.vertexColor.format: '{float4} (16 bytes)' tutorial.input.table.vertexPosition.format: '{float3} (12 bytes)' -tutorial.input.title: Describe the vertex input layout -tutorial.lifecycle.description: 'The finished application repeats this sequence:' -tutorial.lifecycle.details: 'Closing the window returns from {run}. Each rendered frame has already waited for its - GPU work to complete, so we can now dispose the resources it used. The cleanup after {windowRun} should be:' -tutorial.lifecycle.guidance: Release the swap chain before its native window and the context after all of its resources. - The queue owns and recycles submitted command buffers, and the swap chain owns its drawable; neither needs a separate - {dispose} call in this application. -tutorial.lifecycle.title: Follow the lifetime of one frame -tutorial.pipeline.behavior: 'After the input layout, add:' -tutorial.pipeline.context: '{cullNone} fills the triangle without discarding either face orientation. The order - of its vertices determines the face winding, so disabling culling prevents that order from hiding our first triangle.' -tutorial.pipeline.description: We now have vertex data, an input layout and two shaders. The {graphicsPipeline} - connects them and specifies how the GPU assembles vertices into primitives and writes the result to an attachment. -tutorial.pipeline.details: 'A pipeline combines programmable shader stages with fixed-function settings, which control - GPU operations such as triangle assembly, face culling and blending. For this triangle, choose these settings:' -tutorial.pipeline.guidance: The color format comes from {swapChainDescFormat}. It must match the image used by the - render pass. {count1} means one sample per pixel. -tutorial.pipeline.item: '{triangleList} assembles each consecutive group of three vertices into one triangle. We - will supply three vertices and draw once, so no index buffer is needed.' -tutorial.pipeline.notes: '{depthNone} disables depth testing and writing, matching the pass without a depth attachment.' -tutorial.pipeline.reference: '{opaque} disables blending, so the fragment shader''s color replaces the background - inside the triangle.' -tutorial.pipeline.title: Connect the shaders and vertex layout -tutorial.pipeline.usage: The shader objects can be disposed after creating the pipeline, as they are in the sample - renderer. Keep the pipeline itself alive for every frame that draws with it. Add {pipelineDispose} before {vertexBufferDispose} - in the cleanup. Pipeline creation is the final initialization step before the render callback. -tutorial.pipeline.validation: The pipeline description declares the attachment configuration; it does not create - another image. {inputLayouts} has one entry because position and color are stored together in one buffer. -tutorial.presentation.title: Connect the GPU to the window -tutorial.project.context: Enable {emphasis} ({allowUnsafeBlocks}) in the project's build settings. We will use it - to pass vertex data to the GPU and for the window helper's native calls. +tutorial.input.title: Vertex input layout +tutorial.lifecycle.description: 'Each frame follows this sequence:' +tutorial.lifecycle.details: 'When the window closes, {run} returns and execution continues to the cleanup code. + Each frame has already waited for its submitted work to finish, so the resources used by those commands can now + be released. The complete cleanup after {windowRun} is:' +tutorial.lifecycle.guidance: Release the swap chain before destroying its native window, and release the context + after its resources. Submitted command buffers are recycled by the queue, and the drawable is managed by the swap + chain, so neither needs a separate {dispose} call. +tutorial.lifecycle.title: Frame lifecycle and cleanup +tutorial.pipeline.behavior: 'After the input layout, create the pipeline:' +tutorial.pipeline.context: '{cullNone} disables face culling, so the triangle is drawn whether its vertices appear + clockwise or counterclockwise.' +tutorial.pipeline.description: A {graphicsPipeline} brings together the vertex layout, the two shaders, and the + settings that determine how primitives are assembled and written to attachments. +tutorial.pipeline.details: 'The shaders process vertices and fragments. The other pipeline settings control primitive + assembly, face culling, depth testing, and blending:' +tutorial.pipeline.guidance: The pipeline's color format must match the render-pass attachment, so it is taken from + {swapChainDescFormat}. {count1} specifies one sample per pixel. +tutorial.pipeline.item: '{triangleList} assembles each consecutive group of three vertices into a triangle.' +tutorial.pipeline.notes: '{depthNone} disables depth testing and depth writes, consistent with the absence of a + depth attachment.' +tutorial.pipeline.reference: '{opaque} disables blending. The fragment shader''s output therefore replaces the background + color inside the triangle.' +tutorial.pipeline.title: Graphics pipeline +tutorial.pipeline.usage: Shader objects may be released after pipeline creation. Keep the pipeline alive while rendering, + and add {pipelineDispose} before {vertexBufferDispose} in the cleanup. +tutorial.presentation.title: Graphics context and presentation +tutorial.project.context: Enable {emphasis} ({allowUnsafeBlocks}) in the project's build settings. Native calls + in the window helper and the vertex upload require unsafe code. tutorial.project.context.emphasis: Allow unsafe code -tutorial.project.description: 'Create the project and enter its directory:' -tutorial.project.details: 'Install the packages:' -tutorial.project.guidance: '{zenithNET} supplies the shared rendering API. The three backend packages let the same - program select the implementation for its platform. {zenithNETCompiler} compiles Slang shaders, the small GPU - programs we will write later, for that implementation. Silk.NET supplies the window and event loop.' -tutorial.project.title: Create a console project -tutorial.requirements.context: You can follow this page from an empty project. The {link} and its {detail} are available - as a reference for the rendering and windowing APIs used here. +tutorial.project.description: Create a C# console project named {firstTriangle} targeting .NET 10. +tutorial.project.details: 'Add the following NuGet packages to the project:' +tutorial.project.guidance: '{zenithNET} provides the shared rendering API, and the three backend packages supply + its platform implementations. {zenithNETCompiler} compiles the Slang shaders introduced below for the selected + backend. Silk.NET provides window creation and event processing.' +tutorial.project.title: Project setup +tutorial.requirements.context: The {link} and its {detail} provide reference implementations for this tutorial. tutorial.requirements.context.detail: shared host tutorial.requirements.context.link: Hello Triangle sample -tutorial.requirements.description: 'You need the {emphasis}, a code editor or IDE, and a desktop with a GPU and - driver supported by a Zenith.NET backend. Basic familiarity with C# is enough; the graphics concepts are introduced - as they are used. This is an ordinary {net10} console project. A backend translates Zenith.NET operations into - calls to a graphics API, such as DirectX 12, Metal or Vulkan. The application chooses one at startup:' +tutorial.requirements.description: 'You need the {emphasis} and basic C# knowledge. The application targets {net10}. + Your GPU and driver must support the backend selected for your platform:' tutorial.requirements.description.emphasis: .NET 10 SDK -tutorial.requirements.details: Linux needs an X11-compatible window session for the windowing path used here. Optional - ray tracing and mesh shading features are not needed for this triangle. -tutorial.requirements.guidance: Zenith.NET renders into a surface supplied by the application. Silk.NET.Windowing - will create the desktop window and process its events. On macOS, the presentation target is a Metal layer ({cAMetalLayerCs}); - the tutorial's window helper attaches that layer for us. +tutorial.requirements.guidance: Zenith.NET renders into a native surface provided by the application. Silk.NET.Windowing + creates the window and processes its events. On macOS, presentation uses a Metal layer, represented by {cAMetalLayerCs}; + the window helper attaches it to the window. tutorial.requirements.table.headings.graphicsBackend: Graphics backend tutorial.requirements.table.headings.platform: Platform -tutorial.requirements.table.headings.windowSurface: Window surface tutorial.requirements.table.linux.graphicsBackend: Vulkan 1.4 -tutorial.requirements.table.linux.platform: Linux -tutorial.requirements.table.linux.windowSurface: X11 window and display; XWayland is also suitable +tutorial.requirements.table.linux.platform: Linux (X11 or XWayland) tutorial.requirements.table.macOS.graphicsBackend: Metal 4 tutorial.requirements.table.macOS.platform: macOS -tutorial.requirements.table.macOS.windowSurface: Metal layer attached to the window tutorial.requirements.table.windows.graphicsBackend: DirectX 12 tutorial.requirements.table.windows.platform: Windows -tutorial.requirements.table.windows.windowSurface: Win32 window handle -tutorial.requirements.title: Before you begin -tutorial.resize.context: 'Run {dotnetRun} again. The window should now have a uniform dark background that continues - to fill it after resizing. Keep this callback: the triangle will be drawn inside its existing render pass.' -tutorial.resize.description: 'The swap chain''s images must follow the framebuffer dimensions. Use {framebufferResize} - to respond to changes in pixel size, including changes caused by display scaling. After the render callback, still - before {windowRun}, add:' -tutorial.resize.details: Silk.NET distinguishes window-size changes from {link}. We need the latter because the - swap chain stores pixels. A minimized window can have a zero-size framebuffer. Both callbacks skip their GPU work - in that case. After a resize, the render pass will use the new attachment dimensions for its viewport and scissor. +tutorial.requirements.title: Prerequisites +tutorial.resize.context: 'Build and run the application again. The background should continue to fill the window + when you resize it: each new render pass sets its viewport and scissor from the resized attachment. Keep the render + callback in place; the triangle will be drawn inside this pass.' +tutorial.resize.description: 'The swap chain must follow changes to the framebuffer''s size. Register a {framebufferResize} + callback after the render callback and before {windowRun}:' +tutorial.resize.details: Listen for {link}, which are measured in pixels, rather than changes to the window's logical + size. If minimizing the window sets either framebuffer dimension to zero, the resize callback leaves the swap + chain unchanged. The render callback also returns while either dimension is zero, pausing rendering until the + framebuffer has a usable size again. tutorial.resize.details.link: framebuffer-size changes -tutorial.resize.guidance: We wait after every submission, so no earlier frame is still using the images when the - resize handler replaces them. The current {present} implementation also waits on the graphics queue. This simple - loop keeps one frame's work complete before the next begins; {link} covers more advanced scheduling. +tutorial.resize.guidance: The render callback waits for each submitted frame to finish before calling {present}. + The resize callback can therefore replace the swap-chain images without interrupting work from an earlier frame. + The {link} article explains these completion and resource-lifetime requirements in more detail. tutorial.resize.guidance.link: Synchronization -tutorial.resize.title: Respond to resizing -tutorial.shaders.compilation.context: Compilation happens once during initialization. {appContextBaseDirectory} - locates the copied shader beside the executable, independently of the current working directory. These shaders - only consume vertex input, so there are no constant buffers, textures or resource handles to bind yet. -tutorial.shaders.compilation.description: In the file properties for {triangleSlang}, set {emphasis} to {detail}. - This makes the shader available beside the executable. +tutorial.resize.title: Resizing +tutorial.shaders.compilation.context: Using {appContextBaseDirectory} loads the copied shader from the application's + output directory, so launching the application from another working directory does not change where it looks for + the file. +tutorial.shaders.compilation.description: For {triangleSlang}, set the file property {emphasis} to {detail}. The + build will then copy the shader beside the executable. tutorial.shaders.compilation.description.detail: Copy if newer tutorial.shaders.compilation.description.emphasis: Copy to Output Directory -tutorial.shaders.compilation.details: 'Return to {programCs}. After the vertex upload, add these initialization - statements before the render callback:' -tutorial.shaders.compilation.guidance: '{zenithCompiler} returns a shader description containing code for the requested - graphics API. {createShader} creates the corresponding backend object. Both the graphics API and entry-point names - matter: use {contextGraphicsApi}, and spell {vSMain} and {fSMain} exactly as in the Slang file.' -tutorial.shaders.compilation.title: Compile for the selected backend -tutorial.shaders.context: '{fSInput} connects the vertex shader''s output to the fragment shader''s input. When - written by the vertex shader, {sVPOSITION} supplies a clip-space position: the four coordinates the GPU uses to - determine what lies inside the visible image. {cOLOR0} carries the color to interpolate between vertices. The - two stages must agree on its type and semantic.' -tutorial.shaders.description: A shader is a program executed by the GPU. This draw needs a vertex shader to position - vertices and a fragment shader to produce the colors inside the triangle. We will write them in Slang, a shader - language, and compile two entry points from the same file. An entry point is the function where a shader stage - begins executing. -tutorial.shaders.details: 'Create {triangleSlang}, starting with these two structures:' +tutorial.shaders.compilation.details: 'Return to {programCs} and add shader initialization after the vertex upload, + before the render callback:' +tutorial.shaders.compilation.guidance: '{zenithCompiler} compiles the source for {contextGraphicsApi}, and {createShader} + creates a shader object from the compiled description. The entry-point names {vSMain} and {fSMain} select the + two functions defined in the Slang file.' +tutorial.shaders.compilation.title: Compiling the shaders +tutorial.shaders.context: '{fSInput} connects the two shader stages. The vertex shader writes a clip-space position + to {sVPOSITION}; the GPU uses this position to determine which part of the triangle is visible. The {cOLOR0} field + carries the vertex color, which is interpolated across the triangle before reaching the fragment shader. Its type + and semantic must agree between the two stages.' +tutorial.shaders.description: Shaders are programs that run on the GPU. The vertex shader determines each vertex's + position, and the fragment shader determines the color at each covered image location. Both stages will be written + in one Slang file, with a separate entry point—the function where execution begins—for each stage. +tutorial.shaders.details: 'Create {triangleSlang} with these input and output structures:' tutorial.shaders.fragment.description: 'Append the fragment entry point to the same file:' -tutorial.shaders.fragment.details: Rasterization determines which image locations the triangle covers. It produces - fragments, the data processed by the fragment shader, with vertex colors interpolated across the covered area. - {fSMain} returns this interpolated color through {sVTARGET}, which identifies the first color attachment. -tutorial.shaders.fragment.guidance: Vertex-color interpolation is separate from attachment blending. Blending combines - a fragment's output with the color already stored in the attachment. Our opaque blend state disables that combination, - so the interpolated color replaces the background inside the triangle. -tutorial.shaders.fragment.title: Color the fragments -tutorial.shaders.guidance: '{vSInput} describes what the vertex shader receives from the vertex buffer. The semantics - {pOSITION0} and {cOLOR0} identify the inputs; C# field names alone do not establish that mapping.' -tutorial.shaders.title: Write the two shader stages +tutorial.shaders.fragment.details: Rasterization determines where the triangle covers the image and generates fragments + for those locations. Each fragment receives a color interpolated from the three vertex colors. {fSMain} returns + this color, and {sVTARGET} directs the result to the first color attachment. +tutorial.shaders.fragment.title: Fragment shading +tutorial.shaders.guidance: '{vSInput} defines the vertex shader''s inputs. {pOSITION0} and {cOLOR0} identify the + attributes by semantic; the C# field names alone do not establish this mapping.' +tutorial.shaders.title: Shader stages tutorial.shaders.vertex.description: 'Append the vertex entry point to {triangleSlang}:' tutorial.shaders.vertex.details: The GPU invokes this entry point for each input vertex. It adds the homogeneous - coordinate {w} to the position and forwards the color. After the vertex stage, position is divided by w; here - that division leaves x, y and z unchanged. This is why the positions chosen above can be understood directly in - normalized device coordinates. -tutorial.shaders.vertex.title: Position each vertex -tutorial.surface.description: 'The context also needs to know where to display its output. Add the following {emphasis}:' + coordinate {w} and forwards the color. After vertex processing, position is divided by w. Since w is 1 here, x, + y, and z are unchanged and may be interpreted directly as normalized device coordinates. +tutorial.shaders.vertex.title: Vertex shading +tutorial.surface.description: "Specify the native presentation target {emphasis}:" tutorial.surface.description.emphasis: after {windowCenter} and before {windowRun} -tutorial.surface.details: '{surface} describes a native presentation target and its pixel dimensions. The framebuffer - is the pixel image associated with the window. {framebufferSize} gives its dimensions in pixels; the window''s - logical dimensions can differ when display scaling is enabled.' -tutorial.surface.guidance: The surface matches the backend selected above. Windows supplies a window handle, Linux - supplies an X11 display and window, and the macOS helper supplies the attached Metal layer. This is the only platform-specific - part of connecting our window to rendering. -tutorial.surface.title: Describe the native surface -tutorial.swapChain.context: 'The swap chain uses both the context and the native window. Replace the {windowDispose} - line at the bottom of {programCs} with this cleanup order:' -tutorial.swapChain.description: 'Use the surface description to create the images that will be presented. Immediately - after the surface block, add:' -tutorial.swapChain.details: The {swapChain} manages the images displayed in the window. Each frame, {drawable} gives - us the current image as a {texture}, the API type for image data. After drawing, {present} requests display of - the result and advances to the next drawable. -tutorial.swapChain.guidance: '{b8G8R8A8UNorm} stores four 8-bit color channels in blue, green, red and alpha order. - {uNorm} means integer values from 0 to 255 represent values from 0 to 1. The shader will still return a logical - RGBA value; this format determines how those channels are stored in the image. Later, the graphics pipeline will - use {swapChainDescFormat} to match this attachment.' -tutorial.swapChain.title: Create the swap chain +tutorial.surface.details: The framebuffer is the window's image in pixels. {surface} describes the native presentation + target and its dimensions, and {framebufferSize} gives the size in pixels. With display scaling, this can differ + from the window's logical size. +tutorial.surface.guidance: 'The surface supplies the native handles needed by the selected backend: a Win32 window + on Windows, an X11 display and window on Linux, or the attached Metal layer on macOS.' +tutorial.surface.title: Native surface +tutorial.swapChain.context: 'The swap chain depends on both the context and the window. Replace {windowDispose} + at the end of {programCs} with this disposal order:' +tutorial.swapChain.description: 'Create the swap chain immediately after the surface description:' +tutorial.swapChain.details: The {swapChain} manages the images presented by the window. {drawable} supplies the + current image as a {texture}, the API's image resource. After rendering, {present} requests display of that image + and advances to the next drawable. +tutorial.swapChain.guidance: '{b8G8R8A8UNorm} stores four 8-bit channels in blue, green, red, and alpha order. {uNorm} + maps integer values 0–255 to values 0–1. Shader output remains a logical RGBA value; the format specifies its + storage representation. The pipeline will use {swapChainDescFormat} to match this attachment.' +tutorial.swapChain.title: Swap chain tutorial.title: First Triangle -tutorial.troubleshooting.description: 'Read any error in the console first, then use the earlier checkpoints to - identify the stage that failed:' -tutorial.troubleshooting.details: Use the {link} and {detail} to compare the vertex data, input layout and draw - operation. That sample places windowing and submission in a shared host; this tutorial keeps the application - flow in {programCs}. Continue with {context} to learn indexed drawing, transformations and depth testing. +tutorial.troubleshooting.description: 'Use console diagnostics and the three checkpoints to identify the failing + stage:' +tutorial.troubleshooting.details: The {link} and {detail} provide a reference for the vertex data, input layout, + and draw operation. That example separates windowing and submission into a shared host; this tutorial retains + the application flow in {programCs}. {context} introduces indexed drawing, transformations, and depth testing. tutorial.troubleshooting.details.context: Spinning Cube tutorial.troubleshooting.details.detail: Slang shader tutorial.troubleshooting.details.link: sample renderer @@ -913,23 +844,16 @@ tutorial.troubleshooting.table.shaders.symptom: The clear-color step works, but tutorial.troubleshooting.table.window.check: Confirm the .NET project builds and the window-only step runs in a desktop session. On Linux, check that X11 or XWayland is available. tutorial.troubleshooting.table.window.symptom: No window opens -tutorial.troubleshooting.title: Check the stage that failed -tutorial.window.context: '{usingZenithTutorials} imports the helper''s namespace. Each C# file uses its own ordinary - using directives, so the interop import is needed in both files. The {buffer} alias refers to the Zenith.NET - buffer type and distinguishes it from {systemBuffer}.' -tutorial.window.description: Add {cocoaHelperCs} to the project, keeping its namespace. Add {interopUsing} at - the top of that file, before its namespace declaration. The helper attaches a Metal layer to the window on macOS; - the other platform branches do not call it. -tutorial.window.details: 'Replace the generated {programCs} with the following code. It uses top-level statements, - which execute in order without an explicit {main} method. Later sections will tell you where to add code to this - same file:' -tutorial.window.guidance: '{graphicsAPINone} asks Silk.NET to create a window without its own graphics context. - We will create that context with Zenith.NET. {initialize} creates the native window and makes its handles available. - A handle is an identifier supplied by the windowing system. {center} centers the window, and {run} processes events - until it closes. Execution then continues to {dispose}, which releases the window.' -tutorial.window.notes: Run {dotnetRun}. An empty window should open and respond to moving, resizing and closing. - Its contents are not defined yet because we have not submitted any rendering commands. Close it before continuing. -tutorial.window.title: Open a window +tutorial.troubleshooting.title: Troubleshooting +tutorial.window.description: "Download {cocoaHelperCs} into the project. This helper class attaches the Metal layer to the macOS window." +tutorial.window.details: 'Replace the generated {programCs} with the code below. It uses top-level statements, which + run in order without an explicit {main} method. Each later section will show where to add its code:' +tutorial.window.guidance: '{graphicsAPINone} leaves graphics-context creation to Zenith.NET. {initialize} creates + the native window and makes its window-system handles available. {center} places the window in the center of the + screen. {run} processes events until the window closes, then execution continues to {dispose} to release it.' +tutorial.window.notes: Build and run the application, then check that the window opens, moves, resizes, and closes. + Its contents are not yet defined because no rendering commands have been submitted. Close the window before continuing. +tutorial.window.title: Window creation ui.action.copy: Copy ui.action.navigate: Navigate ui.action.open: Open @@ -952,7 +876,7 @@ ui.content.tutorial: Tutorial ui.contents.close: Close contents ui.contents.open: Open contents ui.contents.title: Contents -ui.footer.caption: Modern RHI for .NET. +ui.footer.caption: Modern RHI for .NET ui.footer.label: Footer ui.language.label: Language ui.language.unavailable: Not translated diff --git a/documents/locales/es-ES/strings.yml b/documents/locales/es-ES/strings.yml index f06c8ab7..e0bd4966 100644 --- a/documents/locales/es-ES/strings.yml +++ b/documents/locales/es-ES/strings.yml @@ -1,604 +1,592 @@ ### YamlMime:Resources -concepts.execution.context.description: Un {graphicsContext} representa un dispositivo de backend y proporciona sus colas de gráficos, cálculo y transferencia. Cree los búferes, texturas, sombreadores y canalizaciones para una carga de trabajo a través del mismo contexto. Un recurso o identificador creado por otro contexto no se puede vincular simplemente a los búferes de comandos de este. -concepts.execution.context.details: Elija el backend para la plataforma y la superficie de presentación. La API sigue siendo compartida, pero la compatibilidad del dispositivo sigue siendo importante. {capabilities} expone el nombre del dispositivo y los indicadores {rayTracingSupported} y {meshShadingSupported}. Compruebe el indicador correspondiente antes de crear una carga de trabajo opcional, como hacen los ejemplos {link} y {detail}. Estos indicadores no son una lista completa de restricciones de formato, memoria o plataforma. -concepts.execution.context.details.detail: sombreado de mallas -concepts.execution.context.details.link: trazado de rayos -concepts.execution.context.title: El contexto conecta recursos y colas -concepts.execution.description: Una aplicación de Zenith.NET crea recursos de GPU, graba comandos que los utilizan y envía esos comandos a una cola. La CPU puede continuar mientras la GPU ejecuta el envío. Mantenga los recursos válidos hasta que finalice ese trabajo, incluso después de que las llamadas de grabación hayan regresado. -concepts.execution.ownership.description: "Aquí, la propiedad significa responsabilidad de liberación. Una referencia de C# mantiene accesible un objeto administrado; no evita que un {dispose} explícito destruya el recurso nativo. Del mismo modo, enviar un comando que utiliza un búfer no transfiere la propiedad de ese búfer a la cola." -concepts.execution.ownership.details: Al apagar, deje de enviar nuevo trabajo, espere los últimos usos en cada cola involucrada, libere los recursos de la aplicación y luego libere el contexto. La liberación del contexto libera sus propias colas y asistentes internos; no espera todo el trabajo de la aplicación ni libera cada recurso que la aplicación creó. -concepts.execution.ownership.guidance: Aplique las mismas reglas de tiempo de vida durante el renderizado. Conserve el valor de finalización del último uso de un recurso para saber cuándo se pueden sobrescribir sus bytes o reemplazar el recurso. Consulte {link} para obtener información sobre vistas y tiempos de vida de recursos de respaldo. -concepts.execution.ownership.guidance.link: Administración de recursos -concepts.execution.ownership.table.applicationResources.object: Recursos creados por la aplicación -concepts.execution.ownership.table.applicationResources.ownership: La aplicación los libera después de su último uso en la GPU. -concepts.execution.ownership.table.commandBuffers.object: Búferes de comandos prestados -concepts.execution.ownership.table.commandBuffers.ownership: La cola los gestiona y los recicla. -concepts.execution.ownership.table.headings.object: Objeto -concepts.execution.ownership.table.headings.ownership: ¿Quién lo libera? -concepts.execution.ownership.table.queues.object: Colas de contexto y sus líneas de tiempo -concepts.execution.ownership.table.queues.ownership: El contexto y las colas los gestionan. -concepts.execution.ownership.table.swapChainDrawable.ownership: La cadena de intercambio lo gestiona. -concepts.execution.ownership.title: Mantener la propiedad separada de la finalización en la GPU -concepts.execution.pipelines.description: "Una canalización de gráficos combina sombreadores, el diseño de entrada de vértices, la regla para ensamblar vértices en primitivas, formatos de adjuntos y estado de renderizado. Establézcala antes de enlazar datos de vértices, índices o constantes y de emitir comandos de dibujo. Sus formatos de adjuntos y recuento de muestras deben coincidir con los adjuntos de la pasada de renderizado." -concepts.execution.pipelines.details: Una canalización de cálculo proporciona el punto de entrada del sombreador para un dispatch, que inicia grupos de subprocesos de GPU. Establézcala y configure sus constantes antes del dispatching. Los dispatches de cálculo pertenecen a fuera de las pasadas de renderizado gráfico. Cambiar la canalización es un cambio en la forma en que los comandos posteriores interpretan sus entradas; enlace los datos requeridos por la canalización seleccionada antes de usarla. -concepts.execution.pipelines.guidance: "La {link} muestra la secuencia gráfica completa. El {detail} graba un dispatch seguido de una pasada gráfica que muestra el resultado." -concepts.execution.pipelines.guidance.detail: ejemplo de cálculo -concepts.execution.pipelines.guidance.link: devolución de llamada de renderizado del triángulo -concepts.execution.pipelines.title: Una canalización determina cómo interpretan los datos los comandos -concepts.execution.queues.description: Comience con {graphicsQueue} cuando un fotograma combine dibujo, cálculo y copias. Mantener el trabajo dependiente en una cola facilita seguir su ordenación. -concepts.execution.queues.details: Una cola acepta lotes de comandos para su ejecución. Las colas separadas no corresponden necesariamente a motores de hardware independientes, por lo que su trabajo podría no ejecutarse simultáneamente. Utilice otra cola cuando la carga de trabajo pueda beneficiarse de la superposición y agregue una dependencia explícita cuando una cola consuma los resultados de otra cola. -concepts.execution.queues.guidance: Cuando los comandos posteriores dependen de escrituras anteriores, la aplicación también debe asegurarse de que esas escrituras estén disponibles para los comandos posteriores. Enviar ambos búferes de comandos a la misma cola no establece automáticamente cada dependencia de este tipo. Los comandos pueden usar diferentes etapas de GPU, y los accesos posteriores pueden necesitar una barrera o una transición de textura. {link} explica la distinción entre el orden de envío y la visibilidad de los recursos. -concepts.execution.queues.guidance.link: Sincronización -concepts.execution.queues.table.computeQueue.workToRecord: Dispatches de cálculo y trabajo de transferencia compatible, sin pasadas de renderizado gráfico. -concepts.execution.queues.table.graphicsQueue.workToRecord: Pasadas de renderizado y dibujo, más operaciones de cálculo y transferencia utilizadas por el fotograma. -concepts.execution.queues.table.headings.queue: Cola -concepts.execution.queues.table.headings.workToRecord: Trabajo a grabar -concepts.execution.queues.table.transferQueue.workToRecord: Trabajo de carga, descarga y copia, sin dibujo ni dispatches de cálculo. -concepts.execution.queues.title: Elegir una cola para el trabajo que ejecutará -concepts.execution.recording.context: La cola sondea la finalización y recicla los búferes de comandos terminados. Llame a {queueCommandBuffer} para cada nueva grabación; puede devolver una instancia reciclada. No libere un búfer de comandos prestado, no lo envíe dos veces ni continúe grabando en él después del envío. Grabe un búfer de comandos determinado desde un solo subproceso a la vez; el bloqueo interno de la cola no protege contra modificaciones simultáneas en un búfer de comandos. -concepts.execution.recording.description: "{queueCommandBuffer} devuelve un {commandBuffer} con la grabación ya iniciada. Grabe los comandos y sus dependencias, luego llame a {submit} una vez. El envío finaliza la grabación y devuelve un {timelineValue} que identifica un punto de finalización en esa cola." -concepts.execution.recording.details: "Por ejemplo, después de grabar un fotograma en {commandBuffer}, el triángulo lo envía y espera a que se complete con:" -concepts.execution.recording.guidance: "{submit} programa el trabajo; {wait} evita que la CPU continúe hasta que se haya completado ese envío. Grabar un dibujo, finalizar una pasada de renderizado y enviar un búfer de comandos son operaciones independientes. Ni grabar el dibujo ni finalizar la pasada esperan a la GPU." -concepts.execution.recording.title: La grabación no ejecuta comandos -concepts.execution.title: Modelo de ejecución -concepts.platforms.description: Elija si su aplicación posee la ventana nativa y el bucle de fotogramas o si utiliza un control de renderizado de interfaz de usuario. Esa elección determina quién obtiene la textura de salida, envía comandos y presenta el resultado. La textura de salida es la textura utilizada como salida del fotograma actual. El trabajo de gráficos y cálculo fuera de pantalla no necesita una ventana ni una cadena de intercambio. -concepts.platforms.frame.context: Agregue sus enlaces de canalización y comandos de dibujo dentro de esa pasada. Finalice la pasada antes de regresar. No envíe el búfer de comandos suministrado ni presente de forma independiente, y no libere el búfer de comandos ni la textura de salida. Si su controlador utiliza la textura de salida en otro layout, devuélvala a {colorAttachment} para la transición final del control. -concepts.platforms.frame.description: Las integraciones implementan {iZenithView}. La aplicación suministra su {graphicsContext}, actualiza datos de escena en {updateRequested} y graba el renderizado en {renderRequested} mediante {renderEventArgs}. -concepts.platforms.frame.details: "El control gestiona el ciclo completo de cada fotograma. Obtiene la textura de salida y el búfer de comandos, cambia la textura a {colorAttachment}, invoca los controladores de eventos y realiza el envío y la presentación que requiere el framework." -concepts.platforms.frame.guidance: "Para un {iZenithView} inicializado llamado {view}, con un contexto asignado, este controlador graba una pasada de borrado completa. Requiere {usingZenithNET}:" -concepts.platforms.frame.notes: Los controles pasan de {undefined} al inicio de cada fotograma, por lo que las aplicaciones no pueden depender de que se conserve el contenido anterior de la textura de salida. Borre o renderice la imagen requerida en cada fotograma. Mantenga la acumulación persistente o el renderizado almacenado en caché en una textura propiedad de la aplicación y luego muestre esa textura a través de la vista. -concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat} suministra el formato de color predeterminado de las integraciones. Compruebe la textura de salida real del evento al hacer coincidir los formatos de adjuntos, los recuentos de muestras y las dimensiones." -concepts.platforms.frame.title: Grabar en el fotograma suministrado por un control de interfaz de usuario -concepts.platforms.integration.context: WinForms, WPF y la ruta de WinUI de Windows requieren Windows. Las aplicaciones MAUI necesitan la carga de trabajo de su plataforma de destino y deben registrar el controlador del control con {useZenithView}; consulte {extensionsCs}. Se deben cumplir tanto la compatibilidad del marco como la del backend. -concepts.platforms.integration.description: "Los controles comparten la interfaz de eventos, pero no todos presentan de la misma manera:" -concepts.platforms.integration.details: La lectura de mapas de bits (bitmap readback) copia los píxeles renderizados en la memoria de la CPU antes de que la interfaz de usuario los muestre. La interoperabilidad de texturas compartidas evita esa lectura, pero aún puede requerir copias y sincronización de GPU. Por lo tanto, la interfaz {renderRequested} compartida no implica costos de presentación idénticos o requisitos de interoperabilidad nativa iguales. -concepts.platforms.integration.guidance: "Utilice el paquete para el marco de la aplicación; por ejemplo:" -concepts.platforms.integration.table.avalonia.integration: Avalonia -concepts.platforms.integration.table.avalonia.presentation: Renderiza en una textura y descarga píxeles en un {writeableBitmap}. Consulte {zenithViewCs} y {surfaceCs}. -concepts.platforms.integration.table.headings.integration: Integración -concepts.platforms.integration.table.headings.presentation: Cómo llega su imagen a la interfaz de usuario -concepts.platforms.integration.table.maui.integration: .NET MAUI -concepts.platforms.integration.table.maui.presentation: Utiliza superficies nativas en Android, iOS y Mac Catalyst, y composición de texturas compartidas en Windows. Consulte las {link}. -concepts.platforms.integration.table.maui.presentation.link: implementaciones de plataforma -concepts.platforms.integration.table.uno.integration: Ruta de Uno -concepts.platforms.integration.table.uno.presentation: Descarga píxeles en un {writeableBitmap}. Consulte {zenithViewUnoCs}. -concepts.platforms.integration.table.winForms.integration: WinForms -concepts.platforms.integration.table.winForms.presentation: Crea una cadena de intercambio de Zenith.NET para el {hWND} del control. Consulte {zenithViewCs}. -concepts.platforms.integration.table.winUI.integration: WinUI en Windows -concepts.platforms.integration.table.winUI.presentation: Renderiza en una textura compartida de Direct3D 11 importada y luego copia a una cadena de intercambio de composición conectada a {swapChainPanel}. Consulte {zenithViewWinUICs}. -concepts.platforms.integration.table.wpf.integration: WPF -concepts.platforms.integration.table.wpf.presentation: Importa una textura compartida de Direct3D 11 y luego copia a través de interoperabilidad Direct3D a una superficie mostrada por {d3DImage}. Consulte {surfaceCs}. -concepts.platforms.integration.title: Elegir la ruta de presentación así como el marco de trabajo -concepts.platforms.lifecycle.context: Para una vista de interfaz de usuario, utilice {descWidth}, {descHeight}, {descFormat} y {descSampleCount} de la textura de salida del evento al crear recursos de renderizado coincidentes. El control determina la resolución de esa textura de salida; no asuma que sus dimensiones lógicas o escala de pantalla siempre son iguales a las dimensiones de la textura. -concepts.platforms.lifecycle.description: Para una cadena de intercambio nativa, pase las dimensiones del búfer de fotogramas en píxeles. Los tamaños de ventana expresados en unidades lógicas pueden diferir cuando la escala de pantalla está activada. Omita los búferes de fotogramas de tamaño cero, cambie el tamaño de la cadena de intercambio cuando cambie su tamaño de píxeles y obtenga {swapChainDrawable} para cada fotograma. La textura de salida es propiedad de la cadena de intercambio y puede cambiar después de la presentación o del cambio de tamaño. -concepts.platforms.lifecycle.details: "{swapChainResize} cambia las dimensiones de la superficie existente. {swapChainRefresh} reemplaza la descripción de la superficie, incluidos sus identificadores nativos. Antes de cualquiera de las operaciones, complete los usos pendientes de los recursos afectados. Libere la cadena de intercambio antes de destruir su destino de presentación nativo." -concepts.platforms.lifecycle.guidance: "Vuelva a crear texturas fuera de pantalla o de profundidad propiedad de la aplicación cuyo tamaño siga a la ventana y actualice las constantes que contengan sus identificadores. Una canalización puede seguir en uso a través de un cambio de tamaño cuando sus formatos de adjuntos y recuento de muestras siguen siendo compatibles. El {link} mantiene su canalización mientras reemplaza su textura de profundidad." -concepts.platforms.lifecycle.guidance.link: renderizador de cubo giratorio -concepts.platforms.lifecycle.title: Mantener el tamaño y el tiempo de vida de la textura de salida con su host -concepts.platforms.ownership.description: "La aplicación es propietaria del contexto que asigna y de los recursos que crea para renderizar. El control posee sus propios recursos de presentación. Cambiar la propiedad {graphicsContext} de la vista hace que el planificador recree los recursos del control; no recrea las canalizaciones, los búferes ni las texturas de la aplicación para el nuevo contexto." -concepts.platforms.ownership.details: Coordine el reemplazo de recursos con el ciclo de vida de los fotogramas de la vista. Detenga la actividad de fotogramas de la vista y finalice los usos pendientes de la GPU antes de liberar los recursos de la aplicación o el contexto asignado. Quitar una vista no transfiere la propiedad del contexto al control. -concepts.platforms.ownership.guidance: El archivo compartido {frameSchedulerCs} despacha el trabajo del fotograma a través del despachador de interfaz de usuario de la vista. Mantenga los controladores de fotogramas enfocados en actualizar y grabar el fotograma; el trabajo prolongado de la CPU allí también retrasa la interfaz de usuario. -concepts.platforms.ownership.title: Mantener los recursos de la aplicación fuera de la propiedad del control -concepts.platforms.surface.context: Que una biblioteca de ventanas o un marco de interfaz de usuario sea compatible con un sistema operativo no garantiza que el backend de GPU seleccionado esté disponible allí. Las funciones del dispositivo, los controladores y la compatibilidad con superficies nativas aún deben coincidir. Compruebe el trazado de rayos y el sombreado de mallas opcionales a través de {contextCapabilities} antes de crear esas cargas de trabajo. -concepts.platforms.surface.description: El {link} utiliza Silk.NET para crear una ventana y procesar eventos. Zenith.NET se conecta a esa ventana a través de una descripción de {surface} y una {swapChain}. Una superficie contiene identificadores y dimensiones nativas; construir la descripción no crea ni posee la ventana del sistema operativo. -concepts.platforms.surface.description.link: triángulo -concepts.platforms.surface.details: "El identificador debe coincidir con el backend seleccionado:" -concepts.platforms.surface.guidance: El archivo {appCs} del tutorial muestra las opciones de Windows, macOS y X11. Su host de Linux suministra identificadores Xlib; usarlo en una sesión Wayland requiere XWayland. Una aplicación nativa de Wayland suministraría diferentes identificadores a través de {surfaceWayland}. -concepts.platforms.surface.table.android.backend: Vulkan en Android. -concepts.platforms.surface.table.apple.backend: Metal en plataformas Apple. -concepts.platforms.surface.table.headings.backend: Ruta de backend -concepts.platforms.surface.table.headings.factory: Fábrica de superficies -concepts.platforms.surface.table.headings.handles: Identificadores suministrados por el host -concepts.platforms.surface.table.wayland.backend: Vulkan con un host Wayland nativo. -concepts.platforms.surface.table.wayland.handles: Pantalla y superficie Wayland -concepts.platforms.surface.table.win32.backend: DirectX 12 o Vulkan en Windows. -concepts.platforms.surface.table.xlib.backend: Vulkan en Linux con X11 o XWayland. -concepts.platforms.surface.table.xlib.handles: Pantalla y ventana X11 -concepts.platforms.surface.title: Suministrar una superficie nativa cuando la aplicación posee la presentación -concepts.platforms.title: Integración de plataforma -concepts.resources.allocation.context: "Empiece con recursos creados por el contexto, salvo que necesite su propio asignador de memoria. Al usar un montículo, espere a que termine todo el trabajo de GPU que utiliza sus recursos; después libere los recursos ubicados y, por último, el propio montículo." -concepts.resources.allocation.description: "Un {heap} proporciona memoria en la que se ubican recursos en desplazamientos explícitos en bytes. La aplicación elige esos desplazamientos y lleva el control de las regiones en uso." -concepts.resources.allocation.details: "Antes de ubicar un recurso, utilice {contextGetSizeAndAlignment} con su descripción exacta de búfer o textura. Elija un desplazamiento múltiplo de la alineación devuelta, reserve el tamaño devuelto y mantenga el recurso dentro del tamaño total del montículo. Las asignaciones en uso no deben solaparse. El almacenamiento de texturas puede incluir relleno y alineación específicos del backend; multiplicar el número de píxeles por los bytes por píxel no permite calcular el tamaño de la asignación." -concepts.resources.allocation.guidance: "Para los búferes ubicados, mantenga la residencia del búfer coherente con la del montículo. Utilice montículos exclusivos de GPU para las texturas de GPU ordinarias descritas aquí. El tamaño y la alineación son requisitos de ubicación, no una garantía de que cualquier recurso pueda ubicarse en cualquier montículo en todos los backends." -concepts.resources.allocation.title: Ubicar recursos en un montículo cuando se necesita control de asignación -concepts.resources.bufferUsages.table.constant.role: Parámetros de sombreador leídos a través de un enlace de búfer de constantes. +concepts.execution.context.description: "Un {graphicsContext} conecta la aplicación con un dispositivo GPU mediante un backend concreto y proporciona sus colas gráfica, de cálculo y de transferencia. Los recursos que se utilizan juntos deben pertenecer al mismo contexto; no se pueden enlazar búferes, texturas, sombreadores, canalizaciones ni sus identificadores entre contextos distintos." +concepts.execution.context.details: "{capabilities} indica el nombre del dispositivo y las funciones que admite. Compruebe {rayTracingSupported} y {meshShadingSupported} antes de crear los recursos que necesitan esas funciones. Los ejemplos de {link} y {detail} realizan estas comprobaciones durante la inicialización." +concepts.execution.context.details.detail: "sombreado de mallas" +concepts.execution.context.details.link: "trazado de rayos" +concepts.execution.context.title: "Contexto gráfico" +concepts.execution.description: "El trabajo de la GPU se prepara en la CPU: la aplicación crea recursos, graba comandos que los utilizan y envía esos comandos a una cola. Tras el envío, la CPU puede continuar mientras la GPU ejecuta el trabajo. Los recursos deben seguir disponibles hasta que esa ejecución termine." +concepts.execution.ownership.description: "La propiedad establece quién libera un objeto; la finalización en la GPU determina cuándo puede hacerlo. Una llamada a {dispose} libera los recursos nativos aunque aún existan referencias de C# al objeto. Enviar comandos no transfiere a la cola la propiedad de los recursos que utilizan." +concepts.execution.ownership.details: "Al cerrar la aplicación, deje de enviar trabajo y espere al último uso de los recursos en cada cola implicada. Después, libere los recursos de la aplicación y el contexto. El contexto libera sus colas y auxiliares internos, por lo que este último paso debe realizarse cuando todo el trabajo de la aplicación haya terminado." +concepts.execution.ownership.guidance: "Durante el renderizado, lleve un seguimiento del trabajo que utiliza datos que se van a sobrescribir o recursos que se van a sustituir. Espere a que termine antes de modificar o liberar el almacenamiento afectado. {link} explica cómo se aplica este modelo de vida útil a las vistas y a los recursos que las respaldan." +concepts.execution.ownership.guidance.link: "Administración de recursos" +concepts.execution.ownership.table.applicationResources.object: "Recursos creados por la aplicación" +concepts.execution.ownership.table.applicationResources.ownership: "La aplicación los libera después de su último uso en la GPU." +concepts.execution.ownership.table.commandBuffers.object: "Búferes de comandos prestados" +concepts.execution.ownership.table.commandBuffers.ownership: "La cola los gestiona y los recicla." +concepts.execution.ownership.table.headings.object: "Objeto" +concepts.execution.ownership.table.headings.ownership: "Responsabilidad de liberación" +concepts.execution.ownership.table.queues.object: "Colas de contexto y sus líneas de tiempo" +concepts.execution.ownership.table.queues.ownership: "El contexto y las colas las gestionan." +concepts.execution.ownership.table.swapChainDrawable.ownership: "La cadena de intercambio lo gestiona." +concepts.execution.ownership.title: "Propiedad y tiempo de vida" +concepts.execution.pipelines.description: "Una canalización gráfica define los sombreadores, la disposición de entrada de vértices, el ensamblado de primitivas, los formatos de adjunto y el estado de renderizado. Se selecciona antes de enlazar vértices, índices o constantes. Los formatos y el número de muestras deben coincidir con la pasada de renderizado." +concepts.execution.pipelines.details: "Una canalización de cálculo selecciona el punto de entrada del sombreador que ejecutará un despacho. Enlace la canalización y sus constantes antes del despacho, fuera de una pasada de renderizado gráfico." +concepts.execution.pipelines.guidance: "La {link} presenta la secuencia gráfica. El {detail} incorpora un despacho de cálculo antes de la pasada que muestra su resultado." +concepts.execution.pipelines.guidance.detail: "ejemplo de cálculo" +concepts.execution.pipelines.guidance.link: "función de renderizado del triángulo" +concepts.execution.pipelines.title: "Estado de la canalización" +concepts.execution.queues.description: "{graphicsQueue} es el punto de partida habitual para un fotograma que combina dibujo, cálculo y copias. Agrupar operaciones dependientes en una cola simplifica su ordenación." +concepts.execution.queues.details: "Las colas permiten enviar cargas de trabajo independientes por separado, aunque no necesariamente corresponden a motores de hardware independientes. Use colas adicionales cuando resulte útil solapar la ejecución. Si una cola utiliza datos producidos por otra, conecte sus envíos mediante una dependencia explícita." +concepts.execution.queues.guidance: "Dentro de una cola, las operaciones dependientes también pueden necesitar barreras o transiciones de textura para que los accesos posteriores vean las escrituras anteriores. Estas dependencias de memoria son distintas del orden de envío; {link} explica cómo expresarlas." +concepts.execution.queues.guidance.link: "Sincronización" +concepts.execution.queues.table.computeQueue.workToRecord: "Despachos de cálculo y transferencias compatibles, sin pasadas gráficas." +concepts.execution.queues.table.graphicsQueue.workToRecord: "Pasadas de renderizado, dibujo, cálculo y transferencias." +concepts.execution.queues.table.headings.queue: "Cola" +concepts.execution.queues.table.headings.workToRecord: "Operaciones admitidas" +concepts.execution.queues.table.transferQueue.workToRecord: "Cargas, descargas y copias, sin dibujo ni despachos de cálculo." +concepts.execution.queues.title: "Selección de colas" +concepts.execution.recording.context: "La cola recupera los búferes de comandos completados para reutilizarlos. Obtenga uno con {queueCommandBuffer} para cada grabación, grabe desde un solo hilo a la vez y envíelo una única vez. Después del envío, deje que la cola lo gestione: no lo modifique, vuelva a enviar ni libere." +concepts.execution.recording.description: "{queueCommandBuffer} devuelve un {commandBuffer} cuya grabación ya está iniciada. Tras grabar las operaciones y sus dependencias, se llama a {submit} una vez. El envío cierra la grabación y devuelve un {timelineValue} que identifica su finalización en esa cola." +concepts.execution.recording.details: "Tras grabar un fotograma en {commandBuffer}, el tutorial lo envía y espera de este modo:" +concepts.execution.recording.guidance: "La grabación construye la secuencia de comandos; {submit} programa su ejecución. La llamada posterior a {wait} bloquea el hilo de la CPU hasta que termina ese envío. Así, el bucle del tutorial resulta fácil de seguir: cada fotograma termina antes de comenzar el siguiente." +concepts.execution.recording.title: "Grabación y envío" +concepts.execution.title: "Modelo de ejecución" +concepts.platforms.description: "La presentación puede gestionarla la aplicación o un control de interfaz. Esta elección determina quién obtiene la textura de salida del fotograma, registra y envía los comandos y presenta el resultado. Esa textura de salida se denomina drawable." +concepts.platforms.frame.context: "Grabe los enlaces de canalización y los comandos de dibujo dentro de la pasada y termínela antes de que retorne el manejador. El control envía los comandos y presenta el resultado. El manejador no debe enviar el búfer de comandos ni liberar ninguno de los objetos recibidos. Si cambia la disposición de la textura de salida, restáurela a {colorAttachment} antes de retornar para que el control pueda realizar la transición final." +concepts.platforms.frame.description: "Los controles implementan {iZenithView}. La aplicación asigna {graphicsContext}, actualiza la escena en {updateRequested} y graba en {renderRequested} mediante los {renderEventArgs} recibidos." +concepts.platforms.frame.details: "En cada fotograma, el control obtiene una textura de salida y un búfer de comandos, cambia la disposición de la textura a {colorAttachment} y llama a los manejadores de actualización y renderizado. Después envía el trabajo grabado y presenta la imagen mediante el mecanismo del framework." +concepts.platforms.frame.guidance: "Añada {usingZenithNET} al archivo. Para una instancia de {iZenithView} llamada {view}, ya inicializada y con un contexto gráfico asignado, registre este manejador del evento de renderizado para borrar la textura de salida que proporciona el control:" +concepts.platforms.frame.notes: "La transición inicial utiliza {undefined}, que permite descartar el contenido anterior. Dibuje o borre la imagen completa en cada fotograma. Guarde el renderizado acumulado o en caché en una textura propia de la aplicación y dibújela después sobre la textura de salida del control." +concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat} proporciona el formato de color predeterminado de estas integraciones." +concepts.platforms.frame.title: "Renderizado mediante controles de interfaz" +concepts.platforms.integration.context: "WinForms, WPF y la integración Windows de WinUI se ejecutan en Windows. Para MAUI, instale la carga de trabajo de la plataforma de destino y registre el controlador con {useZenithView}, como se muestra en {extensionsCs}." +concepts.platforms.integration.description: "La interfaz de eventos es común, pero la presentación depende del framework:" +concepts.platforms.integration.details: "Estas implementaciones difieren en cómo llevan la imagen de la GPU a la interfaz. La lectura como mapa de bits copia los píxeles a la memoria de la CPU antes de mostrarlos. La interoperabilidad mediante texturas compartidas evita esa copia, pero aún puede necesitar copias en la GPU y sincronización. Al elegir una integración, considere este mecanismo de presentación además del evento común {renderRequested}." +concepts.platforms.integration.guidance: "Añada mediante NuGet el paquete de integración de su framework de interfaz. Para Avalonia, utilice {avaloniaPackage}." +concepts.platforms.integration.table.avalonia.integration: "Avalonia" +concepts.platforms.integration.table.avalonia.presentation: "Renderiza en una textura y descarga píxeles en un {writeableBitmap}. Consulte {zenithViewCs} y {surfaceCs}." +concepts.platforms.integration.table.headings.integration: "Integración" +concepts.platforms.integration.table.headings.presentation: "Mecanismo de presentación" +concepts.platforms.integration.table.maui.integration: ".NET MAUI" +concepts.platforms.integration.table.maui.presentation: "Utiliza superficies nativas en Android, iOS y Mac Catalyst, y composición de texturas compartidas en Windows. Consulte las {link}." +concepts.platforms.integration.table.maui.presentation.link: "implementaciones de plataforma" +concepts.platforms.integration.table.uno.integration: "Ruta de Uno" +concepts.platforms.integration.table.uno.presentation: "Descarga píxeles en un {writeableBitmap}. Consulte {zenithViewUnoCs}." +concepts.platforms.integration.table.winForms.integration: "WinForms" +concepts.platforms.integration.table.winForms.presentation: "Crea una cadena de intercambio de Zenith.NET para el {hWND} del control. Consulte {zenithViewCs}." +concepts.platforms.integration.table.winUI.integration: "WinUI en Windows" +concepts.platforms.integration.table.winUI.presentation: "Renderiza en una textura compartida de Direct3D 11 importada y copia el resultado a una cadena de intercambio de composición conectada a {swapChainPanel}. Consulte {zenithViewWinUICs}." +concepts.platforms.integration.table.wpf.integration: "WPF" +concepts.platforms.integration.table.wpf.presentation: "Importa una textura compartida de Direct3D 11 y copia su contenido, mediante interoperabilidad con Direct3D, a una superficie que muestra {d3DImage}. Consulte {surfaceCs}." +concepts.platforms.integration.title: "Framework y presentación" +concepts.platforms.lifecycle.context: "Al crear adjuntos compatibles, utilice {descWidth}, {descHeight}, {descFormat} y {descSampleCount} de la textura de salida que proporciona el evento de renderizado. Esa textura indica las dimensiones reales del destino; no deben deducirse del tamaño de diseño del control ni de la escala de pantalla." +concepts.platforms.lifecycle.description: "La cadena de intercambio utiliza el ancho y el alto en píxeles del búfer de fotogramas, que pueden diferir del tamaño lógico de la ventana cuando hay escalado de pantalla. Aplace el renderizado y el redimensionamiento de la cadena mientras alguna dimensión sea cero. Obtenga {swapChainDrawable} en cada fotograma: la cadena de intercambio posee esta textura y puede sustituirla tras presentar o redimensionar." +concepts.platforms.lifecycle.details: "Si cambia el tamaño del búfer de fotogramas, espere a que terminen los usos pendientes de las imágenes anteriores en la GPU antes de llamar a {swapChainResize}. Para sustituir el destino nativo de presentación, espere del mismo modo y pase la nueva descripción de superficie y sus identificadores a {swapChainRefresh}. Al cerrar, libere la cadena de intercambio antes de destruir su destino nativo." +concepts.platforms.lifecycle.guidance: "Si la aplicación tiene texturas de profundidad o fuera de pantalla que siguen el tamaño de la ventana, vuelva a crearlas cuando cambie ese tamaño y actualice las constantes que contengan sus identificadores. La canalización se puede reutilizar mientras sigan coincidiendo los formatos y el número de muestras de los adjuntos. El {link} muestra esta separación entre las texturas que se redimensionan y la canalización reutilizable." +concepts.platforms.lifecycle.guidance.link: "renderizador de cubo giratorio" +concepts.platforms.lifecycle.title: "Dimensiones y vida útil de la cadena de intercambio" +concepts.platforms.ownership.description: "La aplicación posee el contexto asignado y sus recursos de renderizado; el control posee sus recursos de presentación. Cuando cambia {graphicsContext} en la vista, el planificador vuelve a crear los recursos del control para el nuevo contexto. Vuelva a crear también las canalizaciones, los búferes y las texturas de la aplicación para ese contexto." +concepts.platforms.ownership.details: "Antes de sustituir recursos de renderizado, detenga la actividad de fotogramas de la vista y espere al trabajo de la GPU que los utiliza. Solo entonces libere los recursos o el contexto anteriores. Al retirar la vista, la aplicación sigue siendo responsable de liberar el contexto que tenía asignado." +concepts.platforms.ownership.guidance: "El componente compartido {frameSchedulerCs} ejecuta los manejadores de eventos de cada fotograma mediante el distribuidor de la interfaz de la vista. Limite esos manejadores a actualizar la escena y grabar comandos: un trabajo prolongado en la CPU también retrasa la respuesta de la interfaz." +concepts.platforms.ownership.title: "Responsabilidades de aplicación y control" +concepts.platforms.surface.description: "El {link} utiliza Silk.NET para crear la ventana y procesar sus eventos. Zenith.NET recibe los identificadores nativos y las dimensiones mediante una descripción {surface}, con la que crea una {swapChain}. La aplicación sigue siendo responsable de la ventana del sistema operativo." +concepts.platforms.surface.description.link: "tutorial del triángulo" +concepts.platforms.surface.details: "Los identificadores nativos deben corresponder al backend:" +concepts.platforms.surface.guidance: "El programa anfitrión de {appCs} admite Windows, macOS y X11. En Linux, la ventana proporciona identificadores Xlib, por lo que necesita XWayland para ejecutarse en una sesión Wayland. Una aplicación nativa de Wayland proporciona los identificadores de pantalla y superficie mediante {surfaceWayland}." +concepts.platforms.surface.table.android.backend: "Vulkan en Android." +concepts.platforms.surface.table.apple.backend: "Metal en plataformas Apple." +concepts.platforms.surface.table.headings.backend: "Backend y plataforma" +concepts.platforms.surface.table.headings.factory: "Fábrica de superficies" +concepts.platforms.surface.table.headings.handles: "Identificadores suministrados por el host" +concepts.platforms.surface.table.wayland.backend: "Vulkan con un host Wayland nativo." +concepts.platforms.surface.table.wayland.handles: "Pantalla y superficie Wayland" +concepts.platforms.surface.table.win32.backend: "DirectX 12 o Vulkan en Windows." +concepts.platforms.surface.table.xlib.backend: "Vulkan en Linux con X11 o XWayland." +concepts.platforms.surface.table.xlib.handles: "Pantalla y ventana X11" +concepts.platforms.surface.title: "Superficies de presentación nativas" +concepts.platforms.title: "Integración de plataforma" +concepts.resources.allocation.context: "Los recursos colocados en un montículo dependen de su almacenamiento durante toda su vida útil. Después de su último uso en la GPU, libere los recursos antes de liberar el montículo." +concepts.resources.allocation.description: "Use un {heap} cuando la aplicación necesite gestionar las asignaciones por sí misma. Un montículo proporciona almacenamiento donde se colocan los recursos en desplazamientos explícitos en bytes; la aplicación elige esos desplazamientos y lleva el registro de las regiones ocupadas." +concepts.resources.allocation.details: "Para cada recurso, llame a {contextGetSizeAndAlignment} con la descripción de búfer o textura que se utilizará al crearlo. Reserve el tamaño devuelto en un desplazamiento múltiplo de la alineación indicada, dentro del montículo y sin solapar otra asignación en uso. Las texturas pueden necesitar relleno específico del backend; por eso, el número de píxeles y los bytes por píxel no bastan para calcular el tamaño de la asignación." +concepts.resources.allocation.guidance: "La residencia de un búfer colocado en un montículo debe coincidir con la del montículo. Para almacenar texturas, use un montículo exclusivo de la GPU." +concepts.resources.allocation.title: "Asignación en montículos" +concepts.resources.bufferUsages.table.constant.role: "Parámetros de sombreador leídos a través de un enlace de búfer de constantes." concepts.resources.bufferUsages.table.headings.role: "Rol" -concepts.resources.bufferUsages.table.headings.usage: Uso -concepts.resources.bufferUsages.table.index.role: Índices utilizados por el dibujo indexado. -concepts.resources.bufferUsages.table.indirect.role: "Argumentos leídos por comandos de dibujo o dispatch indirectos." +concepts.resources.bufferUsages.table.headings.usage: "Uso" +concepts.resources.bufferUsages.table.index.role: "Índices utilizados por el dibujo indexado." +concepts.resources.bufferUsages.table.indirect.role: "Argumentos leídos por comandos de dibujo o despacho indirectos." concepts.resources.bufferUsages.table.none.role: "No se declaran indicadores de uso del búfer." -concepts.resources.bufferUsages.table.storageReadOnly.role: "Datos de búfer accedidos mediante un enlace de sombreador de solo lectura." -concepts.resources.bufferUsages.table.storageReadWrite.role: "Datos de búfer accedidos mediante un enlace de sombreador de lectura y escritura." +concepts.resources.bufferUsages.table.storageReadOnly.role: "Datos del búfer disponibles mediante un enlace de sombreador de solo lectura." +concepts.resources.bufferUsages.table.storageReadWrite.role: "Datos del búfer disponibles mediante un enlace de sombreador de lectura y escritura." concepts.resources.bufferUsages.table.transferDst.role: "Almacenamiento de destino para una copia de GPU." concepts.resources.bufferUsages.table.transferSrc.role: "Datos de origen para una copia de GPU." -concepts.resources.bufferUsages.table.vertex.role: Atributos de vértice capturados para dibujar. -concepts.resources.bufferUsages.title: Usos de búfer -concepts.resources.description: "Elija la descripción de un recurso según las operaciones que lo utilizarán. Una textura que recibe renderizado, se muestrea en un sombreador y se descarga a la CPU necesita declarar esos tres usos y sincronizar los accesos entre ellos. La ubicación de memoria y el tiempo de vida del recurso son decisiones adicionales." -concepts.resources.memory.context: Para un búfer accesible por la CPU, {map} proporciona a la CPU una dirección. No espera a que la GPU deje de acceder a los mismos bytes. {unmap} igualmente no envía trabajo ni espera a que se complete. Antes de sobrescribir datos editables por la CPU, finalice las lecturas de GPU que aún necesiten su contenido anterior. -concepts.resources.memory.description: "Un {bufferDesc} tiene un campo {residency}. Elíjalo según cómo accederán a los datos la CPU y la GPU:" -concepts.resources.memory.details: La residencia describe el acceso previsto de la CPU a la asignación. No implica que cada dispositivo tenga memoria física de CPU y GPU separada. El triángulo utiliza {cpuWriteOnly} para inicializar un pequeño búfer de vértices directamente. Una malla estática grande puede beneficiarse en cambio del almacenamiento exclusivo de GPU con una carga única. -concepts.resources.memory.guidance: "{textureDesc} no tiene campo de residencia. Las texturas ordinarias creadas por el contexto utilizan almacenamiento de GPU. Su API pública proporciona operaciones de carga y descarga para transferir datos de CPU, sin exponer un método de mapeo directo. Los montículos explícitos permiten controlar la ubicación, como se explica más abajo." -concepts.resources.memory.table.cpuReadOnly.cPUAccess: "Leer la memoria mapeada después de que termine la copia de GPU." +concepts.resources.bufferUsages.table.vertex.role: "Atributos de vértice que leen los comandos de dibujo." +concepts.resources.bufferUsages.title: "Usos de búfer" +concepts.resources.description: "La descripción de un recurso establece cómo puede utilizar la aplicación su almacenamiento. Por ejemplo, una textura que se usa como destino de renderizado, se muestrea en un sombreador y se copia a la CPU necesita los indicadores de uso de las tres operaciones. La ubicación de memoria determina el acceso de la CPU; la sincronización y la gestión de la vida útil determinan cuándo se pueden usar los datos o liberar el almacenamiento." +concepts.resources.memory.context: "En los búferes accesibles desde la CPU, {map} proporciona la dirección desde la que se leen o escriben los datos. Ni el mapeo ni {unmap} esperan al trabajo de la GPU: antes de leer un resultado, la aplicación debe esperar a que termine la escritura que lo produce; antes de modificar esos mismos bytes, debe esperar a que terminen los accesos pendientes de la GPU." +concepts.resources.memory.description: "El campo {residency} de {bufferDesc} establece el acceso de CPU previsto para la asignación:" +concepts.resources.memory.details: "La residencia expresa los requisitos de acceso de la CPU, también en sistemas donde CPU y GPU comparten memoria física. El triángulo utiliza {cpuWriteOnly} para inicializar directamente su pequeño búfer de vértices. Para geometría estática de mayor tamaño, puede ser más adecuado cargar los datos en almacenamiento exclusivo de la GPU." +concepts.resources.memory.guidance: "Las texturas creadas directamente mediante el contexto utilizan almacenamiento de la GPU. Por eso, {textureDesc} no tiene un campo de residencia; la aplicación intercambia sus datos con la memoria de la CPU mediante cargas y descargas." +concepts.resources.memory.table.cpuReadOnly.cPUAccess: "Solo lectura" concepts.resources.memory.table.cpuReadOnly.typicalRole: "Datos producidos por la GPU para su lectura en la CPU" -concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "Escribir la memoria mapeada cuando hayan terminado los lectores anteriores de GPU." +concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "Solo escritura" concepts.resources.memory.table.cpuWriteOnly.typicalRole: "Datos proporcionados o actualizados por la CPU" -concepts.resources.memory.table.gpuOnly.cPUAccess: "Transferir bytes mediante un búfer de carga o de lectura desde la GPU." +concepts.resources.memory.table.gpuOnly.cPUAccess: "Ninguno" concepts.resources.memory.table.gpuOnly.typicalRole: "Geometría estática y datos de trabajo de la GPU" -concepts.resources.memory.table.headings.cPUAccess: Acceso de CPU -concepts.resources.memory.table.headings.residency: Residencia -concepts.resources.memory.table.headings.typicalRole: Rol típico -concepts.resources.memory.title: "Elegir memoria según el acceso de CPU necesario" -concepts.resources.textureUsages.description: "Los indicadores de uso para transferencias describen la dirección de las copias de GPU. El acceso de CPU es una decisión independiente de ubicación de memoria, descrita más abajo." -concepts.resources.textureUsages.details: "Combinar indicadores de uso declara varios roles; no ejecuta las operaciones ni ordena sus accesos. Las texturas siguen necesitando {link} adecuados, y sus formatos deben admitir los usos solicitados en el dispositivo seleccionado." -concepts.resources.textureUsages.details.link: "layout y sincronización" +concepts.resources.memory.table.headings.cPUAccess: "Acceso previsto de la CPU" +concepts.resources.memory.table.headings.residency: "Residencia" +concepts.resources.memory.table.headings.typicalRole: "Rol típico" +concepts.resources.memory.title: "Acceso de CPU y ubicación de memoria" +concepts.resources.textureUsages.description: "Los indicadores de transferencia describen si el recurso actúa como origen o destino de una copia en la GPU. La posibilidad de acceder directamente desde la CPU se decide por separado al elegir la ubicación de memoria." +concepts.resources.textureUsages.details: "Los indicadores de uso declaran las funciones que puede desempeñar una textura. Para pasar de una a otra se deben cumplir los requisitos de {link}; además, el dispositivo elegido debe admitir esos usos para el formato de la textura." +concepts.resources.textureUsages.details.link: "disposición y sincronización" concepts.resources.textureUsages.table.colorAttachment.role: "Un adjunto de color en una pasada de renderizado." concepts.resources.textureUsages.table.depthStencilAttachment.role: "Un adjunto de profundidad y plantilla en una pasada de renderizado." concepts.resources.textureUsages.table.headings.role: "Rol" -concepts.resources.textureUsages.table.headings.usage: Uso +concepts.resources.textureUsages.table.headings.usage: "Uso" concepts.resources.textureUsages.table.none.role: "No se declaran indicadores de uso de la textura." concepts.resources.textureUsages.table.sampled.role: "Datos de textura leídos mediante un enlace de textura muestreada." -concepts.resources.textureUsages.table.storage.role: "Datos de textura accedidos mediante un enlace de textura de almacenamiento para lecturas o escrituras del sombreador." +concepts.resources.textureUsages.table.storage.role: "Datos de textura disponibles para lectura o escritura del sombreador mediante un enlace de textura de almacenamiento." concepts.resources.textureUsages.table.transferDst.role: "Almacenamiento de imagen de destino para una copia de GPU." concepts.resources.textureUsages.table.transferSrc.role: "Datos de imagen de origen para una copia de GPU." -concepts.resources.textureUsages.title: Usos de textura -concepts.resources.title: Administración de recursos -concepts.resources.transfers.context: Una descarga graba una copia de GPU en el almacenamiento interno de lectura. La biblioteca copia esos bytes en el destino de CPU suministrado cuando restablece el búfer de comandos completado para su reutilización. Mantenga el destino asignado y mantenga la memoria administrada anclada hasta que regrese el {wait} del valor de envío. -concepts.resources.transfers.description: "Una carga copia datos de CPU a un recurso de GPU; una descarga copia datos del recurso a la memoria de CPU. Los métodos del propio recurso completan esa transferencia antes de devolver el control:" -concepts.resources.transfers.details: "Estas esperas cubren la transferencia que envían esos métodos. No descubren dependencias con otra cola que ya estuviera leyendo o escribiendo el recurso. Establezca esas dependencias antes de llamar al método del recurso. Una copia directa mediante memoria mapeada también exige que quien llama garantice la finalización del trabajo de GPU correspondiente." -concepts.resources.transfers.guidance: "Utilice {commandBufferUpload} o {commandBufferDownload} cuando las copias deban grabarse con otro trabajo. Los tiempos de vida de sus punteros difieren:" -concepts.resources.transfers.item: "Durante la llamada, una carga copia los datos de origen de CPU en un búfer de carga interno, también llamado memoria provisional o staging. El puntero de origen solo debe permanecer válido durante esa llamada." -concepts.resources.transfers.notes: "Para una textura, el paso de fila es la distancia en bytes entre filas consecutivas de datos de CPU, y el paso de corte es la distancia en bytes entre cortes de profundidad consecutivos. No describen la distribución interna de la textura en memoria de GPU. Consulte {link} para distinguir la finalización de GPU de la disponibilidad de los datos leídos." -concepts.resources.transfers.notes.link: Sincronización -concepts.resources.transfers.table.bufferDownload.transfer: Copia directa de CPU para {cpuReadOnly}; de lo contrario, envía una descarga en la cola de transferencia y espera. -concepts.resources.transfers.table.bufferUpload.transfer: Copia directa de CPU para {cpuWriteOnly}; de lo contrario, envía una carga en la cola de transferencia y espera. -concepts.resources.transfers.table.headings.method: Método -concepts.resources.transfers.table.headings.transfer: "Cómo transfiere los datos" +concepts.resources.textureUsages.title: "Usos de textura" +concepts.resources.title: "Administración de recursos" +concepts.resources.transfers.context: "Una descarga copia primero los datos de la GPU a un almacenamiento interno de lectura. La biblioteca los copia al destino de CPU indicado cuando recupera el búfer de comandos completado. La llamada a {wait} sobre el valor de envío de la descarga completa ambos pasos. Mantenga el destino asignado y la memoria administrada anclada hasta que esa llamada retorne." +concepts.resources.transfers.description: "Las cargas copian datos de la CPU a un recurso de la GPU; las descargas copian datos del recurso a la memoria de la CPU. Los métodos de búferes y texturas completan la transferencia antes de retornar:" +concepts.resources.transfers.details: "Antes de llamar a estos métodos, resuelva los accesos en conflicto de otras colas. La espera interna del método abarca su propia transferencia y no establece una dependencia con otra cola. Cuando se copia directamente a través de memoria mapeada, corresponde al llamador esperar a los accesos de la GPU que entren en conflicto." +concepts.resources.transfers.guidance: "Para enviar transferencias junto con otro trabajo de la GPU, grábelas con {commandBufferUpload} o {commandBufferDownload}. La memoria de origen de una carga y la de destino de una descarga tienen requisitos de vida útil distintos:" +concepts.resources.transfers.item: "Durante una llamada de carga, la biblioteca copia los datos de origen a un almacenamiento temporal de transferencia. Después, la GPU lee los datos desde ese almacenamiento, por lo que el puntero de origen de la aplicación solo debe permanecer válido hasta que retorna la llamada." +concepts.resources.transfers.notes: "En las transferencias de texturas, el paso de fila es la distancia en bytes entre filas consecutivas de datos de la CPU; el paso de sección es la distancia entre secciones de profundidad consecutivas. Estos valores permiten copiar los datos entre su organización en la CPU y el almacenamiento de la textura en la GPU. {link} explica por qué terminar la copia en la GPU y entregar los datos al destino de una descarga son pasos distintos." +concepts.resources.transfers.notes.link: "Sincronización" +concepts.resources.transfers.table.bufferDownload.transfer: "Para {cpuReadOnly}, copia directamente desde la memoria mapeada. En los demás casos, envía la descarga a la cola de transferencia y espera a que termine." +concepts.resources.transfers.table.bufferUpload.transfer: "Para {cpuWriteOnly}, copia directamente a la memoria mapeada. En los demás casos, envía la carga a la cola de transferencia y espera a que termine." +concepts.resources.transfers.table.headings.method: "Método" +concepts.resources.transfers.table.headings.transfer: "Comportamiento de transferencia" concepts.resources.transfers.table.textureTransfers.method: "{textureUpload} / {textureDownload}" -concepts.resources.transfers.table.textureTransfers.transfer: "Utiliza la cola gráfica, cambia el layout del subrecurso seleccionado para realizar la copia, lo cambia al layout final solicitado y espera a que termine la transferencia." -concepts.resources.transfers.title: "Elegir entre transferencias inmediatas y transferencias grabadas" -concepts.resources.usages.description: "{bufferUsages} y {textureUsages} son enumeraciones de indicadores que declaran los roles previstos de un recurso. Se asignan a {bufferDescUsages} y {textureDescUsages}, respectivamente. Una enumeración de indicadores permite combinar varios miembros con {value} cuando un recurso tiene más de un rol." -concepts.resources.usages.title: Declarar los usos requeridos antes de crear un recurso -concepts.resources.views.description: Una {bufferView} describe una región de búfer y su interpretación. Una {textureView} selecciona un tipo de textura compatible, un formato y un rango de subrecursos. Una vista comparte el almacenamiento de respaldo; no copia los datos ni añade usos que faltaban cuando se creó el recurso. Su rango tampoco es una garantía portátil de comprobación de límites en el sombreador. -concepts.resources.views.details: "Utilice el handle del propio recurso para su vista predeterminada, o cree una vista cuando necesite otra región o una interpretación compatible distinta. Mantenga referencias de C# a la vista y al recurso subyacente mientras el trabajo de GPU pueda utilizarlos; un handle de recurso por sí solo no mantiene vivo ninguno de los dos objetos. Libérelos únicamente tras su último uso en la GPU. Después de reemplazar cualquiera de ellos, actualice las constantes que contengan su antiguo {link}." -concepts.resources.views.details.link: "handle de recurso" -concepts.resources.views.guidance: El {link} muestra una textura de profundidad reemplazada al cambiar el tamaño. El {detail} muestra una textura de entrada que se mantiene separada de su salida editable. Ambos hacen que el tiempo de vida del recurso siga al trabajo que realmente lo utiliza. -concepts.resources.views.guidance.detail: ejemplo de cálculo -concepts.resources.views.guidance.link: renderizador de cubo giratorio -concepts.resources.views.title: "Mantener disponibles las vistas y sus recursos subyacentes durante su uso" -concepts.shaders.binding.context: "En el ejemplo de cálculo, {input} se llena con {inputTextureSampledHandle} y {output} con {outputTextureStorageHandle}. El {descriptorHandle} con tipo de Slang indica al sombreador cómo acceder a cada recurso:" -concepts.shaders.binding.description: "{setConstantBuffer} enlaza un búfer y un desplazamiento de bytes para los datos de constantes de la canalización actual. Enlaza el almacenamiento visible por GPU existente; no carga un valor de C#. Llene el búfer primero y asegúrese de que los lectores de GPU anteriores hayan finalizado antes de sobrescribir sus bytes." -concepts.shaders.binding.details: "Establezca la canalización antes de su búfer de constantes. Para una carga de trabajo de cálculo con recursos ya creados y cargados, la grabación utiliza este orden:" -concepts.shaders.binding.guidance: Este fragmento asume un {commandBuffer} de grabación, una {computePipeline}, un {constantBuffer} cargado con uso {bufferUsagesConstant} y los recuentos de grupos de subprocesos para la carga de trabajo. El desplazamiento 0 enlaza el inicio del búfer. Si varios registros de datos de constantes comparten un búfer, el desplazamiento inicial de cada registro debe cumplir con la alineación de enlace del backend. Ese requisito es independiente del diseño de campos dentro del registro. -concepts.shaders.binding.notes: "{resourceHandle} almacena dos campos de 32 bits, pero su interpretación pertenece al backend. No lo trate como un índice de descriptor universal, dirección o valor que se pueda transferir entre contextos. Un identificador no crea un recurso, no añade un uso faltante ni realiza sincronización." -concepts.shaders.binding.reference: Conserve referencias al recurso y a cualquier vista utilizada para obtener su identificador, y libérelos solo después de que se complete el último uso del sombreador. Al reemplazar una textura o vista, actualice las constantes que contengan su identificador anterior. {link} explica esa relación de tiempo de vida. -concepts.shaders.binding.reference.link: Administración de recursos -concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: Leer elementos estructurados del tipo de sombreador {t}. -concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: Leer o escribir elementos estructurados del tipo de sombreador {t}. -concepts.shaders.binding.table.headings.access: Acceso previsto +concepts.resources.transfers.table.textureTransfers.transfer: "Envía la copia y las transiciones de textura a la cola gráfica y espera a que terminen. El subrecurso seleccionado queda en la disposición final solicitada." +concepts.resources.transfers.title: "Transferencias inmediatas y grabadas" +concepts.resources.usages.description: "{bufferUsages} y {textureUsages} son enumeraciones de indicadores que declaran los usos de un recurso. Se asignan a {bufferDescUsages} y {textureDescUsages}, respectivamente. Para varios usos, se combinan los miembros necesarios mediante {value}." +concepts.resources.usages.title: "Usos de recursos" +concepts.resources.views.description: "Una {bufferView} describe una región de un búfer y cómo se interpretan sus datos. Una {textureView} selecciona un intervalo de subrecursos y un tipo y formato de textura compatibles. Ambas se refieren al almacenamiento existente, con los usos declarados al crearlo. Los intervalos de las vistas describen el acceso, pero no garantizan una comprobación de límites uniforme en los sombreadores de todos los backends." +concepts.resources.views.details: "El identificador del propio recurso proporciona su vista predeterminada. Cree otra vista para seleccionar una región o una interpretación compatible diferente. Mantenga vivos tanto la vista como el recurso que la respalda hasta que la GPU termine de utilizarlos; un identificador no conserva ninguno de los dos objetos. Si sustituye alguno, actualice las constantes que contengan el {link} anterior." +concepts.resources.views.details.link: "identificador de recurso" +concepts.resources.views.title: "Vistas y recursos subyacentes" +concepts.shaders.binding.context: "El ejemplo asigna {inputTextureSampledHandle} a {input} y {outputTextureStorageHandle} a {output}. En Slang, el parámetro de tipo de {descriptorHandle} determina cómo se accede al recurso:" +concepts.shaders.binding.description: "{setConstantBuffer} selecciona un búfer existente y el desplazamiento de byte desde el que la canalización actual lee sus constantes. Cargue los parámetros en ese almacenamiento antes de que los utilice el sombreador. Si un trabajo anterior de la GPU todavía lee esos bytes, espere a que termine antes de actualizarlos." +concepts.shaders.binding.details: "Con el búfer de comandos, la canalización de cálculo, el búfer de constantes cargado y el número de grupos de hilos preparados, grabe el despacho en este orden. Seleccione primero la canalización, ya que el enlace del búfer de constantes se aplica a ella:" +concepts.shaders.binding.guidance: "Aquí, {commandBuffer} graba un despacho con {computePipeline} y los parámetros almacenados en {constantBuffer}. El búfer necesita el uso {bufferUsagesConstant}, y el desplazamiento 0 selecciona su comienzo. Si varios registros de constantes comparten un búfer, el desplazamiento inicial de cada registro debe cumplir también la alineación de enlace del backend, con independencia de la disposición de sus campos internos." +concepts.shaders.binding.notes: "{resourceHandle} contiene dos campos de 32 bits cuya interpretación depende del backend. Sus valores solo son válidos en el contexto donde se creó el recurso." +concepts.shaders.binding.reference: "El recurso y su vista deben conservarse hasta el último acceso del sombreador. Sustituir una textura o vista exige actualizar las constantes con el identificador anterior. Las reglas de propiedad se detallan en {link}." +concepts.shaders.binding.reference.link: "Administración de recursos" +concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: "Lectura de elementos estructurados del tipo {t} del sombreador" +concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: "Lectura y escritura de elementos estructurados del tipo {t} del sombreador" +concepts.shaders.binding.table.headings.access: "Acceso previsto" concepts.shaders.binding.table.headings.cHandle: "Identificador de C#" -concepts.shaders.binding.table.headings.slangFieldType: Tipo de campo Slang -concepts.shaders.binding.table.samplerHandle.access: Suministrar estado de muestreo de textura. -concepts.shaders.binding.table.textureSampledHandle.access: Leer una textura. -concepts.shaders.binding.table.textureStorageHandle.access: Leer o escribir una textura de almacenamiento. -concepts.shaders.binding.title: Enlazar el búfer de constantes y los recursos que describe -concepts.shaders.compilation.description: "{zenithCompiler} compila un punto de entrada de Slang con nombre y devuelve un {shaderDesc}. Utilice el {graphicsApi} del contexto para que el resultado se dirija al backend que creará el sombreador: DXIL para DirectX 12, una biblioteca Metal para Metal o SPIR-V para Vulkan." -concepts.shaders.compilation.details: "Por ejemplo, con un {context} existente y el sombreador del triángulo copiado junto al ejecutable:" -concepts.shaders.compilation.guidance: "{vSMain} debe coincidir exactamente con el nombre del punto de entrada en el archivo del sombreador. Mantenga válidos los objetos de sombreador mientras crea la canalización, luego libérelos después de la creación de la canalización, como se muestra en {link}. Realice esta inicialización una vez en lugar de recompilar en cada fotograma." -concepts.shaders.compilation.guidance.link: Primer triángulo -concepts.shaders.compilation.title: Compilar un punto de entrada para el contexto seleccionado -concepts.shaders.description: "Un sombreador recibe datos suministrados por la aplicación. Los atributos de vértice describen vértices individuales; los búferes contienen parámetros o matrices; los identificadores de recursos identifican otros recursos a los que accederá el sombreador. Las declaraciones de C# y las declaraciones de Slang deben coincidir en lo que significan esos valores. Hacer coincidir un nombre de campo no es suficiente: el diseño, el acceso a recursos y el enlace deben coincidir." -concepts.shaders.dispatch.description: "{dispatch} toma el número de grupos de subprocesos. El punto de entrada {numthreads} del ejemplo de cálculo ejecuta 16 × 16 subprocesos por grupo. Divida las dimensiones de la imagen entre 16 y redondee hacia arriba para encontrar los recuentos de grupos. Por ejemplo, una imagen de 17 × 19 necesita 2 × 2 grupos. El sombreador comprueba sus coordenadas de píxeles con las dimensiones de la imagen porque los últimos grupos pueden contener subprocesos fuera de la imagen." -concepts.shaders.dispatch.details: El compilador almacena el tamaño de grupo declarado del punto de entrada en {shaderDescThreadGroupSize}; no convierte las dimensiones en píxeles suministradas a {dispatch} en recuentos de grupos. Utilice {computeShaderRendererCs} con su sombreador para el ejemplo completo de enlace y dispatch, y {link} antes de que otra pasada consuma la salida. -concepts.shaders.dispatch.details.link: Sincronización -concepts.shaders.dispatch.title: Despachar grupos de subprocesos, no píxeles -concepts.shaders.layout.context: "Las {link} hacen explícitos sus desplazamientos. Esta declaración necesita {systemRuntimeInteropServices} y {zenithNET} en el ámbito:" +concepts.shaders.binding.table.headings.slangFieldType: "Tipo de campo Slang" +concepts.shaders.binding.table.samplerHandle.access: "Estado de muestreo de texturas" +concepts.shaders.binding.table.textureSampledHandle.access: "Lectura de texturas" +concepts.shaders.binding.table.textureStorageHandle.access: "Lectura y escritura de texturas de almacenamiento" +concepts.shaders.binding.title: "Constantes e identificadores de recursos" +concepts.shaders.compilation.description: "{zenithCompiler} compila un punto de entrada Slang en un {shaderDesc}. {graphicsApi} selecciona DXIL para DirectX 12, una biblioteca Metal para Metal o SPIR-V para Vulkan." +concepts.shaders.compilation.details: "Con un contexto gráfico ya creado y llamado {context}, compile el sombreador del triángulo a partir de la copia situada junto al ejecutable:" +concepts.shaders.compilation.guidance: "El nombre del punto de entrada {vSMain} debe coincidir con la declaración del archivo de sombreadores. Compile los sombreadores y cree las canalizaciones durante la inicialización; después, reutilice las canalizaciones al renderizar. Una vez creadas, los objetos sombreador se pueden liberar, como muestra {link}." +concepts.shaders.compilation.guidance.link: "Primer triángulo" +concepts.shaders.compilation.title: "Compilación de sombreadores" +concepts.shaders.description: "Las declaraciones de C# y Slang deben coincidir en la ubicación de cada valor y en la forma de acceder a él desde el sombreador. Las disposiciones de entrada describen los atributos de los vértices; las declaraciones de búferes del sombreador describen parámetros y arrays; los identificadores señalan los recursos que utiliza el sombreador." +concepts.shaders.dispatch.description: "{dispatch} indica cuántos grupos de hilos se ejecutan. El ejemplo de cálculo declara {numthreads}, por lo que cada grupo contiene 16 × 16 hilos. Para cubrir una imagen, divida el ancho y el alto entre 16 y redondee cada resultado hacia arriba: una imagen de 17 × 19 necesita 2 × 2 grupos. El sombreador comprueba las coordenadas de cada hilo y omite los que quedan fuera de la imagen." +concepts.shaders.dispatch.details: "El tamaño de grupo declarado está disponible en {shaderDescThreadGroupSize} y permite calcular los grupos que se pasan a {dispatch}. {computeShaderRendererCs} muestra el cálculo completo. Después del despacho, el acceso a la imagen resultante debe seguir los requisitos descritos en {link}." +concepts.shaders.dispatch.details.link: "Sincronización" +concepts.shaders.dispatch.title: "Grupos de hilos" +concepts.shaders.layout.context: "Las {link} muestran esta organización con las dimensiones de una imagen y dos identificadores de textura. Los desplazamientos explícitos indican dónde comienza cada campo. La declaración utiliza {systemRuntimeInteropServices} y {zenithNET}:" concepts.shaders.layout.context.link: "constantes de C# del ejemplo de cálculo" -concepts.shaders.layout.description: "Para la entrada de vértices, el {inputLayout} de la canalización describe formatos, desplazamientos, stride y semánticas. La posición {float3} del triángulo seguida de un color {float4} ocupa 28 bytes, con el color en el byte 12. {inputLayoutAdd} calcula este diseño empaquetado; no inspecciona la estructura de C#. Si los campos de C# contienen relleno, proporcione un diseño coincidente en lugar de asumir que los campos están empaquetados." -concepts.shaders.layout.details: "Los búferes de constantes contienen parámetros de sombreador, mientras que los búferes estructurados contienen matrices de elementos de un tipo declarado. Ambos se leen de acuerdo con sus declaraciones de Slang. No utilizan {inputLayout}. Verifique los desplazamientos de campos y los tamaños de elementos para la representación de sombreador compilada, incluido el relleno. Un tipo de C# no administrado es adecuado para copiarlo como bytes, pero eso por sí solo no demuestra que coincida con un tipo de sombreador. En particular, no aplique el diseño {float3} estrechamente empaquetado de un vértice a cada búfer de sombreador." -concepts.shaders.layout.guidance: Un identificador de recurso es un valor pequeño que hace referencia a un recurso existente. Copiar el identificador en un búfer de constantes no copia el contenido del recurso. +concepts.shaders.layout.description: "Para la entrada de vértices, {inputLayout} describe el formato, el desplazamiento y la semántica de cada atributo, junto con el paso entre vértices. El triángulo coloca una posición {float3} antes de un color {float4}: el color comienza en el desplazamiento de byte 12 y cada vértice ocupa 28 bytes. {inputLayoutAdd} calcula esta disposición compacta a partir de los formatos. Si la estructura de C# contiene relleno, indique desplazamientos y un paso que lo tengan en cuenta." +concepts.shaders.layout.details: "Los búferes de constantes contienen parámetros del sombreador, y los búferes estructurados contienen arrays de elementos tipados. Su disposición sigue las declaraciones de Slang, no {inputLayout}. Ajuste los desplazamientos, tamaños de elemento y relleno de C# a la disposición del sombreador compilado. Un tipo no administrado de C# se puede copiar byte a byte, pero su disposición en memoria no tiene por qué coincidir con la del sombreador; un {float3} empaquetado para un vértice puede necesitar otra alineación en un búfer del sombreador." +concepts.shaders.layout.guidance: "Los parámetros del sombreador pueden incluir identificadores de recursos además de valores ordinarios. Un identificador se refiere a almacenamiento ya existente, por lo que copiarlo a un búfer de constantes no copia el contenido del recurso." concepts.shaders.layout.notes: "La declaración correspondiente en {computeShaderSlang} es:" -concepts.shaders.layout.reference: "Las dimensiones ocupan los primeros ocho bytes, seguidas de dos identificadores de recursos de ocho bytes. El ejemplo de C# reserva 256 bytes en total. Ese tamaño es el tamaño de almacenamiento elegido por el ejemplo, no una regla de que todas las estructuras de Slang o cargas útiles de constantes deban ocupar 256 bytes. Rellenar el tamaño total tampoco corrige un campo en el desplazamiento incorrecto." -concepts.shaders.layout.title: La entrada de vértices y los datos de sombreadores tienen reglas de diseño diferentes -concepts.shaders.matrices.description: El compilador solicita almacenamiento de matrices en orden principal de filas (row-major), que almacena juntos los elementos de cada fila. El {link} coloca tres valores {matrix4x4} en los desplazamientos 0, 64 y 128. Su {detail} utiliza {mulVectorMatrix} en orden de modelo, vista y proyección. -concepts.shaders.matrices.description.detail: sombreador -concepts.shaders.matrices.description.link: renderizador de cubo giratorio -concepts.shaders.matrices.details: El orden de almacenamiento determina cómo ocupan memoria los elementos de la matriz; el orden de multiplicación determina la transformación. Mantenga ambos lados coherentes. Agregar una transposición sin verificar esas dos opciones puede ocultar una falta de coincidencia mientras introduce otra. -concepts.shaders.matrices.title: Mantener coherentes el almacenamiento y la multiplicación de matrices -concepts.shaders.title: Datos de sombreadores y enlace -concepts.synchronization.backends.description: DirectX 12 y Vulkan codifican transiciones de textura con información de layout y acceso. Metal no tiene ninguna operación en la implementación de {transition} de Zenith.NET. Metal agrupa el trabajo grabado en codificadores de renderizado y cálculo. El backend inserta barreras de visibilidad cuando finaliza estos grupos, haciendo que las escrituras anteriores estén disponibles para el trabajo posterior. Las llamadas explícitas a {barrier} manejan dependencias como dispatches de cálculo sucesivos dentro del mismo codificador. -concepts.synchronization.backends.details: Esta distinción es importante al cambiar una carga de trabajo. En el {link}, el dispatch va seguido de una pasada de renderizado gráfico, que también crea un límite de codificador en Metal. Dos dispatches de cálculo dependientes no crean ese límite simplemente cambiando el layout declarado de la textura. Conserve las transiciones requeridas por la API compartida e identifique por separado la dependencia entre los comandos reales de producción y consumo. -concepts.synchronization.backends.details.link: ejemplo de cálculo -concepts.synchronization.backends.title: Una transición no es idéntica en todos los backends -concepts.synchronization.barriers.context: "{barrierStagesAll} es un ámbito más amplio, no un detector automático de dependencias. Seleccione etapas que realmente cubran el trabajo y utilícelas solo en una cola que admita esas operaciones." -concepts.synchronization.barriers.description: "Considere dos dispatches de cálculo: el primero escribe datos de simulación y el segundo lee esos datos para realizar el siguiente paso. Ambos usan búferes de almacenamiento, por lo que no hay un layout de textura que cambiar. Inserte esto entre los dispatches en su búfer de comandos:" -concepts.synchronization.barriers.details: El primer argumento identifica la etapa productora y el segundo la etapa consumidora. La barrera establece la dependencia de ejecución y memoria correspondiente en la GPU. El backend traduce esas etapas a sus reglas de ejecución y acceso a memoria. Esta barrera no cambia el layout de una textura ni espera todo el trabajo en el dispositivo. -concepts.synchronization.barriers.guidance: "La {link} utiliza este patrón entre dispatches dependientes. Coloque la barrera donde se produce la dependencia. Una barrera grabada después del consumidor no puede ordenar ese consumidor después de un productor anterior." -concepts.synchronization.barriers.guidance.link: simulación FluidTank -concepts.synchronization.barriers.title: Ordenar comandos dependientes con una barrera -concepts.synchronization.dependencies.description: Para cada recurso compartido, identifique la operación que accede a él primero, la operación que le sigue y si alguno de los accesos escribe. Leer los mismos datos dos veces no requiere ordenación para proteger su contenido, aunque los cambios de layout o la presentación pueden imponer otros requisitos. Una escritura seguida de una lectura, una lectura seguida de una sobrescritura o dos escrituras pueden requerir una dependencia. -concepts.synchronization.dependencies.details: "Luego elija el mecanismo según dónde se ejecuten esas operaciones:" -concepts.synchronization.dependencies.guidance: Estos mecanismos están relacionados, pero no son intercambiables. Enviar comandos en orden no reemplaza cada dependencia de memoria. Una espera de cola no declara un nuevo layout de textura, y una barrera de comandos no espera en el subproceso de CPU que llama. -concepts.synchronization.dependencies.table.cpuAccess.mechanism: Llamar a {wait} en el valor de finalización correspondiente. -concepts.synchronization.dependencies.table.cpuAccess.situation: La CPU debe esperar antes de acceder a los datos o liberarlos -concepts.synchronization.dependencies.table.crossQueue.mechanism: Pasar su {timelineValue} al {submit} del búfer de comandos consumidor. -concepts.synchronization.dependencies.table.crossQueue.situation: Un envío en otra cola produce los datos -concepts.synchronization.dependencies.table.headings.mechanism: Mecanismo -concepts.synchronization.dependencies.table.headings.situation: Situación -concepts.synchronization.dependencies.table.layoutChange.mechanism: "{commandBufferTransition} con sus layouts anterior y siguiente." -concepts.synchronization.dependencies.table.layoutChange.situation: Un subrecurso de textura cambia cómo se utiliza +concepts.shaders.layout.reference: "Las dos dimensiones ocupan los primeros ocho bytes, seguidas de dos identificadores de ocho bytes cada uno. El ejemplo de C# reserva 256 bytes para el registro completo. El tamaño de otros registros se debe calcular a partir de sus propios campos y requisitos de disposición y alineación." +concepts.shaders.layout.title: "Disposición de los datos" +concepts.shaders.matrices.description: "El compilador almacena las matrices por filas contiguas. El {link} sitúa tres valores {matrix4x4} en los desplazamientos 0, 64 y 128. Su {detail} aplica {mulVectorMatrix} en el orden modelo, vista y proyección." +concepts.shaders.matrices.description.detail: "sombreador" +concepts.shaders.matrices.description.link: "renderizador de cubo giratorio" +concepts.shaders.matrices.details: "El orden de almacenamiento define la disposición de los elementos de la matriz en memoria; el de multiplicación define la transformación. Las convenciones de C# y Slang deben coincidir." +concepts.shaders.matrices.title: "Convenciones matriciales" +concepts.shaders.title: "Datos de sombreadores y enlace" +concepts.synchronization.backends.description: "DirectX 12 y Vulkan codifican las transiciones de textura como cambios de disposición y acceso. En Metal, la implementación de {transition} de Zenith.NET no realiza una operación equivalente. El backend de Metal agrupa los comandos en codificadores de renderizado y cálculo e inserta barreras de visibilidad cuando termina un codificador. Las operaciones dependientes dentro del mismo codificador, como los despachos de cálculo sucesivos, utilizan llamadas explícitas a {barrier}." +concepts.synchronization.backends.details: "En el {link}, iniciar la pasada gráfica termina el codificador de cálculo y hace visible su salida para el trabajo gráfico. Dos despachos de cálculo consecutivos permanecen en el mismo codificador, de modo que necesitan una barrera aunque se grabe una transición de textura entre ellos. Por eso, una secuencia de comandos portable debe contemplar tanto las dependencias de acceso como las disposiciones de textura." +concepts.synchronization.backends.details.link: "ejemplo de cálculo" +concepts.synchronization.backends.title: "Comportamiento de los backends" +concepts.synchronization.barriers.context: "Elija etapas que incluyan los accesos implicados y que admita la cola. {barrierStagesAll} incluye todas las etapas admitidas; seleccione un conjunto más reducido si la dependencia solo afecta a esas etapas." +concepts.synchronization.barriers.description: "Considere dos despachos de cálculo grabados en el mismo búfer de comandos: el primero escribe datos de simulación y el segundo los lee. Coloque una barrera entre ambos para que el segundo vea las escrituras completadas. En un búfer de almacenamiento, esto ordena los accesos sin una transición de disposición de textura:" +concepts.synchronization.barriers.details: "El primer argumento identifica las etapas que producen los datos; el segundo, las que los consumen. Juntos describen el orden de ejecución y la visibilidad de memoria necesarios entre los dos despachos." +concepts.synchronization.barriers.guidance: "La {link} aplica este patrón entre los pasos de simulación. Cada barrera va después del despacho que produce los datos y antes del que los utiliza." +concepts.synchronization.barriers.guidance.link: "simulación FluidTank" +concepts.synchronization.barriers.title: "Barreras de canalización" +concepts.synchronization.dependencies.description: "Para cada recurso, identifique los accesos que afectan a los mismos datos. Si alguno escribe, conserve el orden necesario entre ellos. Dos lecturas no entran en conflicto, aunque siguen vigentes los requisitos de disposición de textura y presentación. Las actualizaciones de la CPU y la liberación de recursos también deben esperar a que la GPU termine de utilizar el almacenamiento afectado." +concepts.synchronization.dependencies.details: "El mecanismo se elige según dónde se ejecutan las operaciones:" +concepts.synchronization.dependencies.guidance: "Una carga de trabajo puede necesitar varios mecanismos. Por ejemplo, una textura producida en otra cola necesita una dependencia entre envíos y la disposición adecuada para su siguiente uso. Ninguna de estas operaciones exige bloquear la CPU, salvo que esta necesite acceder a los datos o liberarlos." +concepts.synchronization.dependencies.table.cpuAccess.mechanism: "Llamar a {wait} en el valor de finalización correspondiente." +concepts.synchronization.dependencies.table.cpuAccess.situation: "El acceso de la CPU o la liberación de recursos depende de la finalización en la GPU" +concepts.synchronization.dependencies.table.crossQueue.mechanism: "Pase el {timelineValue} del productor a {submit} del consumidor." +concepts.synchronization.dependencies.table.crossQueue.situation: "Una cola consume datos producidos en otra" +concepts.synchronization.dependencies.table.headings.mechanism: "Mecanismo" +concepts.synchronization.dependencies.table.headings.situation: "Situación" +concepts.synchronization.dependencies.table.layoutChange.mechanism: "{commandBufferTransition} con sus disposiciones anterior y siguiente." +concepts.synchronization.dependencies.table.layoutChange.situation: "Un subrecurso de textura cambia cómo se utiliza" concepts.synchronization.dependencies.table.pipelineStages.mechanism: "{commandBufferBarrier} con las etapas productora y consumidora." -concepts.synchronization.dependencies.table.pipelineStages.situation: Etapas de GPU dependientes en un flujo de comandos -concepts.synchronization.dependencies.title: Comenzar con el productor y el consumidor -concepts.synchronization.description: Un comando que lee datos escritos por un comando anterior depende de que esas escrituras estén finalizadas y sean visibles para él. El escritor es el productor; el lector es el consumidor. La CPU también necesita un punto de finalización antes de leer, sobrescribir o liberar datos compartidos. Zenith.NET proporciona barreras, transiciones de textura y líneas de tiempo para estas diferentes dependencias. -concepts.synchronization.layouts.context: "{undefined} significa que no es necesario conservar el contenido anterior. Es adecuado para una nueva imagen o un adjunto que se borrará por completo. No es una forma de evitar rastrear el layout de una imagen cuyo contenido se cargará, muestreará o acumulará." -concepts.synchronization.layouts.description: "Los indicadores de uso describen qué roles admite una textura. {textureLayout} describe cómo se accederá a un subrecurso determinado para una operación. Un subrecurso es un nivel mip y una capa de matriz seleccionados. Cambiar su layout prepara ese acceso; no convierte la textura a un formato de píxeles diferente. Por ejemplo, el ejemplo de cálculo escribe una textura de salida en el layout {storage} y luego la muestrea en una pasada gráfica. Entre esos usos graba:" -concepts.synchronization.layouts.details: "Este fragmento supone que {outputTexture} se creó con el uso {sampledStorage} y que el subrecurso seleccionado está en el layout {storage}. {default} selecciona el nivel mip 0 y la capa de matriz 0. La operación no cambia el layout de todos los niveles mip ni de todas las capas de una textura." -concepts.synchronization.layouts.guidance: La aplicación proporciona el layout anterior. {transition} no mantiene un rastreador de layouts visible para la aplicación ni infiere ese valor a partir de comandos anteriores. Rastree el layout dondequiera que un recurso pase entre etapas de renderizado. -concepts.synchronization.layouts.title: Rastrear el layout de cada subrecurso de textura -concepts.synchronization.readback.description: "{isCompleted} solo consulta si la línea de tiempo de la GPU ha alcanzado un valor. No reclama por sí mismo los búferes de comandos ni copia descargas intermedias en el puntero de destino de la aplicación." -concepts.synchronization.readback.details: "{commandBufferDownload} graba primero una copia en el almacenamiento interno de lectura. Al restablecer el búfer de comandos completado para reutilizarlo, la CPU copia los datos al puntero suministrado. Mantenga ese destino válido y la memoria administrada anclada hasta que retorne {wait} para el envío de descarga. Solo entonces lea los datos o libere la memoria. Esperar a un envío posterior de otra cola no sondea la cola que gestiona la descarga." -concepts.synchronization.readback.guidance: "Por eso no basta con sondear {isCompleted} y leer inmediatamente el destino de una descarga asíncrona. En {link} se explican la copia directa y las transferencias mediante almacenamiento provisional." -concepts.synchronization.readback.guidance.link: Administración de recursos -concepts.synchronization.readback.title: La finalización en la GPU y los datos descargados en la CPU son pasos independientes -concepts.synchronization.reuse.description: Para un primer renderizador, una espera inmediata después de cada fotograma es sencilla. Para superponer trabajo, proporcione a los fotogramas pendientes datos mutables separados y conserve el valor de finalización del uso final de cada fotograma. Antes de actualizar un búfer de constantes, reemplazar una textura o liberar una canalización, finalice cada acceso pendiente al recurso afectado. -concepts.synchronization.reuse.details: Al cambiar el tamaño o apagar, detenga los nuevos usos antes de esperar los antiguos. {swapChainResize}, la liberación de recursos y la liberación del contexto no sirven como esperas generales para el trabajo de la aplicación. El triángulo puede cambiar de tamaño de forma segura entre devoluciones de llamada porque cada fotograma anterior ya ha completado su envío. -concepts.synchronization.reuse.guidance: El {swapChainPresent} actual también envía señales y espera en la cola de gráficos después de su operación de presentación. Por lo tanto, quitar la espera de envío explícita del triángulo no establece por sí sola un bucle de presentación superpuesto. Una espera en la cola de gráficos tampoco dice nada sobre el trabajo independiente que aún se está ejecutando en otra cola. -concepts.synchronization.reuse.title: Reutilizar datos solo después de su acceso final -concepts.synchronization.timelines.context: "Antes de que la CPU lea, sobrescriba o libere esos recursos, espere su uso final:" -concepts.synchronization.timelines.description: Una línea de tiempo realiza un seguimiento de la finalización en una cola mediante valores crecientes. {submit} devuelve un {timelineValue} que contiene esa línea de tiempo y el valor asociado con el envío. Los valores de finalización de diferentes líneas de tiempo no son comparables únicamente por sus campos numéricos {value}. -concepts.synchronization.timelines.details: "Supongamos que {producer} y {consumer} son búferes de comandos ya grabados de dos colas del mismo contexto. El productor escribe datos que utiliza el consumidor. Envíelos de esta manera:" -concepts.synchronization.timelines.guidance: Pasar el valor producido hace que la cola consumidora espere por él en la GPU. La CPU no llama a {producedWait} aquí. Mantenga válidos los recursos compartidos hasta que se complete {consumed} y grabe cualquier cambio de layout de textura requerido por el consumidor. -concepts.synchronization.timelines.notes: "{wait} espera ese valor de línea de tiempo y luego comprueba la cola propietaria en busca de envíos completados. Los búferes de comandos terminados se restablecen para su reutilización y sus descargas intermedias se copian en los destinos de CPU suministrados. {queueTimelineSignal} también puede poner en cola un punto de finalización después del trabajo ya enviado a esa cola. Llamar a {signal} no significa que la GPU ya haya alcanzado el punto." -concepts.synchronization.timelines.title: Usar una línea de tiempo para la finalización y transferencias de colas -concepts.synchronization.title: Sincronización -home.actions.reference: Explorar API -home.actions.tutorial: Comenzar con un triángulo -home.entries.description: Un primer fotograma. Un ejemplo enfocado. Una mirada detallada a la API. -home.entries.label: Explorar la documentación -home.entries.reference.action: Explorar la API -home.entries.reference.category: Referencia -home.entries.reference.description: Encuentre los tipos, firmas y miembros que respaldan su aplicación. -home.entries.reference.title: Referencia de la API -home.entries.samples.action: Examinar ejemplos -home.entries.samples.category: Ejemplos -home.entries.samples.description: Explore técnicas enfocadas de renderizado y cálculo a través de su código fuente. -home.entries.samples.title: Ejemplos -home.entries.title: "Empiece a crear." -home.entries.tutorial.action: Iniciar tutorial -home.entries.tutorial.category: Tutorial -home.entries.tutorial.description: Cree una aplicación de renderizado completa, desde la configuración hasta el primer fotograma. -home.entries.tutorial.title: Primer triángulo -home.introduction.accent: "En C#." -home.introduction.description: Cree recursos, grabe comandos y envíe trabajo de gráficos o cálculo a través de una única API de .NET. -home.introduction.title: Cree su propio renderizador. -home.meta.description: "Una API coherente de C# para gráficos y cálculo en DirectX, Metal y Vulkan." -home.scene.description: Estudio de geometría rotatoria. Arrastre o use las teclas de dirección para ajustar la vista. -home.scene.label: Visualización geométrica -home.scene.surface: Superficie -home.scene.wireframe: Estructura alámbrica -home.title: RHI moderno para .NET -learning.concepts.description: Comprenda cómo encajan los comandos, los recursos, los datos de sombreadores y la sincronización antes de combinar pasadas de renderizado. -learning.concepts.execution.description: Grabe trabajo de GPU, envíelo y mantenga vivos sus recursos. -learning.concepts.platforms.description: Conecte una ventana nativa o un control de renderizado de interfaz de usuario. -learning.concepts.resources.description: Elija usos de recursos, ubicación de memoria y vistas. -learning.concepts.shaders.description: "Haga coincidir diseños de C# e identificadores de recursos con Slang." -learning.concepts.synchronization.description: Ordene accesos dependientes y sepa cuándo finaliza el trabajo. -learning.concepts.title: Conceptos básicos -learning.description: Comience con un tutorial completo sobre un triángulo. Luego use los ejemplos enfocados y las guías conceptuales para comprender los recursos, los datos y las dependencias detrás de un renderizador más grande. -learning.entries.samples.action: Examinar ejemplos -learning.entries.samples.description: "Encuentre ejemplos de C# y Slang para geometría, cálculo, consultas de rayos y sombreado de mallas." -learning.entries.tutorial.action: Abrir tutorial -learning.entries.tutorial.description: Cree una aplicación de consola, abra una ventana y dibuje un triángulo. -learning.meta.description: Comience con Zenith.NET y explore su modelo de programación. -learning.title: Aprender -reference.description: Consulte tipos de recursos, firmas de comandos e integraciones de plataforma. -reference.entries.commands.description: Grabe comandos de gráficos, cálculo y transferencia. -reference.entries.commands.label: Grabar trabajo -reference.entries.context.description: Cree recursos de GPU para el backend seleccionado. -reference.entries.context.label: Comience aquí -reference.meta.description: Explore los tipos y miembros en Zenith.NET. -reference.navigation.core: Examinar la API principal. -reference.title: Referencia de la API -samples.computeShader.description: Convierte una imagen a escala de grises con un dispatch de cálculo y muestra la textura resultante. Muestra identificadores de recursos para una textura de entrada muestreada y una textura de salida editable, recuentos de grupos de subprocesos redondeados hacia arriba y una comprobación de límites en el sombreador. Conserve el recurso {assetsTexturesShokoPng} incluido; el renderizador lo procesa una vez y presenta el resultado en los fotogramas subsiguientes. +concepts.synchronization.dependencies.table.pipelineStages.situation: "Etapas de GPU dependientes en un flujo de comandos" +concepts.synchronization.dependencies.title: "Dependencias de acceso" +concepts.synchronization.description: "La sincronización establece el orden de acceso a los datos compartidos y permite que las operaciones posteriores vean los resultados que necesitan. En una dependencia de escritura a lectura, quien escribe es el productor y quien lee es el consumidor. Las barreras y las transiciones coordinan los accesos de la GPU; las líneas de tiempo conectan envíos y permiten que la CPU espere a que termine el trabajo de la GPU." +concepts.synchronization.layouts.context: "Use {undefined} como disposición anterior cuando se pueda descartar el contenido, por ejemplo, en una imagen nueva o en un adjunto que se vaya a borrar por completo. Para conservarlo para una carga, un muestreo o una acumulación, indique la disposición del acceso anterior." +concepts.synchronization.layouts.description: "Los indicadores de uso declaran las funciones permitidas de una textura. {textureLayout} describe cómo se accede a un subrecurso, identificado por un nivel de mip y una capa de array, en un punto concreto de la secuencia de comandos. Cuando cambia ese acceso, grabe una transición. En el ejemplo de cálculo, la textura de salida se escribe en disposición {storage} y después se prepara para muestrearla en una pasada gráfica:" +concepts.synchronization.layouts.details: "{outputTexture} se creó con {sampledStorage}, y el subrecurso seleccionado está en {storage}. {default} elige el nivel mip 0 y la capa 0. Los demás niveles y capas no cambian." +concepts.synchronization.layouts.guidance: "En {transition}, indique la disposición del uso anterior del subrecurso. La aplicación debe mantener actualizado este estado al grabar comandos y pasar texturas entre las etapas de renderizado." +concepts.synchronization.layouts.title: "Disposiciones de textura" +concepts.synchronization.readback.description: "{isCompleted} informa de la finalización en la GPU. Una descarga grabada tiene un paso adicional: copiar el resultado del almacenamiento interno de lectura a la memoria de destino de la aplicación." +concepts.synchronization.readback.details: "{commandBufferDownload} graba la copia de la GPU a ese almacenamiento interno. Una vez terminado el envío, la biblioteca realiza la copia de CPU al recuperar el búfer de comandos completado. Llamar a {wait} sobre el valor de envío de la descarga espera a la GPU y procesa los búferes completados de esa cola, con lo que termina ambos pasos. Mantenga el destino asignado y la memoria administrada anclada hasta que retorne la llamada." +concepts.synchronization.readback.guidance: "Consultar {isCompleted} por sí solo no realiza la copia final de CPU. Esperar en otra cola tampoco recupera los búferes completados de la cola de descarga. {link} describe cuándo las cargas y descargas utilizan acceso directo o almacenamiento temporal de transferencia." +concepts.synchronization.readback.guidance.link: "Administración de recursos" +concepts.synchronization.readback.title: "Finalización de la lectura en CPU" +concepts.synchronization.reuse.description: "El triángulo espera a que termine cada fotograma antes de reutilizar sus datos. Para solapar fotogramas, reserve almacenamiento modificable para cada uno de los que estén en curso y registre cuándo vuelve a estar disponible. Antes de cambiar datos, espere al trabajo de la GPU que todavía acceda a esos bytes; antes de liberar un recurso, espere a todos sus usos pendientes." +concepts.synchronization.reuse.details: "El redimensionamiento y el cierre siguen la misma regla: impedir nuevos usos, esperar a que terminen los existentes y sustituir o liberar los recursos. Respete ese orden antes de llamar a {swapChainResize} o liberar recursos o el contexto. Como el triángulo ya espera en cada fotograma, puede redimensionar entre las llamadas a sus funciones de respuesta." +concepts.synchronization.reuse.guidance: "{swapChainPresent} señala un punto de la cola gráfica y espera a él después de la presentación. Por tanto, el triángulo sigue esperando al presentar aunque se elimine la espera explícita del envío. El trabajo independiente de otras colas necesita su propio seguimiento de finalización." +concepts.synchronization.reuse.title: "Reutilización de recursos" +concepts.synchronization.timelines.context: "Si la CPU necesita leer el resultado, sobrescribir los datos compartidos o liberar los recursos cuando termine el consumidor, espere a ese envío:" +concepts.synchronization.timelines.description: "Una línea de tiempo identifica la finalización con valores crecientes. {submit} devuelve un {timelineValue} con la línea y el valor del envío. Los campos numéricos {value} de líneas distintas no se comparan directamente." +concepts.synchronization.timelines.details: "Sean {producer} y {consumer} búferes grabados en dos colas del mismo contexto, donde el segundo usa los datos del primero. Su envío establece esta dependencia:" +concepts.synchronization.timelines.guidance: "La cola consumidora espera al valor de finalización recibido antes de ejecutar sus comandos. La CPU puede continuar sin llamar a {producedWait}. Conserve los recursos compartidos hasta que se complete {consumed} y grabe las transiciones de textura que necesite el acceso del consumidor." +concepts.synchronization.timelines.notes: "El valor que devuelve {queueTimelineSignal} también permite esperar con {wait} o establecer una dependencia para otra cola. {signal} coloca ese punto de finalización después del trabajo ya enviado; la GPU lo alcanza cuando termina dicho trabajo." +concepts.synchronization.timelines.title: "Líneas de tiempo y dependencias entre colas" +concepts.synchronization.title: "Sincronización" +home.actions.reference: "Explorar API" +home.actions.tutorial: "Comenzar con un triángulo" +home.entries.description: "Tutoriales, ejemplos y referencia de la API" +home.entries.label: "Secciones de la documentación" +home.entries.reference.action: "Explorar la API" +home.entries.reference.category: "Referencia" +home.entries.reference.description: "Consultar tipos, miembros y declaraciones de la API" +home.entries.reference.title: "Referencia de la API" +home.entries.samples.action: "Examinar ejemplos" +home.entries.samples.category: "Ejemplos" +home.entries.samples.description: "Ejemplos ejecutables de técnicas gráficas y de cálculo" +home.entries.samples.title: "Ejemplos" +home.entries.title: "Documentación" +home.entries.tutorial.action: "Iniciar tutorial" +home.entries.tutorial.category: "Tutorial" +home.entries.tutorial.description: "De un proyecto vacío al primer triángulo en pantalla" +home.entries.tutorial.title: "Primer triángulo" +home.introduction.accent: "con .NET" +home.introduction.description: "Zenith.NET ofrece una API común de gráficos y cálculo para DirectX, Metal y Vulkan" +home.introduction.title: "Gráficos multiplataforma{lineBreak}{accent}" +home.meta.description: "Desarrollo gráfico y de cálculo multiplataforma en .NET con una API común para DirectX, Metal y Vulkan" +home.scene.description: "Geometría interactiva en rotación. Arrastre o utilice las flechas para cambiar la vista." +home.scene.label: "Visualización geométrica" +home.scene.surface: "Superficie" +home.scene.wireframe: "Estructura alámbrica" +home.title: "API gráfica para .NET" +learning.concepts.description: "Criterios para elegir usos de recursos, describir datos de sombreadores y coordinar la ejecución en la GPU" +learning.concepts.execution.description: "Grabación, envío y tiempo de vida de los recursos" +learning.concepts.platforms.description: "Presentación nativa y controles de renderizado" +learning.concepts.resources.description: "Usos de recursos, ubicación de memoria y vistas" +learning.concepts.shaders.description: "Convenciones de disposición y enlace entre C# y Slang" +learning.concepts.synchronization.description: "Dependencias, visibilidad y finalización" +learning.concepts.title: "Conceptos básicos" +learning.description: "Empiece por el tutorial del triángulo para crear su primera aplicación. Después, consulte los conceptos de gestión de recursos, datos de sombreadores y sincronización, o elija un ejemplo de la técnica que quiera implementar." +learning.entries.samples.action: "Examinar ejemplos" +learning.entries.samples.description: "Implementaciones C# y Slang de geometría, cálculo, consultas de rayos y sombreado de mallas" +learning.entries.tutorial.action: "Abrir tutorial" +learning.entries.tutorial.description: "Una aplicación de consola que abre una ventana y renderiza un triángulo" +learning.meta.description: "Tutoriales y conceptos del modelo de programación de Zenith.NET" +learning.title: "Aprender" +reference.description: "Referencia de recursos, comandos e integración de plataformas" +reference.entries.commands.description: "Comandos gráficos, de cálculo y de transferencia" +reference.entries.commands.label: "Registrar comandos" +reference.entries.context.description: "Creación de recursos GPU para el backend elegido" +reference.entries.context.label: "Empezar aquí" +reference.meta.description: "Espacios de nombres, tipos y miembros de Zenith.NET" +reference.navigation.core: "Referencia de la API principal" +reference.title: "Referencia de la API" +samples.computeShader.description: "El ejemplo carga la imagen {assetsTexturesShokoPng}, la convierte a escala de grises en un despacho de cálculo y muestra la textura resultante. La conversión se ejecuta una vez; los fotogramas siguientes muestran el mismo resultado. El renderizador ilustra cómo enlazar texturas para muestreo y escritura, redondear hacia arriba el número de grupos de hilos para cubrir la imagen y comprobar sus límites en el sombreador." samples.computeShader.details: "{computeShaderRendererCs} · {computeShaderSlang}" -samples.computeShader.title: Sombreador de cálculo -samples.cube.description: "Agrega dibujo indexado, matrices de modelo, vista y proyección en un búfer de constantes y prueba de profundidad. La textura de profundidad se vuelve a crear al cambiar el tamaño. Úselo al pasar de geometría en espacio de recorte a un objeto transformado; el renderizador utiliza un adjunto de profundidad/plantilla {d32FloatS8UInt}." +samples.computeShader.title: "Sombreador de cálculo" +samples.cube.description: "El cubo añade dibujo indexado, matrices de modelo, vista y proyección en un búfer de constantes y prueba de profundidad. Su textura de profundidad y plantilla {d32FloatS8UInt} se recrea al redimensionar." samples.cube.details: "{spinningCubeRendererCs} · {spinningCubeSlang}" -samples.cube.title: Cubo giratorio -samples.description: "Elija un ejemplo enfocado para la característica que desea estudiar. Cada ejemplo se vincula al renderizador de C# y a su sombreador Slang. Comience con {link} si desea una aplicación completa explicada desde un proyecto vacío." -samples.description.link: Primer triángulo -samples.execution.description: "{link} contiene seis renderizadores independientes en una aplicación de escritorio. Utilice el SDK de .NET 10 y un backend de escritorio compatible, como se describe a continuación. Compile y ejecute la aplicación, luego elija un ejemplo del menú de la consola:" -samples.execution.description.link: ZenithTutorials -samples.execution.details: El host selecciona DirectX 12 en Windows, Metal en macOS y Vulkan en Linux. Utilice un entorno de dispositivo, controlador y compilador de sombreadores compatible con el backend seleccionado. La ruta de ventana de Linux requiere X11 o XWayland. El {link} declara las dependencias de paquetes y copia los recursos de sombreador y textura necesarios en tiempo de ejecución. -samples.execution.details.link: archivo de proyecto -samples.execution.guidance: Los ejemplos comparten código de ventanas y presentación. Puede elegir cualquier ejemplo de forma independiente según la característica que desee estudiar. -samples.execution.title: Ejecutar los ejemplos del tutorial -samples.host.description: "{appCs} crea el contexto, la ventana y la cadena de intercambio. Obtiene un búfer de comandos, llama al renderizador seleccionado, envía el fotograma y lo presenta. {iRendererCs} define los métodos de actualización, renderizado, cambio de tamaño y liberación del renderizador." -samples.host.details: El cálculo y el trazado de rayos producen texturas fuera de pantalla. {texturePresenterCs} y {presentTextureSlang} dibujan esas texturas en la textura de salida del fotograma actual de la ventana. El host sigue siendo el propietario del envío y de la presentación de la cadena de intercambio. -samples.host.title: Host y presentación compartidos -samples.indirectDrawing.description: Dibuja varias copias de un cubo utilizando un búfer de argumentos indirectos indexados y datos por instancia en un búfer estructurado. La CPU suministra los argumentos de dibujo y actualiza las transformaciones. Úselo para comprender el diseño de argumentos indirectos y el acceso de sombreadores a datos de instancia antes de agregar argumentos generados por GPU. +samples.cube.title: "Cubo giratorio" +samples.description: "Cada ejemplo reúne un renderizador C# y su sombreador Slang en torno a una técnica. La configuración completa y la secuencia de renderizado se explican en {link}." +samples.description.link: "Primer triángulo" +samples.execution.description: "Ejecute el proyecto {link} y elija un ejemplo en el menú de la consola." +samples.execution.description.link: "ZenithTutorials" +samples.execution.title: "Ejecución de ejemplos" +samples.host.description: "{appCs} inicializa contexto, ventana y cadena de intercambio. En cada fotograma obtiene un búfer, llama al renderizador, envía los comandos y presenta el resultado. {iRendererCs} define actualización, renderizado, redimensionamiento y liberación." +samples.host.details: "Los renderizadores de cálculo y trazado de rayos producen texturas fuera de pantalla. {texturePresenterCs} y {presentTextureSlang} las dibujan en la textura de salida actual; después, el programa anfitrión compartido envía los comandos y presenta el fotograma." +samples.host.title: "Host y presentación" +samples.indirectDrawing.description: "El dibujo indirecto representa varias instancias de cubo mediante un búfer de argumentos de dibujo indexado y un búfer estructurado con datos por instancia. La CPU proporciona los argumentos y actualiza las transformaciones." samples.indirectDrawing.details: "{indirectDrawingRendererCs} · {indirectDrawingSlang}" -samples.indirectDrawing.title: Dibujo indirecto -samples.meshShading.description: Utiliza un sombreador de tareas para descartar instancias de esferas y pasar sus índices a un sombreador de mallas que emite geometría. El renderizador comprueba {contextCapabilitiesMeshShadingSupported} antes de crear su canalización. Úselo para seguir los identificadores de recursos y los datos de carga útil a través de las etapas de tarea y malla. +samples.indirectDrawing.title: "Dibujo indirecto" +samples.meshShading.description: "Un sombreador de tareas descarta las instancias de esferas no visibles y pasa los índices restantes al sombreador de mallas, que genera la geometría. El renderizador comprueba {contextCapabilitiesMeshShadingSupported} antes de crear la canalización." samples.meshShading.details: "{meshShadingRendererCs} · {meshShadingSlang}" -samples.meshShading.title: Sombreado de mallas -samples.rayTracing.description: Crea estructuras de aceleración de nivel inferior y superior para un suelo y esferas procedimentales, y luego traza consultas de rayos en línea en un sombreador de cálculo. El renderizador comprueba {contextCapabilitiesRayTracingSupported} antes de construir la carga de trabajo. Utilice este ejemplo para entradas de estructuras de aceleración y recorrido de rayos del lado del sombreador. +samples.meshShading.title: "Sombreado de mallas" +samples.rayTracing.description: "El ejemplo construye estructuras de aceleración de nivel inferior y superior para un suelo y esferas procedurales, y realiza consultas de rayos dentro de un sombreador de cálculo. Comprueba {contextCapabilitiesRayTracingSupported} antes de la inicialización." samples.rayTracing.details: "{rayTracingRendererCs} · {rayTracingSlang}" -samples.rayTracing.title: Trazado de rayos -samples.title: Ejemplos -samples.triangle.description: Crea un búfer de vértices y un diseño de entrada coincidente, y luego dibuja tres vértices a través de una canalización de gráficos. Úselo para conectar la creación de recursos con los comandos en una pasada de renderizado. +samples.rayTracing.title: "Trazado de rayos" +samples.title: "Ejemplos" +samples.triangle.description: "El triángulo asocia un búfer de vértices con su disposición de entrada y dibuja tres vértices mediante una canalización gráfica." samples.triangle.details: "{helloTriangleRendererCs} · {helloTriangleSlang} · {link}" -samples.triangle.details.link: Tutorial completo -samples.triangle.title: Hola triángulo -samples.workloads.description: "El {link} del repositorio principal contiene aplicaciones que combinan varias características. Sus proyectos hacen referencia al código fuente de la biblioteca. Desde una copia de Zenith.NET, ejecute el proyecto elegido, por ejemplo:" -samples.workloads.description.link: directorio Experiments -samples.workloads.details: Los experimentos con ventanas utilizan las mismas opciones de host para Windows, macOS y Linux/X11. Para dibujar dentro de Avalonia, WinForms, WPF, WinUI/Uno o MAUI, consulte {link} para obtener información sobre el ciclo de vida de los fotogramas del control y los vínculos de implementación. -samples.workloads.details.link: Integración de plataforma +samples.triangle.details.link: "Tutorial completo" +samples.triangle.title: "Hola triángulo" +samples.workloads.description: "El {link} del repositorio principal contiene aplicaciones de mayor escala que utilizan el código fuente de la biblioteca." +samples.workloads.description.link: "directorio Experiments" +samples.workloads.details: "Las aplicaciones con ventana usan los mismos caminos de Windows, macOS y Linux/X11. {link} describe los controles Avalonia, WinForms, WPF, WinUI/Uno y MAUI, su ciclo de fotogramas y sus implementaciones." +samples.workloads.details.link: "Integración de plataforma" samples.workloads.table.cornellBox.example: "{link}" -samples.workloads.table.cornellBox.example.link: CornellBox -samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: "Trazado de caminos, reducción de ruido, asignación de tonos, aumento de resolución y controles ImGui. Requiere compatibilidad con trazado de rayos y el entorno de compilación de sombreadores para su backend de escritorio." +samples.workloads.table.cornellBox.example.link: "CornellBox" +samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: "Trazado de caminos, reducción de ruido, asignación de tonos, aumento de resolución y controles ImGui. Requiere soporte de trazado de rayos." samples.workloads.table.fluidTank.example: "{link}" -samples.workloads.table.fluidTank.example.link: FluidTank -samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: Simulación de fluidos por cálculo, dependencias entre etapas de simulación y renderizado de superficies multipasada. Requiere su backend de escritorio y el entorno de compilación de sombreadores. -samples.workloads.table.headings.example: Ejemplo -samples.workloads.table.headings.whatItDemonstratesAndRequires: Qué demuestra y qué requiere +samples.workloads.table.fluidTank.example.link: "FluidTank" +samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: "Simulación de fluidos por cálculo, dependencias entre etapas de simulación y renderizado de superficies multipasada." +samples.workloads.table.headings.example: "Ejemplo" +samples.workloads.table.headings.whatItDemonstratesAndRequires: "Técnicas y requisitos" samples.workloads.table.inkCanvas.example: "{link}" -samples.workloads.table.inkCanvas.example.link: InkCanvas -samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: Dibujo con Skia y control de entrada en una ventana nativa. Requiere el backend y la biblioteca nativa de Skia para la plataforma de destino. +samples.workloads.table.inkCanvas.example.link: "InkCanvas" +samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: "Dibujo con Skia y control de entrada en una ventana nativa. Requiere el backend y la biblioteca nativa de Skia para la plataforma de destino." samples.workloads.table.platformDetection.example: "{link}" -samples.workloads.table.platformDetection.example.link: PlatformDetection -samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: Intenta la creación de contexto para cada backend e informa de las funcionalidades del dispositivo. Si la creación del contexto falla, se informa como no compatible; ese resultado también puede indicar la falta de un controlador o una dependencia en tiempo de ejecución. -samples.workloads.title: Explorar cargas de trabajo más amplias -tutorial.context.description: La ventana ahora puede abrirse, pero aún no hemos creado los objetos de GPU que renderizarán en ella. Un {graphicsContext} proporciona acceso al backend gráfico seleccionado y a sus colas de comandos. -tutorial.context.details: "Inserte este bloque {emphasis}:" -tutorial.context.details.emphasis: después de las directivas using, antes de {iWindowWindow} -tutorial.context.guidance: Las ramas seleccionan DirectX 12 en Windows, Metal en macOS y Vulkan en Linux. El código de renderizado que sigue utiliza la API compartida de Zenith.NET. Solicitamos validación durante el desarrollo e imprimimos los mensajes notificados a través de {validationMessage}. Los diagnósticos dependen del backend y de los componentes de validación disponibles en el equipo. -tutorial.context.title: Crear el contexto gráfico -tutorial.description: Cree una aplicación de consola .NET que abra una ventana y dibuje un triángulo con un degradado de color suave. Aprenderá cómo interactúan los datos de vértices, los sombreadores y el estado de la canalización, y luego grabará y enviará los comandos que producen la imagen. -tutorial.details: Siga las secciones en orden. Primero abrirá una ventana vacía, luego mostrará un color de fondo y finalmente dibujará el triángulo. Cada punto de comprobación confirma una parte de la aplicación antes de agregar la siguiente. La inicialización se ejecuta una vez; la devolución de llamada de renderizado graba un nuevo fotograma cada vez que se invoca. +samples.workloads.table.platformDetection.example.link: "PlatformDetection" +samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: "Intenta crear un contexto para cada backend e informa de las capacidades del dispositivo. Si un intento falla, lo muestra como no compatible; la causa puede estar en el dispositivo, el controlador o una dependencia de ejecución ausente." +samples.workloads.title: "Aplicaciones de mayor escala" +tutorial.context.description: "Un {graphicsContext} conecta la aplicación con la GPU mediante un backend y proporciona los métodos para crear los recursos de renderizado." +tutorial.context.details: "Inserte la inicialización del contexto {emphasis}:" +tutorial.context.details.emphasis: "después de las directivas using, antes de {iWindowWindow}" +tutorial.context.guidance: "Cada rama selecciona el backend de la plataforma y solicita la validación. Los mensajes de {validationMessage} aparecen en la consola." +tutorial.context.imports: "Añada las siguientes directivas using al principio de {programCs}:" +tutorial.context.title: "Contexto gráfico" +tutorial.description: "Este tutorial parte de un proyecto de consola .NET vacío para crear una aplicación que abre una ventana y dibuja un triángulo de colores." +tutorial.details: "El tutorial tiene tres puntos de comprobación: una ventana vacía, un fondo de color uniforme y el triángulo de colores. Ejecute la aplicación en cada uno antes de continuar con el siguiente paso." tutorial.draw.context: "Los argumentos para {draw} son:" -tutorial.draw.description: "En la devolución de llamada {windowRender}, reemplace {addTheTriangleDrawCommandsHereLater} por estos tres comandos, entre {beginRenderPass} y {endRenderPass}:" -tutorial.draw.details: "{setPipeline} selecciona los sombreadores y el estado que acabamos de crear. Establézcalo antes de enlazar datos de vértices: el backend utiliza el diseño de entrada de la canalización para interpretar el enlace." -tutorial.draw.guidance: "{setVertexBufferVertexBuffer} enlaza el búfer comenzando en el desplazamiento de bytes 0 a la ranura de entrada 0. Esa ranura corresponde a la única entrada en {inputLayouts}. No vuelve a copiar ni a cargar los datos." -tutorial.draw.notes: Los comandos aún solo están grabados en este punto. Las llamadas a {submitWait} y {present} que ya están al final de la devolución de llamada de renderizado ejecutan el trabajo y muestran su resultado. El borrado sigue siendo necesario porque el triángulo cubre solo una parte de la imagen; el fondo también debe recibir un color definido en cada fotograma. -tutorial.draw.table.firstInstance.meaning: Comenzar la numeración de instancias en cero. -tutorial.draw.table.firstVertex.meaning: Comenzar con el primer vértice en el búfer. -tutorial.draw.table.headings.argument: Argumento -tutorial.draw.table.headings.description: Valor -tutorial.draw.table.headings.meaning: Significado -tutorial.draw.table.instanceCount.meaning: Dibujar una copia del triángulo. -tutorial.draw.table.vertexCount.meaning: Leer tres vértices. -tutorial.draw.title: Dibujar el triángulo dentro de la pasada -tutorial.execution.description: "Compile y ejecute desde el directorio {firstTriangle}:" -tutorial.execution.details: La ventana debería mostrar un triángulo con una esquina superior roja, una esquina inferior derecha verde y una esquina inferior izquierda azul contra un fondo oscuro. El interior debe mostrar un degradado suave entre esos colores. -tutorial.execution.guidance: Cambie el tamaño de la ventana. La devolución de llamada de cambio de tamaño actualiza las dimensiones del búfer de fotogramas y cambia el tamaño de la cadena de intercambio. La pasada de renderizado establece una ventana gráfica que coincide con esa imagen. Debido a que las posiciones de los vértices permanecen en coordenadas normalizadas, el triángulo conserva la misma fracción del ancho y alto de la ventana; cambiar la relación de aspecto puede estirar su forma. Conservar la relación de aspecto de un objeto requiere una directiva de proyección o ventana gráfica, lo cual va más allá de este primer dibujo. -tutorial.execution.title: Ejecutar, cambiar tamaño y cerrar -tutorial.frame.commands.context: Después de {endRenderPass}, la segunda transición prepara la imagen para su presentación. {submit} finaliza la grabación y envía el búfer de comandos; {wait} espera a que la GPU complete ese envío. Luego, {present} solicita la visualización de la imagen renderizada. -tutorial.frame.commands.description: "Una pasada de renderizado agrupa operaciones de dibujo que utilizan los mismos adjuntos. Aquí, el adjunto de color es la textura de salida de la cadena de intercambio, la imagen que recibe nuestro dibujo. {colorAttachmentClear} crea una descripción que indica a la pasada que borre al color RGBA indicado y conserve el resultado cuando termine la pasada. {beginRenderPass} graba esas instrucciones; la GPU realiza el borrado después de que se envían los comandos." -tutorial.frame.commands.details: "Los corchetes contienen nuestro único adjunto de color. El argumento {null} significa que no hay un adjunto de profundidad/plantilla, que almacenaría valores de profundidad y máscaras de plantilla para pruebas de profundidad y plantilla." -tutorial.frame.commands.guidance: "{beginRenderPass} establece una ventana gráfica (viewport) y un recorte (scissor) que cubren el adjunto. La ventana gráfica asigna las coordenadas renderizadas a píxeles, y el recorte limita qué píxeles se pueden escribir. Estos valores predeterminados cubren toda la textura de salida, que es lo que necesita este triángulo." -tutorial.frame.commands.title: Borrar, enviar y presentar -tutorial.frame.description: Primero llene la imagen con un único color de fondo. Esta operación se denomina borrado (clear). Si ese color aparece en la ventana, la superficie, el envío de comandos y la ruta de presentación están funcionando juntos. Este punto de comprobación le permite verificar el bucle de fotogramas antes de agregar geometría y sombreadores. -tutorial.frame.details: "Una devolución de llamada de renderizado es código que Silk.NET llama cuando es hora de dibujar un fotograma. Esta devolución de llamada no necesita el argumento de tiempo transcurrido del evento, por lo que se denomina {value}. Regístrela {emphasis}:" -tutorial.frame.details.emphasis: antes de {windowRun} -tutorial.frame.target.description: "{graphicsQueueCommandBuffer} obtiene un búfer de comandos con la grabación ya iniciada. La grabación describe trabajo para la GPU; no ejecuta ese trabajo de inmediato." -tutorial.frame.target.details: "La primera {transition} prepara la textura de salida para el acceso como adjunto de color. {default} selecciona el nivel mip 0 y la capa de matriz 0. Usamos {undefined} como layout anterior porque borraremos toda la imagen y descartaremos su contenido anterior. Una pasada que deba conservar el contenido existente debe usar su layout anterior real en su lugar." -tutorial.frame.target.guidance: Utilice la textura de salida actual de la cadena de intercambio en cada fotograma. La presentación puede cambiar qué imagen está disponible, por lo que una textura guardada de un fotograma anterior no es un destino de renderizado de ventana permanente. -tutorial.frame.target.title: Preparar la textura de salida -tutorial.frame.title: Mostrar un color de fondo -tutorial.geometry.data.description: Agregue esta matriz {emphasis}. Los siguientes pasos de creación de recursos también pertenecen a antes de esa devolución de llamada, en el orden mostrado. -tutorial.geometry.data.description.emphasis: antes de {windowRender} -tutorial.geometry.data.details: "Cada entrada de la matriz crea un {vertex}. Las dos expresiones {new} internas crean su posición {vector3} y su color {vector4}. Los vértices describen las esquinas superior, inferior derecha e inferior izquierda. El sombreador de vértices suministrará una cuarta coordenada de posición, {w}. Con w igual a 1, x e y describen directamente coordenadas de dispositivo normalizadas: -1 y +1 son los bordes de la imagen y 0 es el centro. Estas coordenadas no dependen de las dimensiones en píxeles de la ventana." -tutorial.geometry.data.guidance: Cada color contiene componentes rojo, verde, azul y alfa. Alfa es 1 en las tres esquinas. Las tres posiciones tienen z = 0, situándolas en el mismo plano. Estas posiciones no necesitan cámara ni matriz de transformación porque ya describen las coordenadas que queremos renderizar. Para este triángulo plano único, también desactivaremos la mezcla y la prueba de profundidad y omitiremos un búfer de profundidad. -tutorial.geometry.data.title: Elegir las esquinas -tutorial.geometry.description: Un vértice es un punto junto con los datos utilizados para dibujarlo. Nuestro triángulo tiene tres vértices, uno para cada esquina. Cada uno contiene una posición y un color. La GPU interpolará los colores calculando valores intermedios a través del triángulo. -tutorial.geometry.format.description: "Agregue esta declaración {emphasis}:" -tutorial.geometry.format.description.emphasis: al final de {programCs}, después de las instrucciones de limpieza -tutorial.geometry.format.details: "{file} limita este tipo a {programCs}, y el constructor inicializa sus campos de posición y color. {layoutKindSequential} mantiene los campos en el orden de declaración. {position} contiene tres flotantes de 32 bits y {color} contiene cuatro. En esta estructura, la posición comienza en el byte 0, el color comienza en el byte 12 y el vértice completo ocupa 28 bytes. Describiremos ese mismo diseño a la canalización de gráficos." -tutorial.geometry.format.title: Definir un vértice -tutorial.geometry.title: Dar a la GPU tres vértices -tutorial.geometry.upload.context: "{fixed} evita que el recolector de elementos no utilizados mueva la matriz mientras se usa su dirección. Para este búfer al que puede escribir la CPU, {upload} mapea la memoria, copia los datos y deshace el mapeo antes de devolver el control. Por tanto, la matriz no necesita seguir anclada después. El búfer debe permanecer vivo durante todo el renderizado, y basta con cargar los datos una vez porque los vértices no cambian." -tutorial.geometry.upload.description: "La matriz administrada son datos de CPU. Un {buffer} proporciona a la GPU almacenamiento desde el que puede leer los vértices. Después de la matriz, agregue:" -tutorial.geometry.upload.details: "El tamaño total es {sizeofVertexVerticesLength}: 28 bytes por vértice, tres vértices, 84 bytes en total. {bufferUsagesVertex} permite el acceso de entrada de vértices. {cpuWriteOnly} permite a la CPU inicializar este pequeño búfer directamente. El stride del descriptor registra el tamaño del elemento; el diseño de entrada que crearemos a continuación indicará a la captura de vértices cómo leer los atributos individuales." -tutorial.geometry.upload.guidance: Crear un búfer no lo rellena. {upload} copia la matriz en esa asignación comenzando en el desplazamiento de byte de destino 0. Su descripción de origen proporciona un puntero y el número de bytes que se van a copiar. -tutorial.geometry.upload.notes: Agregue {vertexBufferDispose} inmediatamente antes de {swapChainDispose} en la limpieza al final de {programCs}. Para geometrías estáticas más grandes, {link} explica cuándo elegir almacenamiento exclusivo de GPU y transferencias de carga en su lugar. -tutorial.geometry.upload.notes.link: Administración de recursos -tutorial.geometry.upload.title: Asignar un búfer y cargar la matriz -tutorial.input.description: "Los bytes de vértices y los sombreadores están listos. A continuación, describa cómo debe leer la GPU cada vértice. Un atributo es un valor único, como posición o color. El diseño de entrada proporciona a cada atributo un formato y un desplazamiento de bytes; el stride proporciona la distancia en bytes de un vértice al siguiente. Agregue este bloque de inicialización después de la creación del sombreador:" -tutorial.input.details: "{inputLayoutAdd} agrega un elemento en el stride actual y aumenta ese stride en el tamaño del elemento. No inspecciona la estructura de C#. Aquí produce la siguiente concordancia entre la memoria de la CPU y las entradas del sombreador:" -tutorial.input.guidance: "Cambiar el orden de los campos de C# o el relleno sin actualizar esta descripción haría que la GPU leyera los bytes incorrectos. El {semanticIndex} predeterminado es cero, coincidiendo con {pOSITION0} y {cOLOR0}. Ambos elementos pertenecen al mismo búfer, por lo que la canalización contendrá un diseño de entrada y enlazaremos ese búfer a la ranura 0." -tutorial.input.table.headings.byteOffset: Desplazamiento de bytes +tutorial.draw.description: "En {windowRender}, sustituya {addTheTriangleDrawCommandsHereLater} por estos comandos entre {beginRenderPass} y {endRenderPass}:" +tutorial.draw.details: "{setPipeline} selecciona sombreadores y estado. Debe preceder al enlace de vértices porque el backend lo interpreta según la disposición de entrada de la canalización." +tutorial.draw.guidance: "{setVertexBufferVertexBuffer} enlaza los datos de vértices ya cargados desde el desplazamiento de byte 0 a la ranura de entrada 0, que corresponde a la única entrada de {inputLayouts}." +tutorial.draw.notes: "Estas llamadas graban los comandos de dibujo. La llamada existente a {submitWait} los envía y espera a que termine la GPU; después, {present} solicita que se muestre la imagen completada. Conserve el borrado al inicio de la pasada para que la zona exterior al triángulo tenga un color de fondo definido." +tutorial.draw.table.firstInstance.meaning: "Comenzar la numeración de instancias en cero." +tutorial.draw.table.firstVertex.meaning: "Comenzar con el primer vértice en el búfer." +tutorial.draw.table.headings.argument: "Argumento" +tutorial.draw.table.headings.description: "Valor" +tutorial.draw.table.headings.meaning: "Significado" +tutorial.draw.table.instanceCount.meaning: "Dibujar una copia del triángulo." +tutorial.draw.table.vertexCount.meaning: "Leer tres vértices." +tutorial.draw.title: "Comandos de dibujo" +tutorial.execution.description: "Compile y ejecute el proyecto {firstTriangle}." +tutorial.execution.details: "Debería aparecer un triángulo sobre un fondo oscuro, rojo arriba, verde abajo a la derecha y azul abajo a la izquierda. La interpolación de los colores de los vértices forma un degradado suave en el interior." +tutorial.execution.guidance: "Al redimensionar, cambian las dimensiones de la imagen en píxeles, pero las coordenadas de los vértices permanecen iguales. El área de visualización adapta esas coordenadas al nuevo ancho y alto, por lo que el triángulo se deforma si cambia la relación de aspecto de la ventana." +tutorial.execution.title: "Ejecución de la aplicación" +tutorial.frame.commands.context: "Después de {endRenderPass}, la segunda transición prepara la textura de salida para su presentación. {submit} termina la grabación y envía el búfer de comandos; {wait} bloquea el hilo hasta que termina ese envío. A continuación, {present} solicita que se muestre la imagen renderizada." +tutorial.frame.commands.description: "Una pasada de renderizado agrupa las operaciones de dibujo que escriben en los mismos adjuntos. En esta pasada, la textura de salida de la cadena de intercambio recibe el color. {colorAttachmentClear} indica cómo inicializar ese adjunto con un color RGBA y conservar su contenido al terminar la pasada. {beginRenderPass} graba el inicio de la pasada con estos ajustes." +tutorial.frame.commands.details: "La colección contiene un adjunto de color. {null} indica que la pasada no tiene adjunto de profundidad y plantilla." +tutorial.frame.commands.guidance: "{beginRenderPass} configura el área de visualización y el rectángulo de recorte para cubrir todo el adjunto. El área de visualización transforma las coordenadas de renderizado en posiciones de píxeles; el rectángulo de recorte limita dónde se puede escribir." +tutorial.frame.commands.title: "Borrado, envío y presentación" +tutorial.frame.description: "Comience por rellenar la ventana con un color de fondo. Esta operación se llama borrado. Cuando el fondo aparece, la superficie, el envío y la presentación ya funcionan juntos y se pueden añadir los vértices y los sombreadores del triángulo." +tutorial.frame.details: "Silk.NET invoca el callback cuando corresponde producir un fotograma. El argumento de tiempo transcurrido no se usa y se denomina {value}. Registre el callback {emphasis}:" +tutorial.frame.details.emphasis: "antes de {windowRun}" +tutorial.frame.target.description: "{graphicsQueueCommandBuffer} devuelve un búfer listo para grabar. La grabación describe trabajo GPU; la ejecución comienza después del envío." +tutorial.frame.target.details: "La disposición de una textura describe el acceso que necesita una operación. La primera llamada a {transition} prepara la textura de salida para usarla como adjunto de color. Aquí, {default} selecciona el nivel de mip 0 y la capa 0 del array, es decir, la imagen base de la textura. Como esta pasada borra toda la imagen, {undefined} permite descartar su contenido anterior." +tutorial.frame.target.guidance: "Obtenga la textura de salida en cada fotograma, ya que la presentación puede seleccionar una imagen distinta." +tutorial.frame.target.title: "Preparación de la salida" +tutorial.frame.title: "Primer fotograma" +tutorial.geometry.data.description: "Añada el array de vértices {emphasis}. Mantenga también las siguientes inicializaciones de recursos antes de este callback, en el orden indicado." +tutorial.geometry.data.description.emphasis: "antes de {windowRender}" +tutorial.geometry.data.details: "Cada entrada construye un {vertex}; las dos expresiones {new} internas aportan posición {vector3} y color {vector4}. Las posiciones forman los vértices superior, inferior derecho e inferior izquierdo. El sombreador añade {w} como cuarta coordenada. Con w = 1, x e y son coordenadas normalizadas del dispositivo: -1 y +1 delimitan la imagen y 0 marca el centro, independientemente de los píxeles." +tutorial.geometry.data.guidance: "Cada color tiene componentes rojo, verde, azul y alfa, con alfa igual a 1. Los tres vértices tienen z = 0 y están en el mismo plano." +tutorial.geometry.data.title: "Posiciones y colores" +tutorial.geometry.description: "Cada uno de los tres vértices tiene una posición y un color. La GPU determina la forma del triángulo a partir de las posiciones e interpola los colores por su superficie." +tutorial.geometry.format.description: "Añada la declaración del vértice {emphasis}:" +tutorial.geometry.format.description.emphasis: "al final de {programCs}, después de las instrucciones de limpieza" +tutorial.geometry.format.details: "{file} limita el tipo a {programCs}, y {layoutKindSequential} mantiene los campos en su orden de declaración. {position} contiene tres valores de coma flotante de 32 bits y comienza en el desplazamiento de byte 0; {color} contiene cuatro y comienza en el desplazamiento de byte 12. Cada vértice ocupa, por tanto, 28 bytes. La disposición de entrada describirá esta organización para que la GPU lea los campos correctamente." +tutorial.geometry.format.imports: "Añada estas directivas using al principio de {programCs} para utilizar los tipos vectoriales y el atributo que define la disposición de la estructura:" +tutorial.geometry.format.title: "Representación del vértice" +tutorial.geometry.title: "Datos de vértices" +tutorial.geometry.upload.context: "{fixed} impide que el recolector de basura mueva el array mientras se usa su dirección. En este búfer escribible por la CPU, {upload} mapea la memoria, copia los bytes y deshace el mapeo antes de retornar. El array solo debe permanecer anclado durante la llamada. Cargue los vértices una vez durante la inicialización y conserve el búfer hasta que termine el renderizado." +tutorial.geometry.upload.description: "Guarde los vértices en un {buffer} para que la GPU pueda leerlos al dibujar. Añada la asignación y la carga de datos justo después del array:" +tutorial.geometry.upload.details: "{sizeofVertexVerticesLength} equivale a tres vértices de 28 bytes, 84 bytes en total. {bufferUsagesVertex} declara acceso de entrada, y {cpuWriteOnly} permite inicialización directa por CPU. El paso del descriptor registra el tamaño del elemento; la disposición posterior define cada atributo." +tutorial.geometry.upload.guidance: "La asignación no inicializa el contenido del búfer. {upload} copia el array al desplazamiento de destino 0 utilizando el puntero de origen y el número de bytes de la descripción de datos." +tutorial.geometry.upload.imports: "En {programCs}, añada {bufferAlias} a las directivas using para distinguir el tipo de búfer de Zenith.NET de {systemBuffer}." +tutorial.geometry.upload.notes: "Coloque {vertexBufferDispose} justo antes de {swapChainDispose} al final de {programCs}. {link} trata el almacenamiento exclusivo de GPU y las cargas para geometrías mayores." +tutorial.geometry.upload.notes.link: "Administración de recursos" +tutorial.geometry.upload.title: "Asignación y carga del búfer" +tutorial.input.description: "La GPU necesita saber dónde se guardan los atributos de cada vértice, como la posición y el color. La disposición de entrada indica su formato y desplazamiento, además del paso: la distancia en bytes hasta el siguiente vértice. Añada este código después de crear los sombreadores:" +tutorial.input.details: "{inputLayoutAdd} sitúa cada atributo a continuación del anterior y suma su tamaño al paso entre vértices. Calcula los desplazamientos a partir de los formatos indicados, sin inspeccionar la estructura de C#. Para estos dos campos, la disposición resultante es:" +tutorial.input.guidance: "El valor predeterminado de {semanticIndex} es cero, que corresponde a {pOSITION0} y {cOLOR0} en el sombreador. La posición y el color se almacenan juntos en un búfer de vértices, por lo que la canalización utiliza una sola disposición de entrada en la ranura 0. Si cambia el orden de los campos o el relleno de la estructura de C#, ajuste también esta disposición." +tutorial.input.table.headings.byteOffset: "Desplazamiento de bytes" tutorial.input.table.headings.cField: "Campo de C#" -tutorial.input.table.headings.format: Formato -tutorial.input.table.headings.shaderInput: Entrada del sombreador -tutorial.input.table.nextVertex.cField: Siguiente vértice -tutorial.input.table.nextVertex.format: "Stride total: 28 bytes" -tutorial.input.table.nextVertex.shaderInput: Siguiente registro de entrada +tutorial.input.table.headings.format: "Formato" +tutorial.input.table.headings.shaderInput: "Entrada del sombreador" +tutorial.input.table.nextVertex.cField: "Siguiente vértice" +tutorial.input.table.nextVertex.format: "Paso total: 28 bytes" +tutorial.input.table.nextVertex.shaderInput: "Siguiente registro de entrada" tutorial.input.table.vertexColor.format: "{float4} (16 bytes)" tutorial.input.table.vertexPosition.format: "{float3} (12 bytes)" -tutorial.input.title: Describir el diseño de entrada de vértices -tutorial.lifecycle.description: "La aplicación terminada repite esta secuencia:" -tutorial.lifecycle.details: "Cerrar la ventana regresa de {run}. Cada fotograma renderizado ya ha esperado a que se complete su trabajo de GPU, por lo que ahora podemos liberar los recursos que utilizó. La limpieza después de {windowRun} debe ser:" -tutorial.lifecycle.guidance: "Libere la cadena de intercambio antes que su ventana nativa, y el contexto después de todos sus recursos. La cola posee y recicla los búferes de comandos enviados; la cadena de intercambio posee su textura de salida. Esos búferes de comandos y esa textura no necesitan una llamada {dispose} independiente en esta aplicación." -tutorial.lifecycle.title: Seguir el ciclo de vida de un fotograma -tutorial.pipeline.behavior: "Después del diseño de entrada, agregue:" -tutorial.pipeline.context: "{cullNone} rellena el triángulo sin descartarlo por la orientación de sus caras. El orden de los vértices determina esa orientación; desactivar el descarte evita que dicho orden oculte nuestro primer triángulo." -tutorial.pipeline.description: "Ahora tenemos datos de vértices, un diseño de entrada y dos sombreadores. La {graphicsPipeline} los conecta y especifica cómo la GPU ensambla los vértices en primitivas y escribe el resultado en un adjunto." -tutorial.pipeline.details: "Una canalización combina etapas de sombreador programables con configuraciones de función fija, que controlan operaciones de GPU como ensamblado de triángulos, descarte de caras y mezcla. Para este triángulo, elija estas configuraciones:" -tutorial.pipeline.guidance: El formato de color proviene de {swapChainDescFormat}. Debe coincidir con la imagen utilizada por la pasada de renderizado. {count1} significa una muestra por píxel. -tutorial.pipeline.item: "{triangleList} ensambla cada grupo consecutivo de tres vértices en un triángulo. Suministraremos tres vértices y dibujaremos una vez, por lo que no se necesita un búfer de índices." -tutorial.pipeline.notes: "{depthNone} deshabilita la prueba y la escritura de profundidad, coincidiendo con la pasada sin adjunto de profundidad." -tutorial.pipeline.reference: "{opaque} deshabilita la mezcla, por lo que el color del sombreador de fragmentos reemplaza el fondo dentro del triángulo." -tutorial.pipeline.title: Conectar los sombreadores y el diseño de vértices -tutorial.pipeline.usage: Los objetos de sombreador se pueden liberar después de crear la canalización, como se hace en el renderizador de ejemplo. Mantenga viva la canalización en sí para cada fotograma que dibuje con ella. Agregue {pipelineDispose} antes de {vertexBufferDispose} en la limpieza. La creación de la canalización es el paso final de inicialización antes de la devolución de llamada de renderizado. -tutorial.pipeline.validation: "La descripción de la canalización declara la configuración del adjunto; no crea otra imagen. {inputLayouts} tiene una entrada porque la posición y el color se almacenan juntos en un solo búfer." -tutorial.presentation.title: Conectar la GPU a la ventana -tutorial.project.context: Habilite {emphasis} ({allowUnsafeBlocks}) en la configuración de compilación del proyecto. Lo utilizaremos para pasar datos de vértices a la GPU y para las llamadas nativas del asistente de ventanas. -tutorial.project.context.emphasis: Permitir código no seguro -tutorial.project.description: "Cree el proyecto y entre en su directorio:" -tutorial.project.details: "Instale los paquetes:" -tutorial.project.guidance: "{zenithNET} proporciona la API de renderizado compartida. Los tres paquetes de backend permiten que el mismo programa seleccione la implementación para su plataforma. {zenithNETCompiler} compila sombreadores Slang, los pequeños programas de GPU que escribiremos más adelante, para esa implementación. Silk.NET suministra la ventana y el bucle de eventos." -tutorial.project.title: Crear un proyecto de consola -tutorial.requirements.context: Puede seguir esta página desde un proyecto vacío. El {link} y su {detail} están disponibles como referencia para las API de renderizado y ventanas utilizadas aquí. -tutorial.requirements.context.detail: host compartido -tutorial.requirements.context.link: ejemplo Hola triángulo -tutorial.requirements.description: "Necesita el {emphasis}, un editor de código o IDE y un equipo de escritorio con una GPU y un controlador compatibles con un backend de Zenith.NET. Basta con tener conocimientos básicos de C#; los conceptos gráficos se introducen a medida que se utilizan. Este es un proyecto de consola {net10} ordinario. Un backend traduce las operaciones de Zenith.NET en llamadas a una API gráfica, como DirectX 12, Metal o Vulkan. La aplicación elige una al inicio:" -tutorial.requirements.description.emphasis: SDK de .NET 10 -tutorial.requirements.details: Linux necesita una sesión de ventanas compatible con X11 para la ruta de ventanas utilizada aquí. Las funciones opcionales de trazado de rayos y sombreado de mallas no son necesarias para este triángulo. -tutorial.requirements.guidance: Zenith.NET renderiza en una superficie suministrada por la aplicación. Silk.NET.Windowing creará la ventana de escritorio y procesará sus eventos. En macOS, el destino de presentación es una capa Metal ({cAMetalLayerCs}); el asistente de ventana del tutorial conecta esa capa por nosotros. -tutorial.requirements.table.headings.graphicsBackend: Backend gráfico -tutorial.requirements.table.headings.platform: Plataforma -tutorial.requirements.table.headings.windowSurface: Superficie de ventana -tutorial.requirements.table.linux.graphicsBackend: Vulkan 1.4 -tutorial.requirements.table.linux.platform: Linux -tutorial.requirements.table.linux.windowSurface: Ventana y pantalla X11; XWayland también es adecuado -tutorial.requirements.table.macOS.graphicsBackend: Metal 4 -tutorial.requirements.table.macOS.platform: macOS -tutorial.requirements.table.macOS.windowSurface: Capa Metal conectada a la ventana -tutorial.requirements.table.windows.graphicsBackend: DirectX 12 -tutorial.requirements.table.windows.platform: Windows -tutorial.requirements.table.windows.windowSurface: Identificador de ventana Win32 -tutorial.requirements.title: Antes de comenzar -tutorial.resize.context: "Ejecute {dotnetRun} nuevamente. La ventana ahora debería tener un fondo oscuro uniforme que continúe llenándola después de cambiar el tamaño. Conserve esta devolución de llamada: el triángulo se dibujará dentro de su pasada de renderizado existente." -tutorial.resize.description: "Las imágenes de la cadena de intercambio deben seguir las dimensiones del búfer de fotogramas. Utilice {framebufferResize} para responder a los cambios en el tamaño de píxeles, incluidos los cambios causados por la escala de pantalla. Después de la devolución de llamada de renderizado, aún antes de {windowRun}, agregue:" -tutorial.resize.details: "Silk.NET distingue los cambios de tamaño de ventana de los {link}. Necesitamos estos últimos porque la cadena de intercambio almacena píxeles. Una ventana minimizada puede tener un búfer de fotogramas de tamaño cero. En ese caso, ambas devoluciones de llamada omiten su trabajo de GPU. Después de cambiar el tamaño, la pasada de renderizado utilizará las nuevas dimensiones del adjunto para su ventana gráfica y recorte." -tutorial.resize.details.link: cambios de tamaño del búfer de fotogramas -tutorial.resize.guidance: Esperamos después de cada envío, por lo que ningún fotograma anterior sigue utilizando las imágenes cuando el controlador de cambio de tamaño las reemplaza. La implementación actual de {present} también espera en la cola de gráficos. Este bucle simple mantiene completo el trabajo de un fotograma antes de que comience el siguiente; {link} cubre una programación más avanzada. -tutorial.resize.guidance.link: Sincronización -tutorial.resize.title: Responder al cambio de tamaño -tutorial.shaders.compilation.context: La compilación se realiza una vez durante la inicialización. {appContextBaseDirectory} localiza el sombreador copiado junto al ejecutable, independientemente del directorio de trabajo actual. Estos sombreadores solo consumen entrada de vértices, por lo que aún no hay búferes de constantes, texturas ni identificadores de recursos para enlazar. -tutorial.shaders.compilation.description: En las propiedades del archivo para {triangleSlang}, establezca {emphasis} en {detail}. Esto hace que el sombreador esté disponible junto al ejecutable. -tutorial.shaders.compilation.description.detail: Copiar si es posterior -tutorial.shaders.compilation.description.emphasis: Copiar en el directorio de salida -tutorial.shaders.compilation.details: "Regrese a {programCs}. Después de la carga de vértices, agregue estas instrucciones de inicialización antes de la devolución de llamada de renderizado:" -tutorial.shaders.compilation.guidance: "{zenithCompiler} devuelve una descripción de sombreador que contiene código para la API gráfica solicitada. {createShader} crea el objeto de backend correspondiente. Tanto la API gráfica como los nombres de los puntos de entrada son importantes: use {contextGraphicsApi} y escriba {vSMain} y {fSMain} exactamente como en el archivo Slang." -tutorial.shaders.compilation.title: Compilar para el backend seleccionado -tutorial.shaders.context: "{fSInput} conecta la salida del sombreador de vértices con la entrada del sombreador de fragmentos. Cuando lo escribe el sombreador de vértices, {sVPOSITION} suministra una posición en espacio de recorte: las cuatro coordenadas que utiliza la GPU para determinar qué queda dentro de la imagen visible. {cOLOR0} transporta el color para interpolar entre vértices. Las dos etapas deben coincidir en su tipo y semántica." -tutorial.shaders.description: Un sombreador es un programa ejecutado por la GPU. Este dibujo necesita un sombreador de vértices para posicionar los vértices y un sombreador de fragmentos para producir los colores dentro del triángulo. Los escribiremos en Slang, un lenguaje de sombreadores, y compilaremos dos puntos de entrada desde el mismo archivo. Un punto de entrada es la función donde comienza a ejecutarse una etapa de sombreador. -tutorial.shaders.details: "Cree {triangleSlang}, comenzando con estas dos estructuras:" -tutorial.shaders.fragment.description: "Agregue el punto de entrada de fragmentos al mismo archivo:" -tutorial.shaders.fragment.details: "La rasterización determina qué ubicaciones de imagen cubre el triángulo. Produce fragmentos (los datos procesados por el sombreador de fragmentos) con los colores de los vértices interpolados en el área cubierta. {fSMain} devuelve este color interpolado a través de {sVTARGET}, que identifica el primer adjunto de color." -tutorial.shaders.fragment.guidance: "La interpolación del color de los vértices es independiente de la mezcla del adjunto. La mezcla combina la salida de un fragmento con el color ya almacenado en el adjunto. Nuestro estado de mezcla opaco desactiva esa combinación, por lo que el color interpolado reemplaza el fondo dentro del triángulo." -tutorial.shaders.fragment.title: Colorear los fragmentos -tutorial.shaders.guidance: "{vSInput} describe lo que recibe el sombreador de vértices desde el búfer de vértices. Las semánticas {pOSITION0} y {cOLOR0} identifican las entradas; los nombres de campos de C# por sí solos no establecen esa asignación." -tutorial.shaders.title: Escribir las dos etapas del sombreador -tutorial.shaders.vertex.description: "Agregue el punto de entrada de vértices a {triangleSlang}:" -tutorial.shaders.vertex.details: La GPU invoca este punto de entrada para cada vértice de entrada. Agrega la coordenada homogénea {w} a la posición y reenvía el color. Después de la etapa de vértices, la posición se divide por w; aquí esa división deja x, y y z sin cambios. Es por eso que las posiciones elegidas anteriormente se pueden entender directamente en coordenadas de dispositivo normalizadas. -tutorial.shaders.vertex.title: Posicionar cada vértice -tutorial.surface.description: "El contexto también necesita saber dónde mostrar su salida. Agregue lo siguiente {emphasis}:" -tutorial.surface.description.emphasis: después de {windowCenter} y antes de {windowRun} -tutorial.surface.details: "{surface} describe un destino de presentación nativo y sus dimensiones en píxeles. El búfer de fotogramas es la imagen de píxeles asociada a la ventana. {framebufferSize} proporciona sus dimensiones en píxeles; las dimensiones lógicas de la ventana pueden diferir cuando la escala de pantalla está activada." -tutorial.surface.guidance: La superficie coincide con el backend seleccionado anteriormente. Windows suministra un identificador de ventana, Linux suministra una pantalla y ventana X11, y el asistente de macOS suministra la capa Metal conectada. Esta es la única parte específica de la plataforma para conectar nuestra ventana al renderizado. -tutorial.surface.title: Describir la superficie nativa -tutorial.swapChain.context: "La cadena de intercambio utiliza tanto el contexto como la ventana nativa. Reemplace la línea {windowDispose} al final de {programCs} por este orden de limpieza:" -tutorial.swapChain.description: "Utilice la descripción de la superficie para crear las imágenes que se presentarán. Inmediatamente después del bloque de superficie, agregue:" -tutorial.swapChain.details: La {swapChain} gestiona las imágenes mostradas en la ventana. En cada fotograma, {drawable} nos proporciona la imagen actual como una {texture}, el tipo de API para datos de imagen. Después de dibujar, {present} solicita mostrar el resultado y avanza al siguiente drawable. -tutorial.swapChain.guidance: "{b8G8R8A8UNorm} almacena cuatro canales de color de 8 bits en orden azul, verde, rojo y alfa. {uNorm} significa que los valores enteros de 0 a 255 representan valores de 0 a 1. El sombreador seguirá devolviendo un valor RGBA lógico; este formato determina cómo se almacenan esos canales en la imagen. Más adelante, la canalización de gráficos utilizará {swapChainDescFormat} para coincidir con este adjunto." -tutorial.swapChain.title: Crear la cadena de intercambio -tutorial.title: Primer triángulo -tutorial.troubleshooting.description: "Lea primero cualquier error en la consola y luego use los puntos de comprobación anteriores para identificar la etapa que falló:" -tutorial.troubleshooting.details: Utilice el {link} y el {detail} para comparar los datos de vértices, el diseño de entrada y la operación de dibujo. Ese ejemplo coloca las ventanas y el envío en un host compartido; este tutorial mantiene el flujo de la aplicación en {programCs}. Continúe con {context} para aprender dibujo indexado, transformaciones y pruebas de profundidad. -tutorial.troubleshooting.details.context: Cubo giratorio -tutorial.troubleshooting.details.detail: sombreador Slang -tutorial.troubleshooting.details.link: renderizador de ejemplo -tutorial.troubleshooting.table.backend.check: Compruebe que el backend seleccionado sea compatible con el dispositivo y el controlador de gráficos instalado. -tutorial.troubleshooting.table.backend.symptom: Falla la creación del backend -tutorial.troubleshooting.table.drawing.check: Compruebe el tamaño de carga, el diseño de entrada, la selección de canalización y la ubicación de los comandos de dibujo dentro de la pasada de renderizado. -tutorial.troubleshooting.table.drawing.symptom: Aparece el fondo pero no el triángulo -tutorial.troubleshooting.table.headings.check: Comprobación -tutorial.troubleshooting.table.headings.symptom: Síntoma -tutorial.troubleshooting.table.input.check: Compruebe el stride de 28 bytes y los desplazamientos de posición/color de 0 y 12. -tutorial.troubleshooting.table.input.symptom: Las posiciones o colores de los vértices están dañados -tutorial.troubleshooting.table.shaders.check: Compruebe el archivo {triangleSlang} copiado, la ortografía del punto de entrada y el diagnóstico notificado por el compilador. -tutorial.troubleshooting.table.shaders.symptom: El paso del color de borrado funciona, pero la carga del sombreador falla -tutorial.troubleshooting.table.window.check: Confirme que el proyecto .NET se compila y que el paso de solo ventana se ejecuta en una sesión de escritorio. En Linux, compruebe que X11 o XWayland estén disponibles. -tutorial.troubleshooting.table.window.symptom: No se abre ninguna ventana -tutorial.troubleshooting.title: Comprobar la etapa que falló -tutorial.window.context: "{usingZenithTutorials} importa el espacio de nombres del asistente. Cada archivo de C# usa sus propias directivas using habituales, por lo que la importación de interoperabilidad es necesaria en ambos archivos. El alias {buffer} se refiere al tipo de búfer de Zenith.NET y lo distingue de {systemBuffer}." -tutorial.window.description: Agregue {cocoaHelperCs} al proyecto, conservando su espacio de nombres. Agregue {interopUsing} en la parte superior de ese archivo, antes de su declaración de espacio de nombres. El asistente conecta una capa Metal a la ventana en macOS; las ramas de otras plataformas no lo llaman. -tutorial.window.details: "Reemplace el archivo {programCs} generado por el siguiente código. Utiliza instrucciones de nivel superior, que se ejecutan en orden sin un método {main} explícito. Las secciones posteriores le indicarán dónde agregar código a este mismo archivo:" -tutorial.window.guidance: "{graphicsAPINone} solicita a Silk.NET que cree una ventana sin su propio contexto gráfico. Crearemos ese contexto con Zenith.NET. {initialize} crea la ventana nativa y pone a disposición sus identificadores. Un identificador es proporcionado por el sistema de ventanas. {center} centra la ventana y {run} procesa eventos hasta que se cierra. La ejecución continúa luego hacia {dispose}, que libera la ventana." -tutorial.window.notes: Ejecute {dotnetRun}. Debería abrirse una ventana vacía y responder a mover, cambiar de tamaño y cerrar. Su contenido aún no está definido porque no hemos enviado ningún comando de renderizado. Ciérrela antes de continuar. -tutorial.window.title: Abrir una ventana -ui.action.copy: Copiar -ui.action.navigate: Navegar -ui.action.open: Abrir -ui.action.source: Ver código fuente -ui.api.browse: Examinar espacios de nombres y tipos. -ui.api.clearTypeSearch: Borrar búsqueda de tipos -ui.api.findType: Buscar un tipo -ui.api.loadError: No se pudieron cargar los tipos. Recargue esta página para intentarlo de nuevo. -ui.api.loadingNamespaces: Cargando espacios de nombres… -ui.api.loadingTypes: Cargando tipos… -ui.api.matchingTypes: Tipos coincidentes -ui.api.namespace: Espacio de nombres -ui.api.namespaces: Espacios de nombres -ui.api.noNamespaceTypes: No hay tipos en este espacio de nombres. -ui.api.noTypes: No hay tipos coincidentes. -ui.api.types: Tipos -ui.content.reference: Referencia -ui.content.source: Código fuente -ui.content.tutorial: Tutorial -ui.contents.close: Cerrar contenido -ui.contents.open: Abrir contenido -ui.contents.title: Contenido -ui.footer.caption: RHI moderno para .NET. -ui.footer.label: Pie de página -ui.language.label: Idioma -ui.language.unavailable: No traducido -ui.members.clear: Borrar búsqueda de miembros -ui.members.close: Cerrar buscador de miembros -ui.members.empty: No hay miembros coincidentes. -ui.members.open: Ir al miembro -ui.members.placeholder: Nombre o firma… -ui.members.search: Buscar miembros -ui.members.title: Buscar un miembro -ui.members.undeclared: Este tipo no tiene miembros declarados. -ui.navigation.api: API -ui.navigation.concepts: Conceptos -ui.navigation.home: Inicio -ui.navigation.label: Navegación principal -ui.navigation.toggle: Alternar navegación -ui.outline.title: En esta página -ui.reference.assembly: Ensamblado -ui.reference.classes: Clases -ui.reference.constructors: Constructores +tutorial.input.title: "Disposición de entrada de vértices" +tutorial.lifecycle.description: "Cada fotograma sigue esta secuencia:" +tutorial.lifecycle.details: "Al cerrar la ventana, {run} retorna y la ejecución continúa en el código de limpieza. Como cada fotograma ya ha esperado a que terminen sus comandos, los recursos que utilizaban se pueden liberar. El bloque completo de limpieza después de {windowRun} es:" +tutorial.lifecycle.guidance: "Libere la cadena de intercambio antes de destruir su ventana nativa y el contexto después de sus recursos. La cola recicla los búferes de comandos enviados, y la cadena de intercambio gestiona la textura de salida; ninguno necesita una llamada independiente a {dispose}." +tutorial.lifecycle.title: "Ciclo del fotograma y limpieza" +tutorial.pipeline.behavior: "Tras la disposición de entrada, cree la canalización:" +tutorial.pipeline.context: "{cullNone} desactiva el descarte de caras, de modo que el triángulo se dibuja tanto si sus vértices aparecen en sentido horario como antihorario." +tutorial.pipeline.description: "Una {graphicsPipeline} reúne la disposición de los vértices, los dos sombreadores y los ajustes para ensamblar primitivas y escribir en los adjuntos." +tutorial.pipeline.details: "Los sombreadores procesan vértices y fragmentos. Los demás ajustes de la canalización controlan el ensamblado de primitivas, el descarte de caras, la prueba de profundidad y la mezcla de colores:" +tutorial.pipeline.guidance: "El formato debe coincidir con el adjunto de la pasada, por lo que procede de {swapChainDescFormat}. {count1} especifica una muestra por píxel." +tutorial.pipeline.item: "{triangleList} ensambla cada grupo de tres vértices consecutivos en un triángulo." +tutorial.pipeline.notes: "{depthNone} desactiva pruebas y escrituras de profundidad, de acuerdo con la ausencia de ese adjunto." +tutorial.pipeline.reference: "{opaque} desactiva la mezcla. El color del fragmento sustituye así el fondo dentro del triángulo." +tutorial.pipeline.title: "Canalización gráfica" +tutorial.pipeline.usage: "Los objetos de sombreador pueden liberarse tras crear la canalización. Mantenga la canalización durante el renderizado y añada {pipelineDispose} antes de {vertexBufferDispose} en la limpieza." +tutorial.presentation.title: "Contexto gráfico y presentación" +tutorial.project.context: "Active {emphasis} ({allowUnsafeBlocks}) en la configuración de compilación. Las llamadas nativas de ventana y la carga de vértices necesitan código no seguro." +tutorial.project.context.emphasis: "Permitir código no seguro" +tutorial.project.description: "Cree un proyecto de consola C# llamado {firstTriangle} que tenga como destino .NET 10." +tutorial.project.details: "Añada los siguientes paquetes NuGet al proyecto:" +tutorial.project.guidance: "{zenithNET} aporta la API común y los tres paquetes de backend sus implementaciones. {zenithNETCompiler} compila los sombreadores Slang que se presentan a continuación. Silk.NET crea la ventana y procesa eventos." +tutorial.project.title: "Configuración del proyecto" +tutorial.requirements.context: "El {link} y su {detail} proporcionan las implementaciones de referencia del tutorial." +tutorial.requirements.context.detail: "host compartido" +tutorial.requirements.context.link: "ejemplo Hola triángulo" +tutorial.requirements.description: "Necesita el {emphasis} y conocimientos básicos de C#. La aplicación tiene {net10} como framework de destino. La GPU y el controlador deben admitir el backend elegido para su plataforma:" +tutorial.requirements.description.emphasis: "SDK de .NET 10" +tutorial.requirements.guidance: "Zenith.NET renderiza en una superficie nativa proporcionada por la aplicación. Silk.NET.Windowing crea la ventana y procesa eventos. En macOS se utiliza una capa Metal, representada por {cAMetalLayerCs}, que el código auxiliar conecta a la ventana." +tutorial.requirements.table.headings.graphicsBackend: "Backend gráfico" +tutorial.requirements.table.headings.platform: "Plataforma" +tutorial.requirements.table.linux.graphicsBackend: "Vulkan 1.4" +tutorial.requirements.table.linux.platform: "Linux (X11 o XWayland)" +tutorial.requirements.table.macOS.graphicsBackend: "Metal 4" +tutorial.requirements.table.macOS.platform: "macOS" +tutorial.requirements.table.windows.graphicsBackend: "DirectX 12" +tutorial.requirements.table.windows.platform: "Windows" +tutorial.requirements.title: "Requisitos previos" +tutorial.resize.context: "Compile y ejecute la aplicación de nuevo. El fondo debe seguir ocupando toda la ventana al cambiar su tamaño: cada nueva pasada ajusta el área de visualización y el rectángulo de recorte a las dimensiones del adjunto. Conserve la función de renderizado; el triángulo se dibujará dentro de esta misma pasada." +tutorial.resize.description: "La cadena de intercambio debe adaptarse a los cambios de tamaño del búfer de fotogramas. Registre una función para {framebufferResize} después de la función de renderizado y antes de {windowRun}:" +tutorial.resize.details: "Responda a los {link}, que se miden en píxeles, en lugar de a los cambios de tamaño lógico de la ventana. Si al minimizar la ventana alguna dimensión pasa a ser cero, la función de redimensionamiento mantiene la cadena de intercambio tal como está. La función de renderizado también retorna mientras alguna dimensión sea cero, de modo que el renderizado se reanuda cuando el búfer de fotogramas vuelve a tener un tamaño válido." +tutorial.resize.details.link: "cambios de tamaño del búfer de fotogramas" +tutorial.resize.guidance: "La función de renderizado espera a que termine cada fotograma enviado antes de llamar a {present}. Por ello, la función de redimensionamiento puede sustituir las imágenes de la cadena de intercambio sin interrumpir trabajo de un fotograma anterior. El artículo {link} explica la relación entre la finalización del trabajo y la vida útil de los recursos." +tutorial.resize.guidance.link: "Sincronización" +tutorial.resize.title: "Redimensionamiento" +tutorial.shaders.compilation.context: "{appContextBaseDirectory} permite cargar la copia del sombreador situada en el directorio de salida de la aplicación. Así, el archivo se busca en el mismo lugar aunque la aplicación se inicie desde otro directorio de trabajo." +tutorial.shaders.compilation.description: "Para {triangleSlang}, establezca {emphasis} en {detail}. La compilación copiará el archivo junto al ejecutable." +tutorial.shaders.compilation.description.detail: "Copiar si es posterior" +tutorial.shaders.compilation.description.emphasis: "Copiar en el directorio de salida" +tutorial.shaders.compilation.details: "En {programCs}, añada la inicialización de sombreadores después de cargar los vértices y antes del callback:" +tutorial.shaders.compilation.guidance: "{zenithCompiler} compila el código fuente para {contextGraphicsApi}, y {createShader} crea un objeto sombreador a partir de la descripción compilada. Los nombres de punto de entrada {vSMain} y {fSMain} seleccionan las dos funciones definidas en el archivo Slang." +tutorial.shaders.compilation.title: "Compilación de sombreadores" +tutorial.shaders.context: "{fSInput} conecta las dos etapas del sombreador. El sombreador de vértices escribe en {sVPOSITION} una posición en el espacio de recorte, que la GPU utiliza para determinar qué parte del triángulo es visible. El campo {cOLOR0} transporta el color del vértice, que se interpola sobre el triángulo antes de llegar al sombreador de fragmentos. Su tipo y su semántica deben coincidir en ambas etapas." +tutorial.shaders.description: "Los sombreadores son programas que se ejecutan en la GPU. El sombreador de vértices determina la posición de cada vértice, y el sombreador de fragmentos determina el color en cada posición cubierta de la imagen. Ambos se escribirán en un mismo archivo Slang, con un punto de entrada propio para cada etapa: la función por la que comienza su ejecución." +tutorial.shaders.details: "Cree {triangleSlang} con estas estructuras de entrada y salida:" +tutorial.shaders.fragment.description: "Añada el punto de entrada de fragmentos al mismo archivo:" +tutorial.shaders.fragment.details: "La rasterización determina qué zonas de la imagen cubre el triángulo y genera fragmentos en esas posiciones. Cada fragmento recibe un color interpolado a partir de los colores de los tres vértices. {fSMain} devuelve ese color, y {sVTARGET} dirige el resultado al primer adjunto de color." +tutorial.shaders.fragment.title: "Sombreado de fragmentos" +tutorial.shaders.guidance: "{vSInput} define las entradas del sombreador de vértices. {pOSITION0} y {cOLOR0} identifican atributos por semántica; los nombres C# no establecen esa correspondencia." +tutorial.shaders.title: "Etapas de sombreado" +tutorial.shaders.vertex.description: "Añada el punto de entrada de vértices a {triangleSlang}:" +tutorial.shaders.vertex.details: "La GPU invoca este punto para cada vértice, incorpora la coordenada homogénea {w} y transmite el color. La posición se divide después por w. Aquí vale 1, por lo que x, y y z no cambian y se interpretan como coordenadas normalizadas del dispositivo." +tutorial.shaders.vertex.title: "Sombreado de vértices" +tutorial.surface.description: "Defina el destino de presentación nativo {emphasis}:" +tutorial.surface.description.emphasis: "después de {windowCenter} y antes de {windowRun}" +tutorial.surface.details: "El búfer de fotogramas es la imagen de la ventana en píxeles. {surface} describe el destino nativo de presentación y sus dimensiones; {framebufferSize} proporciona el tamaño en píxeles. Con el escalado de pantalla, este puede diferir del tamaño lógico de la ventana." +tutorial.surface.guidance: "La superficie proporciona los identificadores nativos del backend: una ventana Win32 en Windows, una pantalla y una ventana X11 en Linux o la capa Metal conectada en macOS." +tutorial.surface.title: "Superficie nativa" +tutorial.swapChain.context: "La cadena depende del contexto y de la ventana. Sustituya {windowDispose} al final de {programCs} por este orden de liberación:" +tutorial.swapChain.description: "Cree la cadena inmediatamente después de describir la superficie:" +tutorial.swapChain.details: "La {swapChain} gestiona las imágenes presentadas. {drawable} suministra la actual como {texture}, el recurso de imagen de la API. Tras renderizar, {present} solicita mostrarla y avanza a la siguiente." +tutorial.swapChain.guidance: "{b8G8R8A8UNorm} almacena cuatro canales de 8 bits en orden azul, verde, rojo y alfa. {uNorm} hace corresponder 0–255 con 0–1. La salida sigue siendo RGBA lógico; el formato define su almacenamiento. La canalización usa {swapChainDescFormat} para coincidir con el adjunto." +tutorial.swapChain.title: "Cadena de intercambio" +tutorial.title: "Primer triángulo" +tutorial.troubleshooting.description: "Utilice los diagnósticos de consola y los tres puntos de control para localizar el fallo:" +tutorial.troubleshooting.details: "El {link} y el {detail} permiten contrastar datos, disposición y dibujo. El ejemplo separa ventana y envío en un host común; el tutorial mantiene el flujo en {programCs}. {context} introduce dibujo indexado, transformaciones y profundidad." +tutorial.troubleshooting.details.context: "Cubo giratorio" +tutorial.troubleshooting.details.detail: "sombreador Slang" +tutorial.troubleshooting.details.link: "renderizador de ejemplo" +tutorial.troubleshooting.table.backend.check: "Compruebe que el backend seleccionado sea compatible con el dispositivo y el controlador de gráficos instalado." +tutorial.troubleshooting.table.backend.symptom: "Falla la creación del backend" +tutorial.troubleshooting.table.drawing.check: "Compruebe el tamaño de la carga, la disposición de entrada, la selección de la canalización y la ubicación de los comandos de dibujo dentro de la pasada de renderizado." +tutorial.troubleshooting.table.drawing.symptom: "Aparece el fondo pero no el triángulo" +tutorial.troubleshooting.table.headings.check: "Comprobación" +tutorial.troubleshooting.table.headings.symptom: "Síntoma" +tutorial.troubleshooting.table.input.check: "Compruebe el paso de 28 bytes y los desplazamientos de posición/color de 0 y 12." +tutorial.troubleshooting.table.input.symptom: "Las posiciones o colores de los vértices están dañados" +tutorial.troubleshooting.table.shaders.check: "Compruebe el archivo {triangleSlang} copiado, la ortografía del punto de entrada y el diagnóstico notificado por el compilador." +tutorial.troubleshooting.table.shaders.symptom: "El fondo se muestra, pero falla la carga de los sombreadores" +tutorial.troubleshooting.table.window.check: "Confirme que el proyecto .NET se compila y que el paso de solo ventana se ejecuta en una sesión de escritorio. En Linux, compruebe que X11 o XWayland estén disponibles." +tutorial.troubleshooting.table.window.symptom: "No se abre ninguna ventana" +tutorial.troubleshooting.title: "Diagnóstico de problemas" +tutorial.window.description: "Descargue {cocoaHelperCs} en el directorio del proyecto. Esta clase auxiliar conecta la capa Metal a la ventana de macOS." +tutorial.window.details: "Sustituya el contenido generado de {programCs} por el código siguiente. Usa instrucciones de nivel superior que se ejecutan en orden, sin un método {main} explícito. Las siguientes secciones indicarán dónde añadir cada fragmento:" +tutorial.window.guidance: "{graphicsAPINone} deja la creación del contexto gráfico a Zenith.NET. {initialize} crea la ventana nativa y permite acceder a los identificadores del sistema de ventanas. {center} la coloca en el centro de la pantalla. {run} procesa los eventos hasta que se cierra; después se ejecuta {dispose} para liberarla." +tutorial.window.notes: "Compile y ejecute la aplicación. Compruebe que puede abrir, mover, redimensionar y cerrar la ventana. Su contenido aún no está definido porque no se han enviado comandos de renderizado. Cierre la ventana antes de continuar." +tutorial.window.title: "Creación de la ventana" +ui.action.copy: "Copiar" +ui.action.navigate: "Navegar" +ui.action.open: "Abrir" +ui.action.source: "Ver código fuente" +ui.api.browse: "Examinar espacios de nombres y tipos." +ui.api.clearTypeSearch: "Borrar búsqueda de tipos" +ui.api.findType: "Buscar un tipo" +ui.api.loadError: "No se pudieron cargar los tipos. Recargue esta página para intentarlo de nuevo." +ui.api.loadingNamespaces: "Cargando espacios de nombres…" +ui.api.loadingTypes: "Cargando tipos…" +ui.api.matchingTypes: "Tipos coincidentes" +ui.api.namespace: "Espacio de nombres" +ui.api.namespaces: "Espacios de nombres" +ui.api.noNamespaceTypes: "No hay tipos en este espacio de nombres." +ui.api.noTypes: "No hay tipos coincidentes." +ui.api.types: "Tipos" +ui.content.reference: "Referencia" +ui.content.source: "Código fuente" +ui.content.tutorial: "Tutorial" +ui.contents.close: "Cerrar el índice" +ui.contents.open: "Abrir el índice" +ui.contents.title: "Índice" +ui.footer.caption: "API gráfica para .NET" +ui.footer.label: "Pie de página" +ui.language.label: "Idioma" +ui.language.unavailable: "No traducido" +ui.members.clear: "Borrar búsqueda de miembros" +ui.members.close: "Cerrar buscador de miembros" +ui.members.empty: "No hay miembros coincidentes." +ui.members.open: "Ir al miembro" +ui.members.placeholder: "Nombre o firma…" +ui.members.search: "Buscar miembros" +ui.members.title: "Buscar un miembro" +ui.members.undeclared: "Este tipo no tiene miembros declarados." +ui.navigation.api: "API" +ui.navigation.concepts: "Conceptos" +ui.navigation.home: "Inicio" +ui.navigation.label: "Navegación principal" +ui.navigation.toggle: "Alternar navegación" +ui.outline.title: "En esta página" +ui.reference.assembly: "Ensamblado" +ui.reference.classes: "Clases" +ui.reference.constructors: "Constructores" ui.reference.declaration: "Declaración de tipo C#" -ui.reference.delegates: Delegados -ui.reference.derived: Tipos derivados -ui.reference.enums: Enumeraciones -ui.reference.events: Eventos -ui.reference.examples: Ejemplos -ui.reference.exceptions: Excepciones -ui.reference.extensionMethods: Métodos de extensión -ui.reference.fields: Campos -ui.reference.implementations: Implementaciones explícitas de interfaz -ui.reference.implements: Implementa -ui.reference.inheritance: Herencia -ui.reference.inheritedMembers: Miembros heredados -ui.reference.interfaces: Interfaces -ui.reference.metadata: Metadatos de tipo -ui.reference.methods: Métodos -ui.reference.namespace: Espacio de nombres -ui.reference.open: Abrir referencia de {name} -ui.reference.operators: Operadores -ui.reference.parameters: Parámetros -ui.reference.properties: Propiedades -ui.reference.related: Vea también -ui.reference.relationships: Herencia y metadatos -ui.reference.remarks: Comentarios -ui.reference.returns: Devuelve -ui.reference.structs: Estructuras -ui.reference.typeParameters: Parámetros de tipo -ui.reference.value: Valor -ui.reference.values: Valores -ui.search.close: Cerrar búsqueda -ui.search.empty: No hay resultados para «{query}». -ui.search.hint: Busque en tutoriales, conceptos, ejemplos y en la referencia de la API. -ui.search.loading: Cargando búsqueda… -ui.search.more: Mostrar más resultados -ui.search.pending: Buscando… -ui.search.placeholder: ¿Qué está buscando? +ui.reference.delegates: "Delegados" +ui.reference.derived: "Tipos derivados" +ui.reference.enums: "Enumeraciones" +ui.reference.events: "Eventos" +ui.reference.examples: "Ejemplos" +ui.reference.exceptions: "Excepciones" +ui.reference.extensionMethods: "Métodos de extensión" +ui.reference.fields: "Campos" +ui.reference.implementations: "Implementaciones explícitas de interfaz" +ui.reference.implements: "Implementa" +ui.reference.inheritance: "Herencia" +ui.reference.inheritedMembers: "Miembros heredados" +ui.reference.interfaces: "Interfaces" +ui.reference.metadata: "Metadatos de tipo" +ui.reference.methods: "Métodos" +ui.reference.namespace: "Espacio de nombres" +ui.reference.open: "Abrir referencia de {name}" +ui.reference.operators: "Operadores" +ui.reference.parameters: "Parámetros" +ui.reference.properties: "Propiedades" +ui.reference.related: "Vea también" +ui.reference.relationships: "Herencia y metadatos" +ui.reference.remarks: "Comentarios" +ui.reference.returns: "Devuelve" +ui.reference.structs: "Estructuras" +ui.reference.typeParameters: "Parámetros de tipo" +ui.reference.value: "Valor" +ui.reference.values: "Valores" +ui.search.close: "Cerrar búsqueda" +ui.search.empty: "No hay resultados para «{query}»." +ui.search.hint: "Busque en tutoriales, conceptos, ejemplos y en la referencia de la API." +ui.search.loading: "Cargando búsqueda…" +ui.search.more: "Mostrar más resultados" +ui.search.pending: "Buscando…" +ui.search.placeholder: "¿Qué está buscando?" ui.search.resultCount: "Resultados: {count}" -ui.search.title: Buscar en la documentación -ui.search.unavailable: La búsqueda no está disponible. Aún puede abrir las páginas siguientes. +ui.search.title: "Buscar en la documentación" +ui.search.unavailable: "La búsqueda no está disponible. Aún puede abrir las páginas siguientes." diff --git a/documents/locales/es-ES/translation.md b/documents/locales/es-ES/translation.md index 65fee19c..92822bd5 100644 --- a/documents/locales/es-ES/translation.md +++ b/documents/locales/es-ES/translation.md @@ -8,6 +8,16 @@ La navegación, el orden de los capítulos, las anclas, los enlaces, el formato, Modifique únicamente los valores de la propia `strings.yml`. El conjunto de claves debe coincidir exactamente con el inglés. No añada, elimine ni renombre claves por iniciativa propia, aunque parezcan repetidas o correspondan a textos de interfaz que aún no haya visto. Si encuentra un error en el original, comunique la clave y el problema a los responsables del proyecto. Primero se corrigen la fuente inglesa y las páginas compartidas; después, las traducciones. +## Estilo y contexto + +Emplear un estilo de manual técnico: preciso, sobrio y comprensible. Explicar la relación entre las operaciones antes de sus restricciones. En los tutoriales, mantener instrucciones concretas y resultados comprobables. El rigor no requiere pasivas ni frases innecesariamente largas. + +Revisar cada artículo en su orden de lectura, junto con los párrafos, tablas y código que lo rodean. Las claves son límites de almacenamiento, no unidades de traducción aisladas. Comprobar las concordancias y preposiciones de los enlaces y fragmentos destacados dentro de la frase completa. + +Los títulos, etiquetas, textos breves visibles de la portada y leyenda del pie no llevan punto final. Los párrafos, diagnósticos e instrucciones de accesibilidad conservan la puntuación normal. Utilizar un término asentado por concepto, sin añadir de forma selectiva equivalentes ingleses entre paréntesis. Conservar los identificadores de API, archivos y ajustes. + +Conserve una frase si explica la operación actual, una decisión de diseño, un resultado comprobable o una condición necesaria. Elimine listas de funciones que no se usan, advertencias genéricas y requisitos repetidos. Traduzca los títulos y las frases divididas por el formato como una unidad, con el orden natural del español. Los marcadores `{accent}` y `{lineBreak}` del título de portada pueden moverse; el diseño no debe imponer la sintaxis inglesa. La eliminación de un pasaje y sus claves se coordina en el original, el marcado común y todos los diccionarios. + ## Texto y marcadores Traduzca frases o párrafos completos con un español técnico claro y natural. Conserve las condiciones, negaciones, unidades, pasos y restricciones de vida útil. No añada garantías técnicas, requisitos de plataforma, versiones de paquetes ni notas de versiones ausentes del original. Mantenga los nombres de productos, paquetes y archivos, así como los identificadores de C# y Slang, incluidas sus mayúsculas y minúsculas. diff --git a/documents/locales/fr-FR/strings.yml b/documents/locales/fr-FR/strings.yml index fefe795e..d05da25f 100644 --- a/documents/locales/fr-FR/strings.yml +++ b/documents/locales/fr-FR/strings.yml @@ -1,92 +1,91 @@ ### YamlMime:Resources -concepts.execution.context.description: Un {graphicsContext} représente un périphérique backend et fournit ses files de graphisme, de calcul et de transfert. Créez les tampons, textures, shaders et pipelines pour une charge de travail via le même contexte. Une ressource ou un handle créé par un autre contexte ne peut pas simplement être lié aux tampons de commandes de celui-ci. -concepts.execution.context.details: Choisissez le backend pour la plateforme et la surface de présentation. L’API reste partagée, mais la prise en charge des périphériques compte toujours. {capabilities} expose le nom du périphérique et les indicateurs {rayTracingSupported} et {meshShadingSupported}. Vérifiez l’indicateur correspondant avant de créer une charge de travail optionnelle, comme le font les exemples {link} et {detail}. Ces indicateurs ne constituent pas une liste exhaustive des restrictions de format, de mémoire ou de plateforme. +concepts.execution.context.description: "Un {graphicsContext} relie l’application à un périphérique GPU par un backend donné et fournit ses files graphiques, de calcul et de transfert. Les ressources utilisées ensemble doivent appartenir au même contexte : tampons, textures, shaders, pipelines et handles ne peuvent pas être liés d’un contexte à un autre." +concepts.execution.context.details: "{capabilities} indique le nom du périphérique et les fonctions prises en charge. Vérifiez {rayTracingSupported} et {meshShadingSupported} avant de créer les ressources nécessaires à ces fonctions. Les exemples de {link} et de {detail} effectuent ces vérifications à l’initialisation." concepts.execution.context.details.detail: mesh shading concepts.execution.context.details.link: lancer de rayons -concepts.execution.context.title: Le contexte relie les ressources et les files -concepts.execution.description: Une application Zenith.NET crée des ressources GPU, enregistre des commandes qui les utilisent et soumet ces commandes à une file. Le CPU peut continuer pendant que le GPU exécute la soumission. Gardez les ressources valides jusqu’à ce que ce travail soit terminé, même après le retour des appels d’enregistrement. -concepts.execution.ownership.description: "Ici, la propriété signifie la responsabilité de la libération. Une référence C# maintient un objet managé accessible ; elle n’empêche pas un {dispose} explicite de détruire la ressource native. De même, la soumission d’une commande qui utilise un tampon ne transfère pas la propriété de ce tampon à la file." -concepts.execution.ownership.details: Lors de l’arrêt, cessez de soumettre de nouveaux travaux, attendez les dernières utilisations sur chaque file impliquée, libérez les ressources de l’application, puis libérez le contexte. La libération du contexte libère ses propres files et assistants internes ; elle n’attend pas tous les travaux de l’application et ne libère pas chaque ressource créée par l’application. -concepts.execution.ownership.guidance: Appliquez les mêmes règles de durée de vie pendant le rendu. Conservez la valeur d’achèvement pour la dernière utilisation d’une ressource afin de savoir quand ses octets peuvent être écrasés ou quand la ressource peut être remplacée. Consultez {link} pour les vues et les durées de vie des ressources sous-jacentes. +concepts.execution.context.title: "Contexte graphique" +concepts.execution.description: "Le travail du GPU se prépare sur le CPU : l’application crée des ressources, enregistre les commandes qui les utilisent, puis les soumet à une file. Le CPU peut ensuite poursuivre son exécution pendant que le GPU traite ces commandes. Les ressources nécessaires doivent rester disponibles jusqu’à la fin de ce traitement." +concepts.execution.ownership.description: "La propriété détermine qui libère un objet ; l’achèvement sur le GPU détermine quand il peut être libéré. Un appel à {dispose} libère les ressources natives même si des références C# à l’objet existent encore. Soumettre des commandes ne transfère pas la propriété de leurs ressources à la file." +concepts.execution.ownership.details: "À l’arrêt, cesser les nouvelles soumissions et attendre la dernière utilisation des ressources sur chaque file concernée. Libérer ensuite les ressources de l’application, puis le contexte. Celui-ci libère ses files et ses objets auxiliaires internes ; cette dernière étape doit donc intervenir après la fin du travail de l’application." +concepts.execution.ownership.guidance: "Pendant le rendu, suivre l’achèvement des accès aux données à modifier ou aux ressources à remplacer. Attendre la fin de ces accès avant de modifier ou de libérer la mémoire concernée. L’article {link} explique comment les vues et les ressources sous-jacentes s’inscrivent dans ce modèle de durée de vie." concepts.execution.ownership.guidance.link: Gestion des ressources concepts.execution.ownership.table.applicationResources.object: Ressources créées par l’application concepts.execution.ownership.table.applicationResources.ownership: L’application les libère après leur dernière utilisation par le GPU. concepts.execution.ownership.table.commandBuffers.object: Tampons de commandes empruntés concepts.execution.ownership.table.commandBuffers.ownership: La file les gère et les recycle. concepts.execution.ownership.table.headings.object: Objet -concepts.execution.ownership.table.headings.ownership: Qui le libère ? +concepts.execution.ownership.table.headings.ownership: "Responsabilité de libération" concepts.execution.ownership.table.queues.object: Files de contexte et leurs lignes de temps concepts.execution.ownership.table.queues.ownership: Le contexte et les files les gèrent. concepts.execution.ownership.table.swapChainDrawable.ownership: La chaîne d’échange la gère. -concepts.execution.ownership.title: Séparer la propriété de l’achèvement GPU -concepts.execution.pipelines.description: Un pipeline graphique combine les shaders, l’agencement d’entrée des sommets, la règle d’assemblage des sommets en primitives, les formats d’attachement et l’état de rendu. Définissez-le avant de lier les données de sommets, d’indices ou de constantes et d’émettre des commandes de dessin. Ses formats d’attachement et son nombre d’échantillons doivent correspondre aux attachements de la passe de rendu. -concepts.execution.pipelines.details: Un pipeline de calcul fournit le point d’entrée de shader pour un dispatch, qui lance des groupes de threads GPU. Définissez-le ainsi que ses constantes avant le dispatch. Les dispatches de calcul appartiennent à l’extérieur des passes de rendu graphique. Changer de pipeline modifie la façon dont les commandes ultérieures interprètent leurs entrées ; liez les données requises par le pipeline sélectionné avant de l’utiliser. -concepts.execution.pipelines.guidance: Le {link} montre la séquence graphique complète. L’{detail} enregistre un dispatch suivi d’une passe graphique qui affiche le résultat. +concepts.execution.ownership.title: "Propriété et durée de vie" +concepts.execution.pipelines.description: "Un pipeline graphique définit les shaders, la disposition des attributs de sommets, l’assemblage des primitives, les formats d’attachement et l’état de rendu. Il doit être sélectionné avant les liaisons de sommets, d’indices ou de constantes. Ses formats et son nombre d’échantillons doivent correspondre à la passe de rendu." +concepts.execution.pipelines.details: "Un pipeline de calcul sélectionne le point d’entrée du shader pour un lancement de calcul. Lier le pipeline et ses constantes avant ce lancement, en dehors d’une passe de rendu graphique." +concepts.execution.pipelines.guidance: "Le {link} présente la séquence graphique. L’{detail} ajoute un lancement de calcul avant la passe graphique qui en affiche le résultat." concepts.execution.pipelines.guidance.detail: exemple de calcul concepts.execution.pipelines.guidance.link: rappel de rendu du triangle -concepts.execution.pipelines.title: Un pipeline détermine comment les commandes interprètent les données -concepts.execution.queues.description: Commencez avec {graphicsQueue} lorsqu’une image combine dessin, calcul et copies. Conserver le travail dépendant sur une seule file rend son ordonnancement plus facile à suivre. -concepts.execution.queues.details: Une file accepte des lots de commandes pour exécution. Des files distinctes ne correspondent pas nécessairement à des moteurs matériels distincts, de sorte que leur travail peut ne pas s’exécuter simultanément. Utilisez une autre file lorsque la charge de travail peut bénéficier d’un chevauchement, et ajoutez une dépendance explicite lorsqu’une file consomme les résultats d’une autre file. -concepts.execution.queues.guidance: Lorsque des commandes ultérieures dépendent d’écritures antérieures, l’application doit également s’assurer que ces écritures sont disponibles pour les commandes ultérieures. La soumission des deux tampons de commandes à la même file n’établit pas automatiquement chaque dépendance de ce type. Les commandes peuvent utiliser différentes étapes de GPU, et les accès ultérieurs peuvent nécessiter une barrière ou une transition de texture. {link} explique la distinction entre ordre de soumission et visibilité des ressources. +concepts.execution.pipelines.title: "État du pipeline" +concepts.execution.queues.description: "{graphicsQueue} constitue le point de départ habituel lorsqu’une image combine dessin, calcul et copies. Regrouper les opérations dépendantes dans une même file simplifie leur ordonnancement." +concepts.execution.queues.details: "Des files distinctes permettent de soumettre séparément des tâches indépendantes, mais ne correspondent pas nécessairement à des moteurs matériels indépendants. Elles sont utiles lorsque les tâches peuvent bénéficier d’une exécution partiellement simultanée. Lorsqu’une file utilise les données produites par une autre, leurs soumissions doivent être reliées par une dépendance explicite." +concepts.execution.queues.guidance: "Dans une même file, des opérations dépendantes peuvent aussi nécessiter des barrières ou des transitions de texture pour que les accès ultérieurs voient les écritures précédentes. Ces dépendances mémoire sont distinctes de l’ordre de soumission. L’article {link} explique comment les exprimer." concepts.execution.queues.guidance.link: Synchronisation -concepts.execution.queues.table.computeQueue.workToRecord: Dispatches de calcul et travail de transfert compatible, sans passes de rendu graphique. -concepts.execution.queues.table.graphicsQueue.workToRecord: Passes de rendu et dessin, plus opérations de calcul et de transfert utilisées par l’image. +concepts.execution.queues.table.computeQueue.workToRecord: "Lancements de calcul et transferts compatibles, sans passe graphique." +concepts.execution.queues.table.graphicsQueue.workToRecord: "Passes de rendu, dessin, calcul et transferts." concepts.execution.queues.table.headings.queue: File -concepts.execution.queues.table.headings.workToRecord: Travail à enregistrer -concepts.execution.queues.table.transferQueue.workToRecord: Travail de chargement, téléchargement et copie, sans dessin ni dispatches de calcul. -concepts.execution.queues.title: Choisir une file pour le travail qu’elle exécutera -concepts.execution.recording.context: La file interroge l’achèvement et recycle les tampons de commandes terminés. Appelez {queueCommandBuffer} pour chaque nouvel enregistrement ; il peut renvoyer une instance recyclée. Ne libérez pas un tampon de commandes emprunté, ne le soumettez pas deux fois et ne continuez pas à y enregistrer après soumission. Enregistrez un tampon de commandes donné depuis un seul thread à la fois ; le verrouillage interne de la file ne protège pas contre les modifications simultanées d’un tampon de commandes. -concepts.execution.recording.description: "{queueCommandBuffer} renvoie un {commandBuffer} dont l’enregistrement a déjà commencé. Enregistrez les commandes et leurs dépendances, puis appelez {submit} une fois. La soumission met fin à l’enregistrement et renvoie une {timelineValue} identifiant un point d’achèvement sur cette file." -concepts.execution.recording.details: "Par exemple, après avoir enregistré une image dans {commandBuffer}, le tutoriel du triangle soumet ce tampon et attend son achèvement ainsi :" -concepts.execution.recording.guidance: "{submit} planifie le travail ; {wait} empêche le CPU de continuer jusqu’à ce que cette soumission soit terminée. L’enregistrement d’un dessin, la fin d’une passe de rendu et la soumission d’un tampon de commandes sont des opérations distinctes. Ni l’enregistrement du dessin ni la fin de la passe n’attendent le GPU." -concepts.execution.recording.title: L’enregistrement n’exécute pas les commandes +concepts.execution.queues.table.headings.workToRecord: "Opérations prises en charge" +concepts.execution.queues.table.transferQueue.workToRecord: "Transferts vers ou depuis le GPU et copies, sans dessin ni lancement de calcul." +concepts.execution.queues.title: "Choix des files" +concepts.execution.recording.context: "La file récupère les tampons de commandes terminés pour les réutiliser. Pour chaque enregistrement, obtenir un tampon avec {queueCommandBuffer}, l’enregistrer depuis un seul thread à la fois et le soumettre une seule fois. Après la soumission, le laisser à la file : ne plus le modifier, le soumettre à nouveau ou le libérer." +concepts.execution.recording.description: "{queueCommandBuffer} renvoie un {commandBuffer} dont l’enregistrement a commencé. Une fois les opérations et leurs dépendances enregistrées, appeler {submit} une seule fois. La soumission termine l’enregistrement et fournit une {timelineValue} qui identifie le point d’achèvement de cette file." +concepts.execution.recording.details: "Après l’enregistrement d’une image dans {commandBuffer}, le tutoriel soumet le tampon et attend son achèvement :" +concepts.execution.recording.guidance: "L’enregistrement construit la séquence de commandes ; {submit} en planifie l’exécution. Un appel à {wait} bloque ensuite le thread CPU jusqu’à la fin de la soumission. Dans le tutoriel, la boucle de rendu reste ainsi facile à suivre : chaque image est terminée avant que la suivante commence." +concepts.execution.recording.title: "Enregistrement et soumission" concepts.execution.title: Modèle d’exécution -concepts.platforms.description: Choisissez si votre application possède la fenêtre native et la boucle de trame ou si elle utilise un contrôle de rendu d’interface utilisateur. Ce choix détermine qui obtient la texture de sortie, soumet les commandes et présente le résultat. La texture de sortie est la texture utilisée comme sortie de l’image actuelle. Les travaux graphiques et de calcul hors écran ne nécessitent ni fenêtre ni chaîne d’échange. -concepts.platforms.frame.context: Ajoutez vos liaisons de pipeline et vos commandes de dessin à l’intérieur de cette passe. Terminez la passe avant de revenir. Ne soumettez pas le tampon de commandes fourni et ne présentez pas de manière indépendante, et ne libérez ni le tampon de commandes ni la texture de sortie. Si votre gestionnaire utilise la texture de sortie dans un autre layout, remettez-la en {colorAttachment} pour la transition finale du contrôle. -concepts.platforms.frame.description: Les intégrations implémentent {iZenithView}. L’application fournit son {graphicsContext}, met à jour les données de scène dans {updateRequested} et enregistre le rendu dans {renderRequested} à l’aide de {renderEventArgs}. -concepts.platforms.frame.details: "Le contrôle gère le déroulement complet de chaque image. Il obtient la texture de sortie et le tampon de commandes, fait passer la texture à {colorAttachment}, appelle les gestionnaires, puis effectue la soumission et la présentation requises par le framework." -concepts.platforms.frame.guidance: "Pour une {iZenithView} initialisée nommée {view}, avec un contexte attribué, ce gestionnaire enregistre une passe d’effacement complète. Il nécessite {usingZenithNET} :" -concepts.platforms.frame.notes: Les contrôles effectuent une transition depuis {undefined} au début de chaque image, de sorte que les applications ne peuvent pas compter sur la préservation du contenu précédent de la texture de sortie. Effacez ou rendez l’image requise à chaque image. Conservez l’accumulation persistante ou le rendu mis en cache dans une texture appartenant à l’application, puis affichez cette texture via la vue. -concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat} fournit le format de couleur par défaut des intégrations. Vérifiez la texture de sortie réelle de l’événement lors de la mise en correspondance des formats d’attachement, des nombres d’échantillons et des dimensions." -concepts.platforms.frame.title: Enregistrer dans l’image fournie par un contrôle d’interface utilisateur -concepts.platforms.integration.context: WinForms, WPF et la voie WinUI sous Windows nécessitent Windows. Les applications MAUI ont besoin de la charge de travail de leur plateforme cible et doivent enregistrer le gestionnaire de contrôle avec {useZenithView} ; voir {extensionsCs}. La prise en charge du framework et celle du backend doivent toutes deux être satisfaites. -concepts.platforms.integration.description: "Les contrôles partagent l’interface d’événements, mais ils ne présentent pas tous de la même manière :" -concepts.platforms.integration.details: La lecture de bitmap (bitmap readback) copie les pixels rendus dans la mémoire CPU avant que l’interface utilisateur ne les affiche. L’interopérabilité par texture partagée évite cette lecture, mais peut toujours nécessiter des copies et une synchronisation GPU. L’interface partagée {renderRequested} n’implique donc pas des coûts de présentation identiques ou des exigences d’interopérabilité native identiques. -concepts.platforms.integration.guidance: "Utilisez le paquet adapté au framework de l’application ; par exemple :" +concepts.platforms.description: "La présentation est gérée par l’application ou par un contrôle d’interface. Ce choix détermine qui obtient la texture de sortie de l’image, enregistre et soumet les commandes, puis présente le résultat. Cette texture de sortie est appelée drawable." +concepts.platforms.frame.context: "Enregistrer les liaisons de pipeline et les commandes de dessin dans la passe, puis la terminer avant que le gestionnaire retourne. Le contrôle soumet les commandes et présente le résultat. Le gestionnaire ne doit ni soumettre le tampon de commandes ni libérer l’un ou l’autre des objets fournis. S’il modifie le layout de la texture de sortie, il doit rétablir {colorAttachment} avant de retourner pour permettre au contrôle d’effectuer la transition finale." +concepts.platforms.frame.description: "Les contrôles implémentent {iZenithView}. L’application assigne {graphicsContext}, met à jour la scène dans {updateRequested} et enregistre le rendu dans {renderRequested} à partir de {renderEventArgs}." +concepts.platforms.frame.details: "Pour chaque image, le contrôle obtient une texture de sortie et un tampon de commandes, passe la texture au layout {colorAttachment}, puis appelle les gestionnaires de mise à jour et de rendu. Il soumet ensuite les commandes enregistrées et présente l’image par le mécanisme du framework." +concepts.platforms.frame.guidance: "Ajouter {usingZenithNET} au fichier. Pour un {iZenithView} initialisé, nommé {view} et associé à un contexte graphique, enregistrer ce gestionnaire afin de remplir sa texture de sortie avec une couleur :" +concepts.platforms.frame.notes: "La transition initiale utilise {undefined}, ce qui autorise l’abandon du contenu précédent. Dessiner ou réinitialiser l’image entière à chaque rendu. Pour conserver une accumulation ou un résultat en cache, utiliser une texture appartenant à l’application, puis dessiner cette texture dans la sortie du contrôle." +concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat} fournit le format de couleur par défaut de ces intégrations." +concepts.platforms.frame.title: "Rendu par un contrôle UI" +concepts.platforms.integration.context: "WinForms, WPF et l’intégration Windows de WinUI s’exécutent sous Windows. Pour MAUI, installer la charge de travail de la plateforme cible et enregistrer le gestionnaire du contrôle avec {useZenithView}, comme dans {extensionsCs}." +concepts.platforms.integration.description: "L’interface d’événements est commune, mais la présentation dépend du framework :" +concepts.platforms.integration.details: "Ces implémentations diffèrent par la façon dont l’image GPU rejoint l’interface. La lecture vers un bitmap copie les pixels en mémoire CPU avant l’affichage. L’interopérabilité par texture partagée évite cette copie CPU, mais peut encore nécessiter des copies GPU et de la synchronisation. Pour choisir une intégration, considérer ce chemin de présentation en plus de l’événement commun {renderRequested}." +concepts.platforms.integration.guidance: "Ajoutez le paquet d’intégration correspondant à votre framework d’interface via NuGet. Pour Avalonia, utilisez {avaloniaPackage}." concepts.platforms.integration.table.avalonia.integration: Avalonia -concepts.platforms.integration.table.avalonia.presentation: Effectue le rendu dans une texture et télécharge les pixels dans un {writeableBitmap}. Voir {zenithViewCs} et {surfaceCs}. +concepts.platforms.integration.table.avalonia.presentation: "Effectue le rendu dans une texture, puis copie les pixels en mémoire CPU dans {writeableBitmap}. Implémentation : {zenithViewCs} et {surfaceCs}." concepts.platforms.integration.table.headings.integration: Intégration -concepts.platforms.integration.table.headings.presentation: Comment son image parvient à l’interface +concepts.platforms.integration.table.headings.presentation: "Mécanisme de présentation" concepts.platforms.integration.table.maui.integration: .NET MAUI concepts.platforms.integration.table.maui.presentation: Utilise des surfaces natives sur Android, iOS et Mac Catalyst, et la composition par texture partagée sous Windows. Voir les {link}. concepts.platforms.integration.table.maui.presentation.link: implémentations de plateforme concepts.platforms.integration.table.uno.integration: Voie Uno -concepts.platforms.integration.table.uno.presentation: Télécharge les pixels dans un {writeableBitmap}. Voir {zenithViewUnoCs}. +concepts.platforms.integration.table.uno.presentation: "Copie les pixels en mémoire CPU dans {writeableBitmap}. Implémentation : {zenithViewUnoCs}." concepts.platforms.integration.table.winForms.integration: WinForms concepts.platforms.integration.table.winForms.presentation: Crée une chaîne d’échange Zenith.NET pour le {hWND} du contrôle. Voir {zenithViewCs}. concepts.platforms.integration.table.winUI.integration: WinUI sous Windows -concepts.platforms.integration.table.winUI.presentation: Effectue le rendu dans une texture partagée Direct3D 11 importée, puis copie vers une chaîne d’échange de composition attachée à {swapChainPanel}. Voir {zenithViewWinUICs}. +concepts.platforms.integration.table.winUI.presentation: "Effectue le rendu dans une texture partagée Direct3D 11 importée, puis copie le résultat vers une chaîne d’échange de composition attachée à {swapChainPanel}. Voir {zenithViewWinUICs}." concepts.platforms.integration.table.wpf.integration: WPF -concepts.platforms.integration.table.wpf.presentation: Importe une texture partagée Direct3D 11, puis copie via l’interopérabilité Direct3D vers une surface affichée par {d3DImage}. Voir {surfaceCs}. -concepts.platforms.integration.title: Choisir la voie de présentation ainsi que le framework -concepts.platforms.lifecycle.context: Pour une vue d’interface utilisateur, utilisez les propriétés {descWidth}, {descHeight}, {descFormat} et {descSampleCount} de la texture de sortie de l’événement lors de la création de ressources de rendu correspondantes. Le contrôle détermine la résolution de cette texture de sortie ; ne supposez pas que ses dimensions logiques ou son échelle d’affichage sont toujours égales aux dimensions de la texture. -concepts.platforms.lifecycle.description: Pour une chaîne d’échange native, transmettez les dimensions du tampon de trame en pixels. Les tailles de fenêtre exprimées en unités logiques peuvent différer lorsque la mise à l’échelle de l’affichage est activée. Ignorez les tampons de trame de taille zéro, redimensionnez la chaîne d’échange lorsque sa taille de pixel change et obtenez {swapChainDrawable} pour chaque image. La texture de sortie appartient à la chaîne d’échange et peut changer après la présentation ou le redimensionnement. -concepts.platforms.lifecycle.details: "{swapChainResize} modifie les dimensions de la surface existante. {swapChainRefresh} remplace la description de la surface, y compris ses handles natifs. Avant l’une ou l’autre opération, terminez les utilisations en cours des ressources affectées. Libérez la chaîne d’échange avant de détruire sa cible de présentation native." -concepts.platforms.lifecycle.guidance: Recréez les textures de profondeur ou hors écran appartenant à l’application dont la taille suit la fenêtre, et mettez à jour les constantes contenant leurs handles. Un pipeline peut rester utilisé à travers un changement de taille lorsque ses formats d’attachement et son nombre d’échantillons restent compatibles. Le {link} conserve son pipeline tout en remplaçant sa texture de profondeur. +concepts.platforms.integration.table.wpf.presentation: "Importe une texture partagée Direct3D 11, puis copie son contenu, par interopérabilité Direct3D, vers une surface affichée par {d3DImage}. Voir {surfaceCs}." +concepts.platforms.integration.title: "Framework et présentation" +concepts.platforms.lifecycle.context: "Pour créer des attachements compatibles, utiliser {descWidth}, {descHeight}, {descFormat} et {descSampleCount} de la texture de sortie fournie par l’événement de rendu. Cette texture donne les dimensions réelles de la cible ; elles ne doivent pas être déduites de la taille du contrôle dans la mise en page ni de l’échelle d’affichage." +concepts.platforms.lifecycle.description: "La chaîne d’échange utilise la largeur et la hauteur du framebuffer en pixels, qui peuvent différer des dimensions logiques de la fenêtre avec la mise à l’échelle de l’affichage. Différer le rendu et le redimensionnement tant qu’une dimension est nulle. Obtenir {swapChainDrawable} pour chaque image : la chaîne d’échange possède cette texture et peut la remplacer après une présentation ou un redimensionnement." +concepts.platforms.lifecycle.details: "Lors d’un changement de dimensions du framebuffer, attendre les accès GPU en cours aux anciennes images avant d’appeler {swapChainResize}. Pour remplacer la cible native de présentation, transmettre sa nouvelle description et ses handles à {swapChainRefresh}, une fois ces accès terminés. À l’arrêt, libérer la chaîne d’échange avant de détruire sa cible native." +concepts.platforms.lifecycle.guidance: "Si les textures de profondeur ou hors écran de l’application suivent la taille de la fenêtre, les recréer quand celle-ci change et mettre à jour les constantes contenant leurs handles. Le pipeline reste utilisable tant que les formats des attachements et les nombres d’échantillons correspondent. Le {link} montre comment recréer les textures tout en conservant le pipeline." concepts.platforms.lifecycle.guidance.link: moteur de rendu du cube en rotation -concepts.platforms.lifecycle.title: Conserver la taille et la durée de vie de la texture de sortie avec son hôte -concepts.platforms.ownership.description: L’application possède le contexte qu’elle assigne et les ressources qu’elle crée pour le rendu. Le contrôle possède ses propres ressources de présentation. La modification de la propriété {graphicsContext} de la vue amène le planificateur à recréer les ressources du contrôle ; cela ne recrée pas les pipelines, tampons ou textures de l’application pour le nouveau contexte. -concepts.platforms.ownership.details: Coordonnez le remplacement des ressources avec le cycle de vie de l’image de la vue. Arrêtez l’activité de trame de la vue et terminez les utilisations GPU en attente avant de libérer les ressources de l’application ou le contexte assigné. La suppression d’une vue ne transfère pas la propriété du contexte au contrôle. -concepts.platforms.ownership.guidance: Le fichier partagé {frameSchedulerCs} distribue le travail de trame via le dispatcher UI de la vue. Gardez les gestionnaires de trame concentrés sur la mise à jour et l’enregistrement de l’image ; un travail CPU prolongé à cet endroit retarde également l’interface utilisateur. -concepts.platforms.ownership.title: Conserver les ressources de l’application en dehors de la propriété du contrôle -concepts.platforms.surface.context: Une bibliothèque de fenêtrage ou un framework d’interface utilisateur prenant en charge un système d’exploitation ne garantit pas que le backend GPU sélectionné y soit disponible. Les fonctionnalités matérielles, les pilotes et la prise en charge des surfaces natives doivent toujours concorder. Vérifiez le lancer de rayons et le mesh shading optionnels via {contextCapabilities} avant de créer ces charges de travail. -concepts.platforms.surface.description: Le {link} utilise Silk.NET pour créer une fenêtre et traiter les événements. Zenith.NET se connecte à cette fenêtre via une description de {surface} et une {swapChain}. Une surface contient des handles et des dimensions natifs ; la construction de la description ne crée ni ne possède la fenêtre du système d’exploitation. -concepts.platforms.surface.description.link: triangle -concepts.platforms.surface.details: "Le handle doit correspondre au backend sélectionné :" -concepts.platforms.surface.guidance: Le fichier {appCs} du tutoriel montre les choix pour Windows, macOS et X11. Son hôte Linux fournit des handles Xlib ; l’utiliser dans une session Wayland nécessite XWayland. Une application Wayland native fournirait des handles différents via {surfaceWayland}. +concepts.platforms.lifecycle.title: "Dimensions et durée de vie de la chaîne d’échange" +concepts.platforms.ownership.description: "L’application possède le contexte assigné et ses ressources de rendu ; le contrôle possède ses ressources de présentation. Lorsque la propriété {graphicsContext} de la vue change, l’ordonnanceur recrée les ressources du contrôle pour le nouveau contexte. L’application doit également recréer ses pipelines, tampons et textures pour ce contexte." +concepts.platforms.ownership.details: "Avant de remplacer des ressources de rendu, arrêter le traitement des images de la vue et attendre le travail GPU qui les utilise. Libérer ensuite seulement les anciennes ressources ou le contexte. L’application reste responsable de la libération du contexte assigné lors du retrait de la vue." +concepts.platforms.ownership.guidance: "Le {frameSchedulerCs} commun exécute les gestionnaires d’image via le dispatcher de l’interface de la vue. Limiter leur travail à la mise à jour de la scène et à l’enregistrement des commandes : un traitement CPU prolongé à cet endroit retarde aussi l’interface." +concepts.platforms.ownership.title: "Responsabilités de l’application et du contrôle" +concepts.platforms.surface.description: "Le {link} utilise Silk.NET pour créer la fenêtre et traiter ses événements. Zenith.NET reçoit les handles natifs et les dimensions dans une description {surface}, à partir de laquelle il crée une {swapChain}. L’application reste responsable de la fenêtre du système d’exploitation." +concepts.platforms.surface.description.link: "tutoriel du triangle" +concepts.platforms.surface.details: "Les handles natifs doivent correspondre au backend :" +concepts.platforms.surface.guidance: "L’hôte des exemples dans {appCs} prend en charge Windows, macOS et X11. Sous Linux, sa fenêtre fournit des handles Xlib ; une session Wayland doit donc disposer de XWayland pour l’exécuter. Une application Wayland native transmet ses handles de display et de surface via {surfaceWayland}." concepts.platforms.surface.table.android.backend: Vulkan sous Android. concepts.platforms.surface.table.apple.backend: Metal sur les plateformes Apple. -concepts.platforms.surface.table.headings.backend: Chemin de backend +concepts.platforms.surface.table.headings.backend: "Backend et plateforme" concepts.platforms.surface.table.headings.factory: Fabrique de surface concepts.platforms.surface.table.headings.handles: Handles fournis par l’hôte concepts.platforms.surface.table.wayland.backend: Vulkan avec un hôte Wayland natif. @@ -94,18 +93,18 @@ concepts.platforms.surface.table.wayland.handles: Affichage et surface Wayland concepts.platforms.surface.table.win32.backend: DirectX 12 ou Vulkan sous Windows. concepts.platforms.surface.table.xlib.backend: Vulkan sous Linux avec X11 ou XWayland. concepts.platforms.surface.table.xlib.handles: Affichage et fenêtre X11 -concepts.platforms.surface.title: Fournir une surface native lorsque l’application possède la présentation +concepts.platforms.surface.title: "Surfaces de présentation natives" concepts.platforms.title: Intégration de plateforme -concepts.resources.allocation.context: "Commencez par des ressources créées via le contexte, sauf si vous avez besoin de votre propre allocateur. Avec un tas, attendez la fin de tous les travaux GPU utilisant ses ressources, puis libérez les ressources placées avant de libérer le tas lui-même." -concepts.resources.allocation.description: "Un {heap} fournit de la mémoire dans laquelle vous placez les ressources à des décalages explicites en octets. L’application choisit ces décalages et suit les régions utilisées." -concepts.resources.allocation.details: "Avant de placer une ressource, utilisez {contextGetSizeAndAlignment} avec sa description exacte de tampon ou de texture. Choisissez un décalage multiple de l’alignement renvoyé, réservez la taille renvoyée et gardez la ressource dans les limites de la taille totale du tas. Les allocations encore utilisées ne doivent pas se chevaucher. Le stockage d’une texture peut inclure du remplissage et un alignement propres au backend ; multiplier le nombre de pixels par le nombre d’octets par pixel ne donne donc pas la taille de l’allocation." -concepts.resources.allocation.guidance: "Pour les tampons placés, faites correspondre la résidence du tampon à celle du tas. Utilisez des tas réservés au GPU pour les textures GPU ordinaires décrites ici. La taille et l’alignement sont des exigences de placement ; ils ne garantissent pas que toute ressource puisse être placée dans n’importe quel tas sur tous les backends." -concepts.resources.allocation.title: Placer des ressources dans un tas lorsqu’un contrôle d’allocation est requis +concepts.resources.allocation.context: "Les ressources placées dans un tas dépendent de sa mémoire pendant toute leur durée de vie. Après leur dernière utilisation par le GPU, libérer les ressources avant de libérer le tas." +concepts.resources.allocation.description: "Un {heap} permet à l’application de gérer elle-même les allocations. Il fournit une mémoire où placer les ressources à des décalages explicites en octets. L’application choisit ces emplacements et suit les régions occupées." +concepts.resources.allocation.details: "Pour chaque ressource, appeler {contextGetSizeAndAlignment} avec la description de tampon ou de texture qui servira à sa création. Réserver la taille renvoyée à un décalage multiple de l’alignement demandé, dans les limites du tas et sans chevaucher une allocation encore active. La taille d’une texture peut inclure du remplissage propre au backend ; le nombre de pixels et le nombre d’octets par pixel ne suffisent donc pas à calculer la taille de son allocation." +concepts.resources.allocation.guidance: "Un tampon placé dans un tas doit déclarer la même résidence que ce tas. Pour les textures, utiliser un tas destiné exclusivement au GPU." +concepts.resources.allocation.title: "Allocation dans un tas" concepts.resources.bufferUsages.table.constant.role: Paramètres de shader lus via une liaison de tampon de constantes. concepts.resources.bufferUsages.table.headings.role: "Rôle" concepts.resources.bufferUsages.table.headings.usage: Usage concepts.resources.bufferUsages.table.index.role: Indices utilisés par le dessin indexé. -concepts.resources.bufferUsages.table.indirect.role: "Arguments lus par les commandes de dessin ou de dispatch indirects." +concepts.resources.bufferUsages.table.indirect.role: "Arguments lus par les commandes de dessin indirect ou de lancement indirect de calcul." concepts.resources.bufferUsages.table.none.role: "Aucun indicateur d’usage du tampon n’est déclaré." concepts.resources.bufferUsages.table.storageReadOnly.role: "Données de tampon accessibles via une liaison de shader en lecture seule." concepts.resources.bufferUsages.table.storageReadWrite.role: "Données de tampon accessibles via une liaison de shader en lecture et écriture." @@ -113,24 +112,24 @@ concepts.resources.bufferUsages.table.transferDst.role: "Stockage de destination concepts.resources.bufferUsages.table.transferSrc.role: "Données sources d’une copie GPU." concepts.resources.bufferUsages.table.vertex.role: Attributs de sommets récupérés pour le dessin. concepts.resources.bufferUsages.title: Usages de tampon -concepts.resources.description: "Choisissez la description d’une ressource selon les opérations qui l’utiliseront. Une texture qui reçoit un rendu, est échantillonnée par un shader et est relue par le CPU doit déclarer ces trois usages et assurer leur synchronisation. Le placement mémoire et la durée de vie de la ressource sont des décisions supplémentaires." -concepts.resources.memory.context: Pour un tampon accessible par le CPU, {map} fournit une adresse au CPU. Il n’attend pas que le GPU cesse d’accéder aux mêmes octets. {unmap} de même ne soumet aucun travail et n’attend pas l’achèvement. Avant d’écraser des données accessibles en écriture par le CPU, terminez les lectures GPU qui ont encore besoin de leur ancien contenu. -concepts.resources.memory.description: "Un {bufferDesc} possède un champ {residency}. Choisissez-le selon la manière dont le CPU et le GPU accèdent aux données :" -concepts.resources.memory.details: La résidence décrit l’accès CPU prévu à l’allocation. Elle n’implique pas que chaque périphérique dispose d’une mémoire physique CPU et GPU séparée. Le triangle utilise {cpuWriteOnly} pour initialiser directement un petit tampon de sommets. Un grand maillage statique peut plutôt bénéficier d’un stockage réservé au GPU avec un transfert unique. -concepts.resources.memory.guidance: "{textureDesc} ne possède aucun champ de résidence. Les textures ordinaires créées par le contexte utilisent un stockage GPU. Leur API publique fournit des opérations de transfert et de lecture pour les transferts de données CPU, sans exposer de méthode de mappage direct. Les tas explicites fournissent un contrôle de placement, décrit ci-dessous." -concepts.resources.memory.table.cpuReadOnly.cPUAccess: "Lire la mémoire mappée après la fin de la copie GPU." +concepts.resources.description: "La description d’une ressource définit les usages autorisés de sa mémoire. Par exemple, une texture servant de cible de rendu, échantillonnée par un shader et recopiée vers le CPU doit déclarer les indicateurs d’usage correspondant aux trois opérations. Le placement mémoire détermine l’accès CPU ; la synchronisation et la gestion de la durée de vie déterminent quand accéder aux données ou libérer la mémoire." +concepts.resources.memory.context: "Pour les tampons accessibles au CPU, {map} fournit l’adresse à laquelle lire ou écrire les données. Ni le mapping ni {unmap} n’attendent le travail du GPU. L’application doit attendre la fin d’une écriture GPU avant d’en lire le résultat, et la fin des accès GPU en cours avant de modifier les mêmes octets." +concepts.resources.memory.description: "Le champ {residency} de {bufferDesc} précise l’accès CPU prévu à l’allocation :" +concepts.resources.memory.details: "La résidence exprime les besoins d’accès du CPU, y compris lorsque CPU et GPU partagent la même mémoire physique. Le triangle utilise {cpuWriteOnly} pour initialiser directement son petit tampon de sommets. Pour une géométrie statique plus volumineuse, un transfert vers une mémoire destinée exclusivement au GPU peut être plus adapté." +concepts.resources.memory.guidance: "Les textures créées directement par le contexte utilisent de la mémoire GPU. {textureDesc} ne comporte donc pas de champ de résidence. L’application échange leurs données avec la mémoire CPU au moyen de transferts vers et depuis le GPU." +concepts.resources.memory.table.cpuReadOnly.cPUAccess: "Lecture seule" concepts.resources.memory.table.cpuReadOnly.typicalRole: "Données produites par le GPU pour être relues par le CPU" -concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "Écrire dans la mémoire mappée après la fin des lectures GPU précédentes." +concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "Écriture seule" concepts.resources.memory.table.cpuWriteOnly.typicalRole: "Données fournies ou mises à jour par le CPU" -concepts.resources.memory.table.gpuOnly.cPUAccess: "Transférer les octets via un tampon de transfert vers le GPU ou de lecture depuis le GPU." +concepts.resources.memory.table.gpuOnly.cPUAccess: "Aucun" concepts.resources.memory.table.gpuOnly.typicalRole: "Géométrie statique et données de travail du GPU" -concepts.resources.memory.table.headings.cPUAccess: Accès CPU +concepts.resources.memory.table.headings.cPUAccess: "Accès CPU prévu" concepts.resources.memory.table.headings.residency: Résidence concepts.resources.memory.table.headings.typicalRole: Rôle typique -concepts.resources.memory.title: "Choisir la mémoire selon l’accès CPU nécessaire" -concepts.resources.textureUsages.description: "Les indicateurs d’usage de transfert décrivent le sens des copies GPU. L’accès CPU relève d’un choix distinct de placement mémoire, décrit plus bas." -concepts.resources.textureUsages.details: "Combiner des indicateurs d’usage déclare plusieurs rôles ; cela n’exécute pas les opérations et n’ordonne pas leurs accès. Les textures nécessitent toujours des choix adaptés de {link}, et leurs formats doivent prendre en charge les usages demandés sur le périphérique choisi." -concepts.resources.textureUsages.details.link: "layout et de synchronisation" +concepts.resources.memory.title: "Accès CPU et placement mémoire" +concepts.resources.textureUsages.description: "Les indicateurs de transfert précisent si la ressource sert de source ou de destination d’une copie GPU. La possibilité pour le CPU d’accéder directement à sa mémoire relève d’un choix distinct : le placement mémoire." +concepts.resources.textureUsages.details: "Les indicateurs d’usage déclarent les rôles possibles d’une texture. Le passage d’un rôle à un autre doit respecter les exigences de {link}. Le périphérique doit également prendre en charge les usages demandés pour le format choisi." +concepts.resources.textureUsages.details.link: "layout et synchronisation" concepts.resources.textureUsages.table.colorAttachment.role: "Un attachement de couleur dans une passe de rendu." concepts.resources.textureUsages.table.depthStencilAttachment.role: "Un attachement de profondeur et de stencil dans une passe de rendu." concepts.resources.textureUsages.table.headings.role: "Rôle" @@ -142,225 +141,220 @@ concepts.resources.textureUsages.table.transferDst.role: "Stockage de l’image concepts.resources.textureUsages.table.transferSrc.role: "Données de l’image source d’une copie GPU." concepts.resources.textureUsages.title: Usages de texture concepts.resources.title: Gestion des ressources -concepts.resources.transfers.context: Un téléchargement enregistre une copie GPU dans un stockage interne de lecture. La bibliothèque copie ces octets dans la destination CPU fournie lorsqu’elle réinitialise le tampon de commandes terminé pour le réutiliser. Gardez la destination allouée, et gardez la mémoire managée épinglée, jusqu’à ce que le {wait} de la valeur de soumission revienne. -concepts.resources.transfers.description: "Un transfert vers le GPU copie les données CPU dans une ressource GPU ; une lecture depuis le GPU ramène les données de la ressource en mémoire CPU. Les méthodes de la ressource terminent ce transfert avant de rendre la main :" -concepts.resources.transfers.details: "Ces attentes couvrent uniquement le transfert soumis par ces méthodes. Elles ne détectent pas les dépendances envers une autre file qui lisait ou écrivait déjà la ressource. Établissez ces dépendances avant d’appeler la méthode de la ressource. Une copie directe via la mémoire mappée exige elle aussi que l’appelant s’assure de l’achèvement du travail GPU concerné." -concepts.resources.transfers.guidance: "Utilisez {commandBufferUpload} ou {commandBufferDownload} lorsque les copies doivent être enregistrées avec d’autres travaux. Les durées de vie de leurs pointeurs diffèrent :" -concepts.resources.transfers.item: "Un transfert vers le GPU copie les données sources du CPU dans un tampon interne de transfert, également appelé mémoire intermédiaire ou staging, pendant l’appel. Le pointeur source doit rester valide uniquement pendant cet appel." -concepts.resources.transfers.notes: "Pour une texture, le pas de ligne est la distance en octets entre deux lignes successives de données CPU ; le pas de tranche est la distance en octets entre deux tranches de profondeur successives. Ils ne décrivent pas l’organisation interne de la texture en mémoire GPU. Consultez {link} pour distinguer l’achèvement GPU de la disponibilité des données relues." +concepts.resources.transfers.context: "Un transfert depuis le GPU copie d’abord les données dans une mémoire de lecture interne. La bibliothèque les copie ensuite vers la destination CPU fournie lorsqu’elle récupère le tampon de commandes terminé. Appeler {wait} sur la valeur de soumission de ce transfert achève les deux étapes. Jusqu’au retour de cet appel, conserver la mémoire de destination et maintenir épinglée toute mémoire managée utilisée." +concepts.resources.transfers.description: "Les transferts vers le GPU copient des données CPU dans une ressource ; les transferts depuis le GPU copient les données d’une ressource en mémoire CPU. Les méthodes des tampons et des textures terminent ce transfert avant de retourner :" +concepts.resources.transfers.details: "Avant ces appels, résoudre les conflits d’accès avec les autres files. L’attente effectuée dans une méthode ne couvre que son propre transfert ; elle n’établit pas de dépendance avec une autre file. Pour les chemins qui accèdent directement à la mémoire mappée, il revient entièrement à l’appelant d’attendre les accès GPU en conflit." +concepts.resources.transfers.guidance: "Pour soumettre des transferts avec d’autres opérations GPU, les enregistrer avec {commandBufferUpload} ou {commandBufferDownload}. La mémoire source d’un transfert vers le GPU et la mémoire de destination d’un transfert depuis le GPU ont des exigences de durée de vie différentes :" +concepts.resources.transfers.item: "Pendant l’appel de transfert vers le GPU, la bibliothèque copie les données source dans une mémoire de transfert temporaire. Le GPU lit ensuite cette copie intermédiaire. Le pointeur source de l’application n’est donc nécessaire que jusqu’au retour de l’appel." +concepts.resources.transfers.notes: "Pour les transferts de texture, le pas de ligne est la distance en octets entre deux lignes successives des données CPU ; le pas de tranche est la distance entre deux tranches de profondeur. Ces valeurs permettent de copier les données entre la mémoire CPU et la texture GPU. L’article {link} explique pourquoi l’achèvement sur le GPU et la copie vers la destination CPU sont deux étapes distinctes." concepts.resources.transfers.notes.link: Synchronisation -concepts.resources.transfers.table.bufferDownload.transfer: Copie directe du CPU pour {cpuReadOnly} ; sinon, soumet un téléchargement sur la file de transfert et attend. -concepts.resources.transfers.table.bufferUpload.transfer: Copie directe du CPU pour {cpuWriteOnly} ; sinon, soumet un transfert sur la file de transfert et attend. +concepts.resources.transfers.table.bufferDownload.transfer: "Copie directement depuis la mémoire mappée pour {cpuReadOnly}. Sinon, soumet le transfert à la file de transfert et attend qu’il soit terminé." +concepts.resources.transfers.table.bufferUpload.transfer: "Copie directement dans la mémoire mappée pour {cpuWriteOnly}. Sinon, soumet le transfert à la file de transfert et attend qu’il soit terminé." concepts.resources.transfers.table.headings.method: Méthode -concepts.resources.transfers.table.headings.transfer: "Mode de transfert des données" +concepts.resources.transfers.table.headings.transfer: "Comportement du transfert" concepts.resources.transfers.table.textureTransfers.method: "{textureUpload} / {textureDownload}" -concepts.resources.transfers.table.textureTransfers.transfer: "Utilise la file graphique, fait passer la sous-ressource sélectionnée au layout nécessaire à la copie, puis au layout final demandé, et attend la fin du transfert." -concepts.resources.transfers.title: "Choisir entre transferts immédiats et transferts enregistrés" -concepts.resources.usages.description: "{bufferUsages} et {textureUsages} sont des énumérations d’indicateurs qui déclarent les rôles prévus d’une ressource. Ils sont affectés respectivement à {bufferDescUsages} et {textureDescUsages}. Une énumération d’indicateurs permet de combiner plusieurs membres avec {value} lorsqu’une ressource a plus d’un rôle." -concepts.resources.usages.title: Déclarer les usages requis avant de créer une ressource -concepts.resources.views.description: Une {bufferView} décrit une région de tampon et son interprétation. Une {textureView} sélectionne un type de texture compatible, un format et une plage de sous-ressources. Une vue partage le stockage sous-jacent ; elle ne copie pas les données et n’ajoute pas d’usages qui manquaient lors de la création de la ressource. Sa plage n’est pas non plus une garantie portable de vérification des limites dans le shader. -concepts.resources.views.details: "Utilisez le handle de la ressource pour sa vue par défaut, ou créez une vue si une autre région ou une interprétation compatible différente est nécessaire. Conservez les références C# vers la vue et sa ressource sous-jacente tant que des travaux GPU peuvent les utiliser ; un handle de ressource seul ne maintient aucun des deux objets en vie. Libérez-les uniquement après leur dernière utilisation GPU. Après avoir remplacé l’un des objets, mettez à jour les constantes contenant son ancien {link}." +concepts.resources.transfers.table.textureTransfers.transfer: "Soumet la copie et les transitions de texture à la file graphique, puis attend leur achèvement. La sous-ressource sélectionnée reste dans le layout final demandé." +concepts.resources.transfers.title: "Transferts immédiats et enregistrés" +concepts.resources.usages.description: "{bufferUsages} et {textureUsages} sont des énumérations d’indicateurs qui déclarent les usages d’une ressource. Leurs valeurs sont affectées à {bufferDescUsages} et {textureDescUsages}, respectivement. Plusieurs membres peuvent être combinés avec {value} pour déclarer plusieurs usages." +concepts.resources.usages.title: "Usages des ressources" +concepts.resources.views.description: "Une {bufferView} décrit une région de tampon et l’interprétation de ses données. Une {textureView} sélectionne une plage de sous-ressources, ainsi qu’un type de texture et un format compatibles. Toutes deux désignent une mémoire existante, avec les usages déclarés à sa création. Les plages des vues décrivent l’accès, mais n’offrent pas de contrôle des limites uniforme dans les shaders sur tous les backends." +concepts.resources.views.details: "Le handle propre à une ressource fournit sa vue par défaut. Créer une vue distincte pour sélectionner une autre région ou une autre interprétation compatible. La vue et sa ressource sous-jacente doivent rester disponibles jusqu’à la fin de leur utilisation par le GPU : un handle ne maintient aucun de ces objets en vie. Si l’un d’eux est remplacé, mettre à jour les constantes contenant l’ancien {link}." concepts.resources.views.details.link: "handle de ressource" -concepts.resources.views.guidance: Le {link} montre une texture de profondeur remplacée lors du redimensionnement. L’{detail} montre une texture d’entrée maintenue séparée de sa sortie accessible en écriture. Les deux font suivre la durée de vie de la ressource au travail qui l’utilise réellement. -concepts.resources.views.guidance.detail: exemple de calcul -concepts.resources.views.guidance.link: moteur de rendu du cube en rotation -concepts.resources.views.title: "Garder les vues et leurs ressources sous-jacentes utilisables ensemble" -concepts.shaders.binding.context: "Dans l’exemple de calcul, {input} est rempli avec {inputTextureSampledHandle} et {output} avec {outputTextureStorageHandle}. Le {descriptorHandle} typé de Slang indique au shader comment accéder à chaque ressource :" -concepts.shaders.binding.description: "{setConstantBuffer} lie un tampon et un décalage d’octets pour les données de constantes du pipeline actuel. Il lie un stockage existant visible par le GPU ; il ne transfère pas de valeur C#. Remplissez d’abord le tampon et assurez-vous que les lecteurs GPU antérieurs ont terminé avant d’écraser ses octets." -concepts.shaders.binding.details: "Définissez le pipeline avant son tampon de constantes. Pour une charge de travail de calcul avec des ressources déjà créées et transférées, l’enregistrement utilise cet ordre :" -concepts.shaders.binding.guidance: Ce fragment suppose un {commandBuffer} en cours d’enregistrement, un {computePipeline}, un {constantBuffer} transféré avec l’usage {bufferUsagesConstant} et les nombres de groupes de threads pour la charge de travail. Le décalage 0 lie le début du tampon. Si plusieurs enregistrements de données de constantes partagent un même tampon, le décalage de départ de chaque enregistrement doit respecter l’alignement de liaison du backend. Cette exigence est distincte de l’agencement des champs à l’intérieur de l’enregistrement. -concepts.shaders.binding.notes: "{resourceHandle} stocke deux champs de 32 bits, mais son interprétation appartient au backend. Ne le traitez pas comme un index de descripteur universel, une adresse ou une valeur pouvant être transférée entre contextes. Un handle ne crée pas de ressource, n’ajoute pas d’usage manquant et n’effectue aucune synchronisation." -concepts.shaders.binding.reference: Conservez des références à la ressource et à toute vue utilisée pour obtenir son handle, et libérez-les uniquement après la fin de la dernière utilisation par le shader. Lors du remplacement d’une texture ou d’une vue, mettez à jour les constantes qui contiennent son ancien handle. {link} explique cette relation de durée de vie. +concepts.resources.views.title: "Vues et ressources sous-jacentes" +concepts.shaders.binding.context: "L’exemple de calcul affecte {inputTextureSampledHandle} à {input} et {outputTextureStorageHandle} à {output}. En Slang, le paramètre de type de {descriptorHandle} définit l’accès à la ressource :" +concepts.shaders.binding.description: "{setConstantBuffer} sélectionne un tampon existant et le décalage en octets à partir duquel le pipeline courant lit ses constantes. Transférer les paramètres dans cette mémoire avant leur utilisation par le shader. Si un travail GPU antérieur lit encore les mêmes octets, attendre sa fin avant de les mettre à jour." +concepts.shaders.binding.details: "Préparer le tampon de commandes, le pipeline de calcul, le tampon de constantes rempli et le nombre de groupes de threads. Enregistrer ensuite le calcul dans l’ordre ci-dessous. Sélectionner d’abord le pipeline, car la liaison du tampon de constantes s’applique à ce pipeline :" +concepts.shaders.binding.guidance: "Ici, {commandBuffer} enregistre un calcul avec {computePipeline} et les paramètres de {constantBuffer}. Le tampon doit déclarer l’usage {bufferUsagesConstant} ; le décalage 0 sélectionne son début. Si plusieurs enregistrements de constantes partagent un tampon, le décalage de chacun doit aussi respecter l’alignement de liaison du backend, indépendamment de la disposition des champs à l’intérieur de l’enregistrement." +concepts.shaders.binding.notes: "{resourceHandle} contient deux champs de 32 bits dont l’interprétation dépend du backend. Leurs valeurs ne sont valables que dans le contexte où la ressource a été créée." +concepts.shaders.binding.reference: "Conserver la ressource et toute vue utilisée pour obtenir son handle jusqu’à la fin du dernier accès du shader. Lorsqu’une texture ou une vue est remplacée, mettre à jour les constantes contenant encore son ancien handle. Les règles de propriété sont détaillées dans {link}." concepts.shaders.binding.reference.link: Gestion des ressources -concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: Lire des éléments structurés du type de shader {t}. -concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: Lire ou écrire des éléments structurés du type de shader {t}. +concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: "Lecture d’éléments structurés de type {t} dans le shader" +concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: "Lecture et écriture d’éléments structurés de type {t} dans le shader" concepts.shaders.binding.table.headings.access: Accès prévu concepts.shaders.binding.table.headings.cHandle: "Handle C#" concepts.shaders.binding.table.headings.slangFieldType: Type de champ Slang -concepts.shaders.binding.table.samplerHandle.access: Fournir l’état d’échantillonnage de texture. -concepts.shaders.binding.table.textureSampledHandle.access: Lire une texture. -concepts.shaders.binding.table.textureStorageHandle.access: Lire ou écrire une texture de stockage. -concepts.shaders.binding.title: Lier le tampon de constantes et les ressources qu’il décrit -concepts.shaders.compilation.description: "{zenithCompiler} compile un point d’entrée Slang nommé et renvoie un {shaderDesc}. Utilisez le {graphicsApi} du contexte afin que le résultat cible le backend qui créera le shader : DXIL pour DirectX 12, une bibliothèque Metal pour Metal ou SPIR-V pour Vulkan." -concepts.shaders.compilation.details: "Par exemple, avec un {context} existant et le shader du triangle copié à côté de l’exécutable :" -concepts.shaders.compilation.guidance: "{vSMain} doit correspondre exactement au nom du point d’entrée dans le fichier de shader. Gardez les objets de shader valides lors de la création du pipeline, puis libérez-les après la création du pipeline, comme indiqué dans {link}. Effectuez cette initialisation une seule fois plutôt que de recompiler à chaque image." +concepts.shaders.binding.table.samplerHandle.access: "État d’échantillonnage des textures" +concepts.shaders.binding.table.textureSampledHandle.access: "Lecture de textures" +concepts.shaders.binding.table.textureStorageHandle.access: "Lecture et écriture de textures de stockage" +concepts.shaders.binding.title: "Constantes et handles de ressources" +concepts.shaders.compilation.description: "{zenithCompiler} compile un point d’entrée Slang en {shaderDesc}. {graphicsApi} détermine la cible : DXIL pour DirectX 12, bibliothèque Metal pour Metal, SPIR-V pour Vulkan." +concepts.shaders.compilation.details: "Avec un contexte graphique nommé {context} déjà créé, compiler le shader du triangle à partir de la copie placée à côté de l’exécutable :" +concepts.shaders.compilation.guidance: "Le nom de point d’entrée {vSMain} doit correspondre à la déclaration dans le fichier de shader. Compiler les shaders et créer les pipelines à l’initialisation, puis réutiliser les pipelines pendant le rendu. Les objets shader peuvent être libérés une fois le pipeline créé, comme dans le tutoriel {link}." concepts.shaders.compilation.guidance.link: Premier triangle -concepts.shaders.compilation.title: Compiler un point d’entrée pour le contexte sélectionné -concepts.shaders.description: "Un shader reçoit des données fournies par l’application. Les attributs de sommets décrivent des sommets individuels ; les tampons contiennent des paramètres ou des tableaux ; les handles de ressources identifient d’autres ressources auxquelles le shader accédera. Les déclarations C# et les déclarations Slang doivent s’accorder sur la signification de ces valeurs. Faire correspondre un nom de champ ne suffit pas : l’agencement, l’accès aux ressources et la liaison doivent tous concorder." -concepts.shaders.dispatch.description: "{dispatch} prend le nombre de groupes de threads. Le point d’entrée {numthreads} de l’exemple de calcul exécute 16 × 16 threads par groupe. Divisez les dimensions de l’image par 16 et arrondissez au supérieur pour trouver le nombre de groupes. Par exemple, une image de 17 × 19 nécessite 2 × 2 groupes. Le shader vérifie ses coordonnées de pixel par rapport aux dimensions de l’image car les derniers groupes peuvent contenir des threads en dehors de l’image." -concepts.shaders.dispatch.details: Le compilateur stocke la taille de groupe déclarée du point d’entrée dans {shaderDescThreadGroupSize} ; il ne convertit pas les dimensions en pixels fournies à {dispatch} en nombres de groupes. Utilisez {computeShaderRendererCs} avec son shader pour l’exemple complet de liaison et de dispatch, et {link} avant qu’une autre passe ne consomme la sortie. +concepts.shaders.compilation.title: "Compilation des shaders" +concepts.shaders.description: "Les déclarations C# et Slang doivent s’accorder sur l’emplacement de chaque valeur et sur son accès par le shader. Les dispositions d’entrée décrivent les attributs de sommets ; les déclarations de tampons dans les shaders décrivent les paramètres et les tableaux ; les handles identifient les ressources utilisées par le shader." +concepts.shaders.dispatch.description: "{dispatch} indique le nombre de groupes de threads à exécuter. L’exemple de calcul déclare {numthreads} : chaque groupe contient donc 16 × 16 threads. Pour couvrir l’image, diviser sa largeur et sa hauteur par 16, puis arrondir chaque résultat à l’entier supérieur. Une image de 17 × 19 pixels demande ainsi 2 × 2 groupes. Le shader vérifie les coordonnées de chaque thread et ignore ceux qui sont hors de l’image." +concepts.shaders.dispatch.details: "La taille de groupe déclarée est disponible dans {shaderDescThreadGroupSize} et permet de calculer le nombre de groupes à transmettre à {dispatch}. Le calcul complet figure dans {computeShaderRendererCs}. Les accès ultérieurs à l’image produite doivent respecter les conditions décrites dans {link}." concepts.shaders.dispatch.details.link: Synchronisation -concepts.shaders.dispatch.title: Dispatcher des groupes de threads, pas des pixels -concepts.shaders.layout.context: "Les {link} rendent leurs décalages explicites. Cette déclaration nécessite {systemRuntimeInteropServices} et {zenithNET} dans la portée :" +concepts.shaders.dispatch.title: "Groupes de threads" +concepts.shaders.layout.context: "Les {link} illustrent cette organisation avec les dimensions de l’image et deux handles de textures. Des décalages explicites indiquent le début de chaque champ. La déclaration utilise {systemRuntimeInteropServices} et {zenithNET} :" concepts.shaders.layout.context.link: "constantes C# de l’exemple de calcul" -concepts.shaders.layout.description: "Pour l’entrée de sommets, l’{inputLayout} du pipeline décrit les formats, décalages, le stride et les sémantiques. La position {float3} du triangle suivie d’une couleur {float4} occupe 28 octets, la couleur étant à l’octet 12. {inputLayoutAdd} calcule cet agencement compacté ; il n’inspecte pas la structure C#. Si les champs C# contiennent du remplissage, fournissez un agencement correspondant au lieu de supposer que les champs sont compactés." -concepts.shaders.layout.details: "Les tampons de constantes contiennent des paramètres de shader, tandis que les tampons structurés contiennent des tableaux d’éléments d’un type déclaré. Tous deux sont lus conformément à leurs déclarations Slang. Ils n’utilisent pas {inputLayout}. Vérifiez les décalages de champs et les tailles d’éléments pour la représentation compilée du shader, y compris le remplissage. Un type C# non managé est adapté pour être copié en tant qu’octets, mais cela ne prouve pas à lui seul qu’il correspond à un type de shader. En particulier, n’appliquez pas l’agencement {float3} étroitement compacté d’un sommet à chaque tampon de shader." -concepts.shaders.layout.guidance: Un handle de ressource est une petite valeur qui fait référence à une ressource existante. Copier le handle dans un tampon de constantes ne copie pas le contenu de la ressource. +concepts.shaders.layout.description: "Pour les sommets, {inputLayout} décrit le format, le décalage et la sémantique de chaque attribut, ainsi que le pas entre sommets. Dans le triangle, une position {float3} précède une couleur {float4} : la couleur commence au décalage de 12 octets et chaque sommet occupe 28 octets. {inputLayoutAdd} calcule cette disposition compacte à partir des formats des éléments. Si la structure C# contient du remplissage, les décalages et le pas doivent en tenir compte." +concepts.shaders.layout.details: "Les tampons de constantes contiennent des paramètres de shader, et les tampons structurés des tableaux d’éléments typés. Leur disposition suit les déclarations Slang, et non {inputLayout}. Les décalages des champs C#, les tailles des éléments et le remplissage doivent correspondre à la disposition mémoire du shader compilé. Un type C# non managé peut être copié sous forme d’octets, mais sa disposition mémoire ne correspond pas nécessairement à celle attendue par le shader : un {float3} compact dans un sommet peut nécessiter un autre alignement dans un tampon de shader." +concepts.shaders.layout.guidance: "Les paramètres de shader peuvent contenir des handles de ressources en plus des valeurs ordinaires. Un handle désigne une mémoire déjà allouée : le copier dans un tampon de constantes ne copie donc pas le contenu de la ressource." concepts.shaders.layout.notes: "La déclaration correspondante dans {computeShaderSlang} est :" -concepts.shaders.layout.reference: "Les dimensions occupent les huit premiers octets, suivies de deux handles de ressources de huit octets. L’exemple C# réserve 256 octets au total. Cette taille est la taille de stockage choisie par l’exemple, et non une règle selon laquelle toutes les structures Slang ou charges utiles de constantes occuperaient 256 octets. Remplir la taille totale ne corrige pas non plus un champ au mauvais décalage." -concepts.shaders.layout.title: L’entrée de sommets et les données de shaders ont des règles d’agencement différentes -concepts.shaders.matrices.description: "Le compilateur demande un stockage des matrices par lignes (row-major), où les éléments de chaque ligne sont contigus. Le {link} place trois valeurs {matrix4x4} aux décalages 0, 64 et 128. Son {detail} utilise {mulVectorMatrix} dans l’ordre modèle, vue et projection." +concepts.shaders.layout.reference: "Les deux dimensions occupent les huit premiers octets, suivis de deux handles de huit octets chacun. L’exemple C# réserve 256 octets pour l’ensemble de l’enregistrement. Pour un autre enregistrement, déterminer la taille à partir de ses propres champs et des contraintes de disposition et d’alignement." +concepts.shaders.layout.title: "Disposition des données" +concepts.shaders.matrices.description: "Le compilateur choisit un stockage des matrices par lignes contiguës. Le {link} place trois valeurs {matrix4x4} aux décalages de 0, 64 et 128 octets. Son {detail} applique {mulVectorMatrix} dans l’ordre modèle, vue et projection." concepts.shaders.matrices.description.detail: shader concepts.shaders.matrices.description.link: moteur de rendu du cube en rotation -concepts.shaders.matrices.details: L’ordre de stockage détermine la façon dont les éléments de la matrice occupent la mémoire ; l’ordre de multiplication détermine la transformation. Maintenez les deux côtés cohérents. Ajouter une transposition sans vérifier ces deux choix peut masquer une incohérence tout en en introduisant une autre. -concepts.shaders.matrices.title: Maintenir cohérents le stockage et la multiplication des matrices +concepts.shaders.matrices.details: "L’ordre de stockage définit la disposition des éléments de matrice en mémoire ; l’ordre de multiplication définit la transformation. Les conventions C# et Slang doivent correspondre." +concepts.shaders.matrices.title: "Conventions matricielles" concepts.shaders.title: Données de shaders et liaison -concepts.synchronization.backends.description: DirectX 12 et Vulkan encodent les transitions de texture avec des informations de layout et d’accès. Metal n’a aucune opération dans l’implémentation de {transition} de Zenith.NET. Metal regroupe le travail enregistré dans des encodeurs de rendu et de calcul. Le backend insère des barrières de visibilité lorsqu’il termine ces groupes, rendant les écritures antérieures disponibles pour le travail ultérieur. Des appels explicites à {barrier} gèrent des dépendances telles que des dispatches de calcul successifs au sein du même encodeur. -concepts.synchronization.backends.details: Cette distinction est importante lors de la modification d’une charge de travail. Dans l’{link}, le dispatch est suivi d’une passe de rendu graphique, ce qui crée également une limite d’encodeur sur Metal. Deux dispatches de calcul dépendants ne créent pas cette limite simplement en modifiant le layout déclaré de la texture. Conservez les transitions requises par l’API partagée et identifiez séparément la dépendance entre les commandes réelles de production et de consommation. +concepts.synchronization.backends.description: "DirectX 12 et Vulkan encodent les transitions de texture sous forme de changements de layout et d’accès. L’implémentation de {transition} dans Zenith.NET n’effectue pas d’opération équivalente sur Metal. Le backend Metal regroupe les commandes dans des encodeurs de rendu et de calcul, puis insère des barrières de visibilité à la fermeture d’un encodeur. Les opérations dépendantes dans un même encodeur, comme deux calculs successifs, utilisent des appels explicites à {barrier}." +concepts.synchronization.backends.details: "Dans l’{link}, l’ouverture de la passe de rendu ferme l’encodeur de calcul et rend sa sortie visible aux commandes graphiques. Deux calculs successifs restent en revanche dans le même encodeur. Leur dépendance exige donc une barrière, même si une transition de texture est enregistrée entre eux. Les séquences de commandes portables doivent ainsi tenir compte des dépendances d’accès autant que des layouts de texture." concepts.synchronization.backends.details.link: exemple de calcul -concepts.synchronization.backends.title: Une transition n’est pas identique sur chaque backend -concepts.synchronization.barriers.context: "{barrierStagesAll} est une portée plus large, pas un détecteur automatique de dépendances. Sélectionnez des étapes qui couvrent réellement le travail et utilisez-les uniquement sur une file qui prend en charge ces opérations." -concepts.synchronization.barriers.description: "Considérez deux dispatches de calcul : le premier écrit des données de simulation et le second lit ces données pour effectuer l’étape suivante. Les deux utilisent des tampons de stockage, il n’y a donc pas de layout de texture à modifier. Insérez ceci entre les dispatches sur leur tampon de commandes :" -concepts.synchronization.barriers.details: Le premier argument identifie l’étape productrice et le second l’étape consommatrice. La barrière établit la dépendance d’exécution et de mémoire correspondante sur le GPU. Le backend traduit ces étapes en ses règles d’exécution et d’accès mémoire. Cette barrière ne change pas le layout d’une texture et n’attend pas tout le travail sur le périphérique. -concepts.synchronization.barriers.guidance: "La {link} utilise ce modèle entre des dispatches dépendants. Placez la barrière là où se trouve la dépendance. Une barrière enregistrée après le consommateur ne peut pas ordonner ce consommateur après un producteur antérieur." +concepts.synchronization.backends.title: "Comportement des backends" +concepts.synchronization.barriers.context: "Choisir des étapes qui couvrent les accès concernés et sont prises en charge par la file. {barrierStagesAll} inclut toutes les étapes disponibles ; une sélection plus restreinte convient lorsque la dépendance ne concerne que certaines d’entre elles." +concepts.synchronization.barriers.description: "Considérons deux calculs enregistrés dans le même tampon de commandes : le premier écrit des données de simulation, le second les lit. Une barrière entre les deux garantit que le second voit les écritures achevées. Pour un tampon de stockage, elle ordonne les accès sans transition de layout de texture :" +concepts.synchronization.barriers.details: "Le premier argument indique les étapes qui ont produit les données ; le second indique celles qui vont les utiliser. Ensemble, ils décrivent l’ordre d’exécution et la visibilité mémoire nécessaires entre les deux calculs." +concepts.synchronization.barriers.guidance: "La {link} applique ce principe entre les étapes de simulation. Chaque barrière suit le calcul qui produit les données et précède celui qui les utilise." concepts.synchronization.barriers.guidance.link: simulation FluidTank -concepts.synchronization.barriers.title: Ordonner les commandes dépendantes avec une barrière -concepts.synchronization.dependencies.description: Pour chaque ressource partagée, identifiez l’opération qui y accède en premier, l’opération qui suit et si l’un des accès effectue une écriture. Lire les mêmes données deux fois ne nécessite aucun ordonnancement pour protéger leur contenu, bien que les changements de layout ou la présentation puissent imposer d’autres exigences. Une écriture suivie d’une lecture, une lecture suivie d’un écrasement ou deux écritures peuvent nécessiter une dépendance. -concepts.synchronization.dependencies.details: "Choisissez ensuite le mécanisme selon l’endroit où ces opérations s’exécutent :" -concepts.synchronization.dependencies.guidance: Ces mécanismes sont liés, mais ne sont pas interchangeables. La soumission de commandes dans l’ordre ne remplace pas chaque dépendance mémoire. Une attente de file ne déclare pas un nouveau layout de texture, et une barrière de commandes n’attend pas sur le thread CPU appelant. +concepts.synchronization.barriers.title: "Barrières de pipeline" +concepts.synchronization.dependencies.description: "Pour chaque ressource, repérer les accès qui portent sur les mêmes données. Si l’un d’eux écrit, préserver l’ordre requis entre eux. Deux lectures ne sont pas en conflit, même si les contraintes de layout et de présentation continuent de s’appliquer. Les mises à jour CPU et la libération des ressources doivent aussi attendre que le GPU ait fini d’utiliser la mémoire concernée." +concepts.synchronization.dependencies.details: "Le mécanisme dépend du lieu d’exécution des opérations :" +concepts.synchronization.dependencies.guidance: "Un traitement peut nécessiter plusieurs mécanismes. Une texture produite sur une autre file demande par exemple une dépendance entre soumissions et le layout adapté à son prochain usage. Ces opérations ne nécessitent de bloquer le CPU que si celui-ci doit lui-même accéder aux données ou libérer leur mémoire." concepts.synchronization.dependencies.table.cpuAccess.mechanism: Appeler {wait} sur la valeur d’achèvement pertinente. -concepts.synchronization.dependencies.table.cpuAccess.situation: Le CPU doit attendre avant d’accéder aux données ou de les libérer -concepts.synchronization.dependencies.table.crossQueue.mechanism: Passer sa {timelineValue} au {submit} du tampon de commandes consommateur. -concepts.synchronization.dependencies.table.crossQueue.situation: Une soumission sur une autre file produit les données +concepts.synchronization.dependencies.table.cpuAccess.situation: "Un accès CPU ou une libération de ressource dépend de la fin du travail GPU" +concepts.synchronization.dependencies.table.crossQueue.mechanism: "Transmettre la valeur {timelineValue} du producteur à l’appel {submit} du consommateur." +concepts.synchronization.dependencies.table.crossQueue.situation: "Une file utilise des données produites sur une autre file" concepts.synchronization.dependencies.table.headings.mechanism: Mécanisme concepts.synchronization.dependencies.table.headings.situation: Situation concepts.synchronization.dependencies.table.layoutChange.mechanism: "{commandBufferTransition} avec ses layouts précédent et suivant." concepts.synchronization.dependencies.table.layoutChange.situation: Une sous-ressource de texture modifie sa façon d’être utilisée concepts.synchronization.dependencies.table.pipelineStages.mechanism: "{commandBufferBarrier} avec les étapes productrice et consommatrice." concepts.synchronization.dependencies.table.pipelineStages.situation: Étapes GPU dépendantes dans un flux de commandes -concepts.synchronization.dependencies.title: Commencer par le producteur et le consommateur -concepts.synchronization.description: "Une commande qui lit des données écrites par une commande antérieure dépend de l’achèvement et de la visibilité de ces écritures. L’opération qui écrit est le producteur ; celle qui lit est le consommateur. Le CPU a aussi besoin d’un point d’achèvement avant de lire, d’écraser ou de libérer des données partagées. Zenith.NET fournit des barrières, des transitions de texture et des lignes de temps pour ces différentes dépendances." -concepts.synchronization.layouts.context: "{undefined} signifie que le contenu précédent n’a pas besoin d’être préservé. Il convient pour une nouvelle image ou un attachement qui sera entièrement effacé. Ce n’est pas un moyen d’éviter de suivre le layout d’une image dont le contenu sera chargé, échantillonné ou accumulé." -concepts.synchronization.layouts.description: "Les indicateurs d’usage décrivent les rôles pris en charge par une texture. {textureLayout} décrit comment une sous-ressource particulière sera accessible pour une opération. Une sous-ressource est un niveau mip et une couche de tableau sélectionnés. Changer son layout prépare cet accès ; cela ne convertit pas la texture en un format de pixel différent. Par exemple, l’exemple de calcul écrit une texture de sortie au layout {storage}, puis l’échantillonne dans une passe graphique. Entre ces usages, il enregistre :" -concepts.synchronization.layouts.details: Ce fragment suppose que {outputTexture} a été créée avec l’usage {sampledStorage} et que sa sous-ressource sélectionnée est au layout {storage}. {default} sélectionne le niveau mip 0 et la couche de tableau 0. L’opération ne fait pas la transition de chaque mip ou couche d’une texture. -concepts.synchronization.layouts.guidance: L’application fournit le layout précédent. {transition} ne maintient pas de suivi de layout visible par l’application et ne déduit pas cette valeur à partir de commandes antérieures. Suivez le layout partout où une ressource passe entre des étapes de rendu. -concepts.synchronization.layouts.title: Suivre le layout de chaque sous-ressource de texture -concepts.synchronization.readback.description: "{isCompleted} interroge uniquement si la ligne de temps du GPU a atteint une valeur. Il ne récupère pas lui-même les tampons de commandes et ne copie pas les téléchargements intermédiaires dans le pointeur de destination de l’application." -concepts.synchronization.readback.details: "{commandBufferDownload} enregistre d’abord une copie dans le stockage interne de lecture. Lorsque le tampon de commandes terminé est réinitialisé pour être réutilisé, le CPU copie les données vers le pointeur fourni. Gardez la destination valide et la mémoire managée épinglée jusqu’au retour de {wait} pour cette soumission de lecture. Lisez les données ou libérez la mémoire seulement ensuite. Attendre une soumission ultérieure d’une autre file n’interroge pas la file qui gère la lecture." -concepts.synchronization.readback.guidance: "Interroger {isCompleted} puis lire immédiatement la destination d’une lecture asynchrone ne suffit donc pas. Consultez {link} pour les chemins de copie directe et de transfert intermédiaire." +concepts.synchronization.dependencies.title: "Dépendances d’accès" +concepts.synchronization.description: "La synchronisation fixe l’ordre dans lequel les opérations accèdent aux données partagées et garantit que les suivantes voient les résultats dont elles ont besoin. Dans une dépendance entre écriture et lecture, l’opération qui écrit produit les données et celle qui lit les consomme. Les barrières et les transitions de texture coordonnent les accès GPU ; les lignes de temps relient les soumissions et permettent au CPU d’attendre la fin du travail GPU." +concepts.synchronization.layouts.context: "Utiliser {undefined} comme layout précédent lorsque le contenu peut être abandonné, par exemple pour une nouvelle image ou un attachement entièrement réinitialisé. Pour conserver le contenu afin de le charger, de l’échantillonner ou de l’accumuler, utiliser le layout de l’accès précédent." +concepts.synchronization.layouts.description: "Les indicateurs d’usage d’une texture déclarent ses rôles autorisés. {textureLayout} décrit l’accès à une sous-ressource à un moment donné de la séquence de commandes. Cette sous-ressource est identifiée par un niveau de mip et une couche de tableau. Lorsque l’accès change, enregistrer une transition. Par exemple, l’exemple de calcul écrit sa texture de sortie dans le layout {storage}, puis la prépare à être échantillonnée dans une passe graphique :" +concepts.synchronization.layouts.details: "{outputTexture} a l’usage {sampledStorage}, et la sous-ressource retenue est en {storage}. {default} sélectionne le niveau mip 0 et la couche 0. Les autres niveaux et couches ne sont pas modifiés." +concepts.synchronization.layouts.guidance: "Pour {transition}, fournir le layout de l’utilisation précédente de la sous-ressource. L’application suit cet état lorsqu’elle enregistre les commandes et transmet les textures entre étapes de rendu." +concepts.synchronization.layouts.title: "Layouts de texture" +concepts.synchronization.readback.description: "{isCompleted} indique la fin du travail GPU. Un transfert enregistré depuis le GPU comporte une étape supplémentaire : copier les données de la mémoire de lecture interne vers la destination de l’application." +concepts.synchronization.readback.details: "{commandBufferDownload} enregistre la copie GPU vers cette mémoire interne. Après la fin de la soumission, la bibliothèque effectue la copie CPU lorsqu’elle récupère le tampon de commandes terminé. Appeler {wait} sur la valeur de soumission de ce transfert attend le GPU et traite les tampons terminés de cette file, ce qui achève les deux étapes. Conserver la mémoire de destination et maintenir épinglée toute mémoire managée jusqu’au retour de l’appel." +concepts.synchronization.readback.guidance: "Interroger seulement {isCompleted} n’effectue pas la copie CPU finale. Attendre une autre file ne récupère pas non plus les tampons terminés de la file responsable du transfert. L’article {link} explique quand les transferts utilisent un accès direct à la mémoire ou un stockage intermédiaire." concepts.synchronization.readback.guidance.link: Gestion des ressources -concepts.synchronization.readback.title: L’achèvement GPU et les données CPU téléchargées sont des étapes distinctes -concepts.synchronization.reuse.description: Pour un premier moteur de rendu, une attente immédiate après chaque image est simple. Pour faire chevaucher le travail, donnez aux images en cours des données modifiables distinctes et conservez la valeur d’achèvement de l’utilisation finale de chaque image. Avant de mettre à jour un tampon de constantes, de remplacer une texture ou de libérer un pipeline, terminez chaque accès en attente à la ressource affectée. -concepts.synchronization.reuse.details: Lors d’un redimensionnement ou d’un arrêt, arrêtez les nouvelles utilisations avant d’attendre les anciennes. {swapChainResize}, la libération de ressources et la libération du contexte ne servent pas d’attentes générales pour le travail de l’application. Le triangle peut redimensionner en toute sécurité entre les rappels car chaque image précédente a déjà terminé sa soumission. -concepts.synchronization.reuse.guidance: Le {swapChainPresent} actuel signale et attend également sur la file graphique après son opération de présentation. La suppression de l’attente de soumission explicite du triangle n’établit donc pas à elle seule une boucle de présentation avec chevauchement. Une attente sur la file graphique ne dit rien non plus sur le travail indépendant qui s’exécute encore sur une autre file. -concepts.synchronization.reuse.title: Ne réutiliser les données qu’après leur accès final -concepts.synchronization.timelines.context: "Avant que le CPU ne lise, n’écrase ou ne libère ces ressources, attendez leur utilisation finale :" -concepts.synchronization.timelines.description: Une ligne de temps suit l’achèvement sur une file à l’aide de valeurs croissantes. {submit} renvoie une {timelineValue} contenant cette ligne de temps et la valeur associée à la soumission. Les valeurs d’achèvement de différentes lignes de temps ne sont pas comparables uniquement par leurs champs numériques {value}. -concepts.synchronization.timelines.details: "Supposons que {producer} et {consumer} sont des tampons de commandes déjà enregistrés provenant de deux files du même contexte. Le producteur écrit des données que le consommateur utilise. Soumettez-les comme ceci :" -concepts.synchronization.timelines.guidance: Passer la valeur produite amène la file consommatrice à l’attendre sur le GPU. Le CPU n’appelle pas {producedWait} ici. Gardez les ressources partagées valides jusqu’à ce que {consumed} soit terminé, et enregistrez tous les changements de layout de texture requis par le consommateur. -concepts.synchronization.timelines.notes: "{wait} attend cette valeur de ligne de temps, puis vérifie les soumissions terminées sur la file propriétaire. Les tampons de commandes terminés sont réinitialisés pour être réutilisés, et leurs téléchargements intermédiaires sont copiés dans les destinations CPU fournies. {queueTimelineSignal} peut également mettre en file d’attente un point d’achèvement après un travail déjà soumis à cette file. Appeler {signal} ne signifie pas que le GPU a déjà atteint ce point." -concepts.synchronization.timelines.title: Utiliser une ligne de temps pour l’achèvement et les transferts de files +concepts.synchronization.readback.title: "Achèvement de la lecture CPU" +concepts.synchronization.reuse.description: "Le triangle attend la fin de chaque image avant de réutiliser ses données. Pour faire chevaucher le traitement de plusieurs images, réserver à chacune des données modifiables distinctes et suivre le moment où leur mémoire redevient disponible. Avant de modifier des données, attendre les accès GPU en cours aux mêmes octets ; avant de libérer une ressource, attendre toutes ses utilisations en cours." +concepts.synchronization.reuse.details: "Le redimensionnement et l’arrêt suivent la même règle : empêcher les nouveaux accès, attendre la fin des accès en cours, puis remplacer ou libérer les ressources. Respecter cet ordre avant {swapChainResize} ou avant de libérer les ressources ou le contexte. Le triangle attend déjà la fin de chaque image et peut donc redimensionner entre les rappels." +concepts.synchronization.reuse.guidance: "Après la présentation, {swapChainPresent} signale un point d’achèvement sur la file graphique et l’attend. Le triangle attend donc lors de la présentation même si l’attente explicite de sa soumission est retirée. Le travail soumis indépendamment à d’autres files demande son propre suivi d’achèvement." +concepts.synchronization.reuse.title: "Réutilisation des ressources" +concepts.synchronization.timelines.context: "Si le CPU doit lire le résultat, écraser les données partagées ou libérer les ressources après le consommateur, attendre cette soumission :" +concepts.synchronization.timelines.description: "Une ligne de temps repère les achèvements par valeurs croissantes. {submit} renvoie une {timelineValue} associant la ligne de temps à la valeur de soumission. Les champs numériques {value} de lignes distinctes ne se comparent pas directement." +concepts.synchronization.timelines.details: "Soient {producer} et {consumer}, deux tampons enregistrés sur des files du même contexte, le second utilisant les données du premier. Leur soumission exprime cette dépendance :" +concepts.synchronization.timelines.guidance: "La file consommatrice attend la valeur d’achèvement fournie avant d’exécuter ses commandes. Le CPU peut continuer sans appeler {producedWait}. Conserver les ressources partagées jusqu’à la fin de {consumed}, et enregistrer les transitions de texture requises par l’accès du consommateur." +concepts.synchronization.timelines.notes: "La valeur renvoyée par {queueTimelineSignal} peut elle aussi être attendue avec {wait} ou servir de dépendance à une autre file. {signal} place ce point d’achèvement après le travail déjà soumis ; le GPU l’atteint une fois ce travail terminé." +concepts.synchronization.timelines.title: "Lignes de temps et dépendances entre files" concepts.synchronization.title: Synchronisation home.actions.reference: Consulter l’API home.actions.tutorial: Commencer par un triangle -home.entries.description: Une première image. Un exemple ciblé. Un aperçu détaillé de l’API. -home.entries.label: Explorer la documentation +home.entries.description: "Tutoriels, exemples et référence API" +home.entries.label: "Rubriques de la documentation" home.entries.reference.action: Explorer l’API home.entries.reference.category: Référence -home.entries.reference.description: Trouvez les types, signatures et membres sous-jacents à votre application. +home.entries.reference.description: "Consulter les types, membres et déclarations de l’API" home.entries.reference.title: Référence de l’API home.entries.samples.action: Parcourir les exemples home.entries.samples.category: Exemples -home.entries.samples.description: Explorez des techniques ciblées de rendu et de calcul à travers leur code source. +home.entries.samples.description: "Des exemples exécutables de techniques graphiques et de calcul" home.entries.samples.title: Exemples -home.entries.title: Commencez à créer. +home.entries.title: "Documentation" home.entries.tutorial.action: Démarrer le tutoriel home.entries.tutorial.category: Tutoriel -home.entries.tutorial.description: Créez une application de rendu complète, de la configuration à la première image affichée. +home.entries.tutorial.description: "D’un projet vide au premier triangle à l’écran" home.entries.tutorial.title: Premier triangle -home.introduction.accent: "En C#." -home.introduction.description: Créez des ressources, enregistrez des commandes et soumettez des travaux de graphisme ou de calcul via une API .NET unifiée. -home.introduction.title: Créez votre moteur de rendu. -home.meta.description: "Une API C# cohérente pour les graphismes et le calcul sur DirectX, Metal et Vulkan." -home.scene.description: Étude de géométrie en rotation. Faites glisser ou utilisez les touches fléchées pour ajuster la vue. +home.introduction.accent: "avec .NET" +home.introduction.description: "Zenith.NET fournit une API commune pour le rendu et le calcul avec DirectX, Metal et Vulkan" +home.introduction.title: "Le rendu multiplateforme{lineBreak}{accent}" +home.meta.description: "Développez des applications graphiques et de calcul multiplateformes avec .NET et une API commune pour DirectX, Metal et Vulkan" +home.scene.description: "Géométrie en rotation interactive. Faire glisser ou utiliser les touches fléchées pour changer le point de vue." home.scene.label: Affichage de la géométrie home.scene.surface: Surface home.scene.wireframe: Fil de fer home.title: RHI moderne pour .NET -learning.concepts.description: Comprenez comment les commandes, les ressources, les données de shaders et la synchronisation s’articulent avant de combiner des passes de rendu. -learning.concepts.execution.description: Enregistrez des travaux GPU, soumettez-les et maintenez leurs ressources en vie. -learning.concepts.platforms.description: Connectez une fenêtre native ou un contrôle de rendu d’interface utilisateur. -learning.concepts.resources.description: Choisissez les usages des ressources, l’emplacement mémoire et les vues. -learning.concepts.shaders.description: "Faites correspondre les agencements C# et les handles de ressources avec Slang." -learning.concepts.synchronization.description: Ordonnez les accès dépendants et sachez quand les travaux se terminent. +learning.concepts.description: "Choisir les usages des ressources, décrire les données des shaders et coordonner l’exécution GPU" +learning.concepts.execution.description: "Enregistrement, soumission et durée de vie des ressources" +learning.concepts.platforms.description: "Présentation native et contrôles de rendu UI" +learning.concepts.resources.description: "Usages des ressources, placement mémoire et vues" +learning.concepts.shaders.description: "Conventions de disposition et de liaison entre C# et Slang" +learning.concepts.synchronization.description: "Dépendances, visibilité et achèvement" learning.concepts.title: Concepts fondamentaux -learning.description: Commencez par un tutoriel complet sur un triangle. Utilisez ensuite les exemples ciblés et les guides conceptuels pour comprendre les ressources, les données et les dépendances derrière un moteur de rendu plus vaste. +learning.description: "Commencez par le tutoriel du triangle pour créer votre première application. Les articles de fond expliquent ensuite la gestion des ressources, les données des shaders et la synchronisation. Les exemples permettent d’aborder séparément chaque technique." learning.entries.samples.action: Parcourir les exemples -learning.entries.samples.description: "Trouvez des exemples en C# et Slang pour la géométrie, le calcul, les requêtes de rayons et le mesh shading." +learning.entries.samples.description: "Implémentations C# et Slang de géométrie, calcul, requêtes de rayons et mesh shading" learning.entries.tutorial.action: Ouvrir le tutoriel -learning.entries.tutorial.description: Créez une application console, ouvrez une fenêtre et dessinez un triangle. -learning.meta.description: Démarrez avec Zenith.NET et explorez son modèle de programmation. +learning.entries.tutorial.description: "Une application console qui ouvre une fenêtre et rend un triangle" +learning.meta.description: "Tutoriels et concepts du modèle de programmation de Zenith.NET" learning.title: Apprendre -reference.description: Recherchez les types de ressources, les signatures de commandes et les intégrations de plateforme. -reference.entries.commands.description: Enregistrez des commandes de graphisme, de calcul et de transfert. -reference.entries.commands.label: Enregistrer des travaux -reference.entries.context.description: Créez des ressources GPU pour le backend sélectionné. +reference.description: "Référence des ressources, commandes et intégrations de plateforme" +reference.entries.commands.description: "Commandes graphiques, de calcul et de transfert" +reference.entries.commands.label: "Enregistrer des commandes" +reference.entries.context.description: "Création de ressources GPU pour le backend sélectionné" reference.entries.context.label: Commencer ici -reference.meta.description: Explorez les types et membres de Zenith.NET. -reference.navigation.core: Parcourir l’API principale. +reference.meta.description: "Espaces de noms, types et membres de Zenith.NET" +reference.navigation.core: "Référence de l’API principale" reference.title: Référence de l’API -samples.computeShader.description: Convertit une image en niveaux de gris avec un dispatch de calcul et affiche la texture résultante. Il illustre les handles de ressources pour une texture d’entrée échantillonnée et une texture de sortie accessible en écriture, des nombres de groupes de threads arrondis au supérieur et une vérification des limites dans le shader. Conservez la ressource {assetsTexturesShokoPng} incluse ; le moteur de rendu la traite une fois et présente le résultat lors des images suivantes. +samples.computeShader.description: "L’exemple charge l’image {assetsTexturesShokoPng}, la convertit en niveaux de gris par un calcul GPU et affiche la texture de sortie. La conversion n’a lieu qu’une fois ; les images suivantes affichent le même résultat. Le moteur de rendu montre comment lier des textures échantillonnées et accessibles en écriture, arrondir le nombre de groupes de threads à l’entier supérieur pour couvrir l’image et vérifier ses limites dans le shader." samples.computeShader.details: "{computeShaderRendererCs} · {computeShaderSlang}" samples.computeShader.title: Shader de calcul -samples.cube.description: Ajoute le dessin indexé, les matrices de modèle, de vue et de projection dans un tampon de constantes, ainsi que le test de profondeur. La texture de profondeur est recréée lors du redimensionnement. Utilisez-le pour passer d’une géométrie dans l’espace de découpage à un objet transformé ; le moteur de rendu utilise un attachement de profondeur/stencil {d32FloatS8UInt}. +samples.cube.description: "Le cube ajoute le dessin indexé, les matrices de modèle, de vue et de projection dans un tampon de constantes, ainsi que le test de profondeur. Sa texture de profondeur et de stencil {d32FloatS8UInt} est recréée au redimensionnement." samples.cube.details: "{spinningCubeRendererCs} · {spinningCubeSlang}" samples.cube.title: Cube en rotation -samples.description: "Choisissez un exemple ciblé pour la fonctionnalité que vous souhaitez étudier. Chaque exemple renvoie au moteur de rendu C# et à son shader Slang. Commencez par {link} si vous souhaitez une application complète expliquée à partir d’un projet vide." +samples.description: "Chaque exemple associe un moteur de rendu C# à son shader Slang et se concentre sur une technique. La configuration complète de l’application et la séquence de rendu sont décrites dans {link}." samples.description.link: Premier triangle -samples.execution.description: "{link} contient six moteurs de rendu indépendants dans une seule application de bureau. Utilisez le SDK .NET 10 et un backend de bureau pris en charge, comme décrit ci-dessous. Compilez et exécutez l’application, puis choisissez un exemple dans le menu de la console :" +samples.execution.description: "Exécutez le projet {link} et choisissez un exemple dans le menu de la console." samples.execution.description.link: ZenithTutorials -samples.execution.details: L’hôte sélectionne DirectX 12 sous Windows, Metal sous macOS et Vulkan sous Linux. Utilisez un environnement de périphérique, pilote et compilateur de shaders pris en charge par le backend sélectionné. Le chemin de fenêtre Linux nécessite X11 ou XWayland. Le {link} déclare les dépendances de paquets et copie les ressources de shaders et de textures nécessaires au moment de l’exécution. -samples.execution.details.link: fichier de projet -samples.execution.guidance: Les exemples partagent le code de gestion des fenêtres et de présentation. Vous pouvez choisir n’importe quel exemple indépendamment selon la fonctionnalité que vous souhaitez étudier. -samples.execution.title: Exécuter les exemples du tutoriel -samples.host.description: "{appCs} crée le contexte, la fenêtre et la chaîne d’échange. Il obtient un tampon de commandes, appelle le moteur de rendu sélectionné, soumet l’image et la présente. {iRendererCs} définit les méthodes de mise à jour, de rendu, de redimensionnement et de libération du moteur de rendu." -samples.host.details: Le calcul et le lancer de rayons produisent des textures hors écran. {texturePresenterCs} et {presentTextureSlang} dessinent ces textures dans la texture de sortie de l’image en cours de rendu de la fenêtre. L’hôte conserve la propriété de la soumission et de la présentation de la chaîne d’échange. -samples.host.title: Hôte et présentation partagés -samples.indirectDrawing.description: Dessine plusieurs copies d’un cube à l’aide d’un tampon d’arguments indirects indexés et de données par instance dans un tampon structuré. Le CPU fournit les arguments de dessin et met à jour les transformations. Utilisez-le pour comprendre l’agencement des arguments indirects et l’accès du shader aux données d’instance avant d’ajouter des arguments générés par le GPU. +samples.execution.title: "Exécution des exemples" +samples.host.description: "{appCs} initialise le contexte, la fenêtre et la chaîne d’échange. À chaque image, l’hôte obtient un tampon de commandes, appelle le moteur choisi, soumet les commandes et présente le résultat. {iRendererCs} définit les opérations de mise à jour, de rendu, de redimensionnement et de libération." +samples.host.details: "Les moteurs de rendu de calcul et de lancer de rayons produisent des textures hors écran. {texturePresenterCs} et {presentTextureSlang} les dessinent dans la texture de sortie courante ; l’hôte commun soumet ensuite les commandes et présente l’image." +samples.host.title: "Hôte et présentation" +samples.indirectDrawing.description: "Le dessin indirect affiche plusieurs instances de cube à partir d’un tampon d’arguments de dessin indexé et d’un tampon structuré de données par instance. Le CPU fournit les arguments et actualise les transformations." samples.indirectDrawing.details: "{indirectDrawingRendererCs} · {indirectDrawingSlang}" samples.indirectDrawing.title: Dessin indirect -samples.meshShading.description: "Utilise un task shader pour écarter du rendu des instances de sphères et transmettre les indices des instances retenues à un mesh shader qui produit la géométrie. Le moteur de rendu vérifie {contextCapabilitiesMeshShadingSupported} avant de créer son pipeline. Cet exemple permet de suivre les handles de ressources et les données de charge utile entre les étapes de tâche et de maillage." +samples.meshShading.description: "Un shader de tâches élimine les instances de sphères non visibles, puis transmet les indices restants au shader de maillage qui produit la géométrie. Le moteur vérifie {contextCapabilitiesMeshShadingSupported} avant de créer le pipeline." samples.meshShading.details: "{meshShadingRendererCs} · {meshShadingSlang}" samples.meshShading.title: Mesh Shading -samples.rayTracing.description: Construit des structures d’accélération de bas et haut niveau pour un sol et des sphères procédurales, puis trace des requêtes de rayons en ligne dans un shader de calcul. Le moteur de rendu vérifie {contextCapabilitiesRayTracingSupported} avant de construire la charge de travail. Utilisez cet exemple pour les entrées de structure d’accélération et le parcours de rayons côté shader. +samples.rayTracing.description: "Cet exemple construit les structures d’accélération de niveau inférieur et supérieur d’un sol et de sphères procédurales, puis effectue des requêtes de rayons directement dans un shader de calcul. Il vérifie {contextCapabilitiesRayTracingSupported} avant l’initialisation." samples.rayTracing.details: "{rayTracingRendererCs} · {rayTracingSlang}" samples.rayTracing.title: Lancer de rayons samples.title: Exemples -samples.triangle.description: Crée un tampon de sommets et un agencement d’entrée correspondant, puis dessine trois sommets via un pipeline graphique. Utilisez-le pour relier la création de ressources aux commandes d’une passe de rendu. +samples.triangle.description: "Le triangle associe un tampon de sommets à la disposition d’entrée correspondante et dessine trois sommets au moyen d’un pipeline graphique." samples.triangle.details: "{helloTriangleRendererCs} · {helloTriangleSlang} · {link}" samples.triangle.details.link: Tutoriel complet samples.triangle.title: Bonjour triangle -samples.workloads.description: "Le {link} du dépôt principal contient des applications qui combinent plusieurs fonctionnalités. Leurs projets font référence au code source de la bibliothèque. Depuis une copie locale de Zenith.NET, exécutez le projet choisi, par exemple :" +samples.workloads.description: "Le {link} du dépôt principal contient des applications plus complètes qui utilisent le code source de la bibliothèque." samples.workloads.description.link: répertoire Experiments -samples.workloads.details: Les expérimentations fenêtrées utilisent les mêmes choix d’hôtes pour Windows, macOS et Linux/X11. Pour dessiner au sein d’Avalonia, WinForms, WPF, WinUI/Uno ou MAUI, consultez {link} pour le cycle de vie des images du contrôle et les liens d’implémentation. +samples.workloads.details: "Les applications fenêtrées utilisent les mêmes chemins Windows, macOS et Linux/X11. Les contrôles Avalonia, WinForms, WPF, WinUI/Uno et MAUI sont décrits dans {link}, avec leur cycle d’image et leur code d’implémentation." samples.workloads.details.link: Intégration de plateforme samples.workloads.table.cornellBox.example: "{link}" samples.workloads.table.cornellBox.example.link: CornellBox -samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: "Tracé de chemins, débruitage, mappage tonal, agrandissement de l’image et contrôles ImGui. Nécessite la prise en charge du lancer de rayons et l’environnement de compilation de shaders pour le backend de bureau utilisé." +samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: "Tracé de chemins, débruitage, mappage tonal, agrandissement de l’image et contrôles ImGui. Nécessite la prise en charge du lancer de rayons." samples.workloads.table.fluidTank.example: "{link}" samples.workloads.table.fluidTank.example.link: FluidTank -samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: Simulation fluide par calcul, dépendances entre étapes de simulation et rendu de surface multipasse. Nécessite son backend de bureau et son environnement de compilation de shaders. +samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: "Simulation de fluide par calcul, dépendances entre étapes de simulation et rendu de surface multipasse." samples.workloads.table.headings.example: Exemple -samples.workloads.table.headings.whatItDemonstratesAndRequires: Ce qu’il démontre et prérequis +samples.workloads.table.headings.whatItDemonstratesAndRequires: "Techniques et prérequis" samples.workloads.table.inkCanvas.example: "{link}" samples.workloads.table.inkCanvas.example.link: InkCanvas samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: Dessin Skia et gestion des entrées dans une fenêtre native. Nécessite le backend et la bibliothèque native Skia pour la plateforme cible. samples.workloads.table.platformDetection.example: "{link}" samples.workloads.table.platformDetection.example.link: PlatformDetection -samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: Tente la création d’un contexte pour chaque backend et signale les fonctionnalités de l’appareil. Un échec de création de contexte est signalé comme non pris en charge ; ce résultat peut également indiquer un pilote manquant ou une dépendance d’exécution non satisfaite. -samples.workloads.title: Explorer des charges de travail plus vastes -tutorial.context.description: La fenêtre peut maintenant s’ouvrir, mais nous n’avons pas encore créé les objets GPU qui y effectueront le rendu. Un {graphicsContext} donne accès au backend graphique sélectionné et à ses files de commandes. -tutorial.context.details: "Insérez ce bloc {emphasis} :" +samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: "Tente de créer un contexte pour chaque backend et rapporte les capacités du périphérique. Un échec est indiqué comme une absence de prise en charge ; il peut provenir du périphérique, du pilote ou d’une dépendance d’exécution manquante." +samples.workloads.title: "Applications complètes" +tutorial.context.description: "Un {graphicsContext} relie l’application au GPU par l’intermédiaire d’un backend et fournit les méthodes de création des ressources de rendu." +tutorial.context.details: "Insérez l’initialisation du contexte {emphasis} :" tutorial.context.details.emphasis: après les directives using, avant {iWindowWindow} -tutorial.context.guidance: Les branches sélectionnent DirectX 12 sous Windows, Metal sous macOS et Vulkan sous Linux. Le code de rendu qui suit utilise l’API partagée de Zenith.NET. Nous demandons la validation pendant le développement et affichons les messages signalés via {validationMessage}. Les diagnostics dépendent du backend et des composants de validation disponibles sur la machine. -tutorial.context.title: Créer le contexte graphique -tutorial.description: Créez une application console .NET qui ouvre une fenêtre et dessine un triangle avec un dégradé de couleurs fluide. Vous apprendrez comment les données de sommets, les shaders et l’état du pipeline fonctionnent ensemble, puis vous enregistrerez et soumettrez les commandes qui produisent l’image. -tutorial.details: Parcourez les sections dans l’ordre. Vous ouvrirez d’abord une fenêtre vide, puis afficherez une couleur d’arrière-plan, et enfin dessinerez le triangle. Chaque point de contrôle confirme une partie de l’application avant d’ajouter la suivante. L’initialisation s’exécute une fois ; le rappel de rendu enregistre une nouvelle image à chaque appel. +tutorial.context.guidance: "Chaque branche sélectionne le backend de la plateforme et demande la validation. Les messages de {validationMessage} sont affichés dans la console." +tutorial.context.imports: "Ajoutez les directives using suivantes au début de {programCs} :" +tutorial.context.title: "Contexte graphique" +tutorial.description: "Ce tutoriel part d’un projet console .NET vide pour créer une application qui ouvre une fenêtre et dessine un triangle coloré." +tutorial.details: "Le tutoriel comporte trois étapes de vérification : une fenêtre vide, un fond uni, puis le triangle coloré. Exécutez l’application à chaque étape avant d’ajouter la partie suivante." tutorial.draw.context: "Les arguments de {draw} sont :" -tutorial.draw.description: "Dans le rappel {windowRender}, remplacez {addTheTriangleDrawCommandsHereLater} par ces trois commandes, entre {beginRenderPass} et {endRenderPass} :" -tutorial.draw.details: "{setPipeline} sélectionne les shaders et l’état que nous venons de créer. Définissez-le avant de lier les données de sommets : le backend utilise l’agencement d’entrée du pipeline pour interpréter la liaison." -tutorial.draw.guidance: "{setVertexBufferVertexBuffer} lie le tampon en commençant au décalage d’octet 0 au slot d’entrée 0. Ce slot correspond à l’unique entrée dans {inputLayouts}. Il ne copie ni ne transfère à nouveau les données." -tutorial.draw.notes: Les commandes ne sont encore qu’enregistrées à ce stade. Les appels {submitWait} et {present} déjà présents à la fin du rappel de rendu exécutent le travail et affichent son résultat. L’effacement reste nécessaire car le triangle ne couvre qu’une partie de l’image ; l’arrière-plan doit également recevoir une couleur définie à chaque image. +tutorial.draw.description: "Dans {windowRender}, remplacez {addTheTriangleDrawCommandsHereLater} par ces commandes, entre {beginRenderPass} et {endRenderPass} :" +tutorial.draw.details: "{setPipeline} sélectionne les shaders et l’état de rendu. Cet appel doit précéder la liaison du tampon de sommets, car le backend l’interprète selon la disposition d’entrée du pipeline." +tutorial.draw.guidance: "{setVertexBufferVertexBuffer} lie les données de sommets déjà transférées, à partir du décalage de 0 octet, à l’emplacement d’entrée 0. Celui-ci correspond à l’unique entrée de {inputLayouts}." +tutorial.draw.notes: "Ces appels enregistrent les commandes de dessin. L’appel {submitWait} déjà présent les soumet et attend que le GPU les termine ; {present} demande ensuite l’affichage de l’image achevée. Conservez l’initialisation avec la couleur de fond au début de la passe pour donner un contenu défini à la zone extérieure au triangle." tutorial.draw.table.firstInstance.meaning: Commencer la numérotation des instances à zéro. tutorial.draw.table.firstVertex.meaning: Commencer avec le premier sommet dans le tampon. tutorial.draw.table.headings.argument: Argument @@ -368,136 +362,131 @@ tutorial.draw.table.headings.description: Valeur tutorial.draw.table.headings.meaning: Signification tutorial.draw.table.instanceCount.meaning: Dessiner une copie du triangle. tutorial.draw.table.vertexCount.meaning: Lire trois sommets. -tutorial.draw.title: Dessiner le triangle à l’intérieur de la passe -tutorial.execution.description: "Compilez et exécutez depuis le répertoire {firstTriangle} :" -tutorial.execution.details: La fenêtre doit afficher un triangle avec un coin supérieur rouge, un coin inférieur droit vert et un coin inférieur gauche bleu sur un fond sombre. L’intérieur doit présenter un dégradé fluide entre ces couleurs. -tutorial.execution.guidance: Redimensionnez la fenêtre. Le rappel de redimensionnement met à jour les dimensions du tampon de trame et redimensionne la chaîne d’échange. La passe de rendu établit une fenêtre d’affichage correspondant à cette image. Étant donné que les positions des sommets restent en coordonnées normalisées, le triangle conserve la même fraction de la largeur et de la hauteur de la fenêtre ; changer le rapport d’aspect peut étirer sa forme. Préserver le rapport d’aspect d’un objet nécessite une stratégie de projection ou de fenêtre d’affichage, ce qui dépasse ce premier dessin. -tutorial.execution.title: Exécuter, redimensionner et fermer -tutorial.frame.commands.context: Après {endRenderPass}, la deuxième transition prépare l’image pour la présentation. {submit} termine l’enregistrement et soumet le tampon de commandes ; {wait} attend que le GPU termine cette soumission. {present} demande ensuite l’affichage de l’image rendue. -tutorial.frame.commands.description: Une passe de rendu regroupe les opérations de dessin qui utilisent les mêmes attachements. Ici, l’attachement de couleur est la texture de sortie de la chaîne d’échange, l’image qui reçoit notre dessin. {colorAttachmentClear} crée une description indiquant à la passe d’effacer à la couleur RGBA donnée et de conserver le résultat à la fin de la passe. {beginRenderPass} enregistre ces instructions ; le GPU effectue l’effacement après la soumission des commandes. -tutorial.frame.commands.details: Les crochets contiennent notre unique attachement de couleur. L’argument {null} signifie qu’il n’y a pas d’attachement de profondeur/stencil, qui stockerait les valeurs de profondeur et les masques de stencil pour les tests de profondeur et de stencil. -tutorial.frame.commands.guidance: "{beginRenderPass} définit une fenêtre d’affichage (viewport) et un découpage (scissor) couvrant l’attachement. La fenêtre d’affichage fait correspondre les coordonnées rendues aux pixels, et le découpage limite les pixels pouvant être écrits. Ces valeurs par défaut couvrent l’ensemble de la texture de sortie, ce dont ce triangle a besoin." -tutorial.frame.commands.title: Effacer, soumettre et présenter -tutorial.frame.description: Remplissez d’abord l’image avec une seule couleur d’arrière-plan. Cette opération s’appelle un effacement (clear). Si cette couleur apparaît dans la fenêtre, la surface, la soumission de commandes et le chemin de présentation fonctionnent ensemble. Ce point de contrôle vous permet de vérifier la boucle de trame avant d’ajouter de la géométrie et des shaders. -tutorial.frame.details: "Un rappel de rendu est du code que Silk.NET appelle lorsqu’il est temps de dessiner une image. Ce rappel n’a pas besoin de l’argument de temps écoulé de l’événement, il est donc nommé {value}. Enregistrez-le {emphasis} :" +tutorial.draw.title: "Commandes de dessin" +tutorial.execution.description: "Compilez et lancez le projet {firstTriangle}." +tutorial.execution.details: "Un triangle doit apparaître sur fond sombre, rouge en haut, vert en bas à droite et bleu en bas à gauche. L’interpolation des couleurs des sommets forme un dégradé continu à l’intérieur." +tutorial.execution.guidance: "Le redimensionnement modifie les dimensions de l’image en pixels, mais les coordonnées des sommets restent identiques. Le viewport les adapte à la nouvelle largeur et à la nouvelle hauteur. Le triangle s’étire donc lorsque le rapport largeur/hauteur de la fenêtre change." +tutorial.execution.title: "Exécution de l’application" +tutorial.frame.commands.context: "Après {endRenderPass}, la seconde transition prépare la sortie pour la présentation. {submit} termine l’enregistrement et soumet le tampon ; {wait} bloque jusqu’à l’achèvement. {present} demande ensuite l’affichage." +tutorial.frame.commands.description: "Une passe de rendu regroupe les opérations de dessin qui écrivent dans les mêmes attachements. Ici, la texture de sortie de la chaîne d’échange reçoit les couleurs produites par le rendu. {colorAttachmentClear} indique que cet attachement doit être initialisé avec une couleur RGBA et que son contenu doit être conservé à la fin de la passe. {beginRenderPass} enregistre le début de la passe avec ces paramètres." +tutorial.frame.commands.details: "La collection contient un attachement de couleur. {null} indique que la passe ne possède pas d’attachement de profondeur et de stencil." +tutorial.frame.commands.guidance: "{beginRenderPass} règle le viewport et le rectangle de découpe sur tout l’attachement. Le viewport convertit les coordonnées de rendu en positions de pixels ; le rectangle de découpe limite la zone où l’écriture est autorisée." +tutorial.frame.commands.title: "Effacement, soumission et présentation" +tutorial.frame.description: "Commencez par remplir la fenêtre d’une couleur de fond. Cette opération s’appelle l’effacement. Lorsque le fond s’affiche, la surface, la soumission et la présentation fonctionnent ensemble ; vous pouvez ajouter les sommets et les shaders du triangle." +tutorial.frame.details: "Silk.NET appelle le rappel de rendu lorsqu’une image doit être produite. L’argument de temps écoulé reste inutilisé et porte le nom {value}. Enregistrez le rappel {emphasis} :" tutorial.frame.details.emphasis: avant {windowRun} -tutorial.frame.target.description: "{graphicsQueueCommandBuffer} obtient un tampon de commandes dont l’enregistrement a déjà commencé. L’enregistrement décrit le travail pour le GPU ; il n’exécute pas ce travail immédiatement." -tutorial.frame.target.details: La première {transition} prépare la texture de sortie pour l’accès en attachement de couleur. {default} sélectionne le niveau mip 0 et la couche de tableau 0. Nous utilisons {undefined} comme layout précédent car nous allons effacer toute l’image et ignorer son contenu antérieur. Une passe qui doit préserver le contenu existant doit utiliser son layout précédent réel à la place. -tutorial.frame.target.guidance: Utilisez la texture de sortie actuelle de la chaîne d’échange à chaque image. La présentation peut modifier l’image disponible, de sorte qu’une texture enregistrée lors d’une image précédente n’est pas une cible de rendu de fenêtre permanente. -tutorial.frame.target.title: Préparer la texture de sortie -tutorial.frame.title: Afficher une couleur d’arrière-plan -tutorial.geometry.data.description: "Ajoutez ce tableau {emphasis}. Placez également les étapes suivantes de création des ressources avant ce rappel, dans l’ordre indiqué." +tutorial.frame.target.description: "{graphicsQueueCommandBuffer} renvoie un tampon prêt à enregistrer. L’enregistrement décrit le travail GPU ; l’exécution ne commence qu’après soumission." +tutorial.frame.target.details: "Le layout d’une texture décrit le type d’accès nécessaire à une opération. Le premier appel à {transition} prépare la texture de sortie à servir d’attachement de couleur. Ici, {default} sélectionne le niveau de mip 0 et la couche de tableau 0, soit l’image de base de cette texture. Comme la passe remplit toute l’image avec la couleur de fond, {undefined} autorise l’abandon de son contenu précédent." +tutorial.frame.target.guidance: "Utilisez la texture de sortie courante à chaque image, car la présentation peut faire passer la chaîne d’échange à une autre texture." +tutorial.frame.target.title: "Préparation de la sortie" +tutorial.frame.title: "Première image" +tutorial.geometry.data.description: "Ajoutez le tableau de sommets {emphasis}. L’initialisation des ressources suivantes reste aussi avant ce rappel, dans l’ordre indiqué." tutorial.geometry.data.description.emphasis: avant {windowRender} -tutorial.geometry.data.details: "Chaque entrée du tableau crée un {vertex}. Les deux expressions {new} internes créent sa position {vector3} et sa couleur {vector4}. Les sommets décrivent les coins supérieur, inférieur droit et inférieur gauche. Le shader de sommets fournira une quatrième coordonnée de position, {w}. Avec w égal à 1, x et y décrivent directement des coordonnées de périphérique normalisées : -1 et +1 sont les bords de l’image, et 0 est le centre. Ces coordonnées ne dépendent pas des dimensions en pixels de la fenêtre." -tutorial.geometry.data.guidance: Chaque couleur contient des composantes rouge, verte, bleue et alpha. Alpha vaut 1 aux trois coins. Les trois positions ont z = 0, ce qui les place dans le même plan. Ces positions n’ont pas besoin de caméra ni de matrice de transformation car elles décrivent déjà les coordonnées que nous voulons rendre. Pour ce triangle plat unique, nous désactiverons également le mélange et le test de profondeur et omettrons un tampon de profondeur. -tutorial.geometry.data.title: Choisir les coins -tutorial.geometry.description: Un sommet est un point associé aux données utilisées pour le dessiner. Notre triangle a trois sommets, un pour chaque coin. Chacun contient une position et une couleur. Le GPU interpolera les couleurs, calculant des valeurs intermédiaires à travers le triangle. -tutorial.geometry.format.description: "Ajoutez cette déclaration {emphasis} :" +tutorial.geometry.data.details: "Chaque entrée construit un {vertex}. Les deux expressions {new} internes donnent sa position {vector3} et sa couleur {vector4}. Les positions définissent les coins supérieur, inférieur droit et inférieur gauche. Le shader de sommets ajoute {w} comme quatrième coordonnée. Avec w = 1, x et y sont des coordonnées normalisées du périphérique : -1 et +1 marquent les bords, 0 le centre, indépendamment des dimensions en pixels." +tutorial.geometry.data.guidance: "Chaque couleur comporte des composantes rouge, verte, bleue et alpha, avec alpha égal à 1. Les trois sommets sont dans le même plan, à z = 0." +tutorial.geometry.data.title: "Positions et couleurs" +tutorial.geometry.description: "Chacun des trois sommets possède une position et une couleur. Le GPU détermine la forme du triangle à partir des positions et interpole les couleurs sur sa surface." +tutorial.geometry.format.description: "Ajoutez la déclaration de sommet {emphasis} :" tutorial.geometry.format.description.emphasis: à la fin de {programCs}, après les instructions de nettoyage -tutorial.geometry.format.details: "{file} limite ce type à {programCs}, et le constructeur initialise ses champs de position et de couleur. {layoutKindSequential} conserve les champs dans l’ordre de déclaration. {position} contient trois flottants 32 bits et {color} en contient quatre. Dans cette structure, la position commence à l’octet 0, la couleur commence à l’octet 12 et le sommet complet occupe 28 octets. Nous décrirons ce même agencement au pipeline graphique." -tutorial.geometry.format.title: Définir un sommet -tutorial.geometry.title: Fournir trois sommets au GPU -tutorial.geometry.upload.context: "{fixed} empêche le ramasse-miettes de déplacer le tableau pendant que son adresse est utilisée. Pour ce tampon accessible en écriture par le CPU, {upload} mappe, copie et démappe la mémoire avant de revenir, de sorte que le tableau n’a pas besoin de rester épinglé par la suite. Le tampon doit rester en vie tout au long du rendu, et le transfert ne doit avoir lieu qu’une seule fois car les sommets ne changent pas." -tutorial.geometry.upload.description: "Le tableau managé est constitué de données CPU. Un {buffer} donne au GPU un stockage dans lequel il peut lire les sommets. Après le tableau, ajoutez :" -tutorial.geometry.upload.details: "La taille totale est {sizeofVertexVerticesLength} : 28 octets par sommet, trois sommets, 84 octets en tout. {bufferUsagesVertex} autorise l’accès en entrée de sommets. {cpuWriteOnly} permet au CPU d’initialiser directement ce petit tampon. Le stride du descripteur enregistre la taille de l’élément ; l’agencement d’entrée que nous créons ci-dessous indiquera à la récupération des sommets comment lire les attributs individuels." -tutorial.geometry.upload.guidance: Créer un tampon ne le remplit pas. {upload} copie le tableau dans cette allocation en commençant au décalage d’octet de destination 0. Sa description source fournit un pointeur et le nombre d’octets à copier. -tutorial.geometry.upload.notes: Ajoutez {vertexBufferDispose} immédiatement avant {swapChainDispose} dans le nettoyage en bas de {programCs}. Pour une géométrie statique plus grande, {link} explique quand choisir un stockage réservé au GPU et des transferts à la place. +tutorial.geometry.format.details: "{file} limite le type au fichier {programCs}, tandis que {layoutKindSequential} conserve l’ordre de déclaration de ses champs. {position} contient trois nombres flottants de 32 bits à partir du décalage de 0 octet ; {color} en contient quatre à partir du décalage de 12 octets. Chaque sommet occupe donc 28 octets. La disposition d’entrée décrira cette organisation pour que le GPU lise correctement les champs." +tutorial.geometry.format.imports: "Ajoutez ces directives using au début de {programCs} pour les types vectoriels et l’attribut de disposition mémoire des structures :" +tutorial.geometry.format.title: "Représentation d’un sommet" +tutorial.geometry.title: "Données de sommets" +tutorial.geometry.upload.context: "{fixed} empêche le ramasse-miettes de déplacer le tableau pendant l’utilisation de son adresse. Pour ce tampon accessible en écriture au CPU, {upload} mappe la mémoire, copie les données, puis termine le mapping avant de retourner. Le tableau ne doit donc rester épinglé que pendant l’appel. Transférez les sommets une seule fois à l’initialisation et conservez le tampon jusqu’à la fin du rendu." +tutorial.geometry.upload.description: "Placez les sommets dans un {buffer} afin que le GPU puisse les lire pendant le dessin. Ajoutez l’allocation et le transfert immédiatement après le tableau :" +tutorial.geometry.upload.details: "{sizeofVertexVerticesLength} représente trois sommets de 28 octets, soit 84 octets. {bufferUsagesVertex} déclare l’accès en entrée de sommets, {cpuWriteOnly} autorise l’initialisation directe par le CPU. Le pas du descripteur indique la taille d’un élément ; la disposition d’entrée précise ensuite chaque attribut." +tutorial.geometry.upload.guidance: "L’allocation n’initialise pas le contenu. {upload} copie le tableau au décalage de destination 0 à partir du pointeur source et du nombre d’octets de la description." +tutorial.geometry.upload.imports: "Dans {programCs}, ajoutez {bufferAlias} aux directives using pour distinguer le type de tampon de Zenith.NET de {systemBuffer}." +tutorial.geometry.upload.notes: "Ajoutez {vertexBufferDispose} juste avant {swapChainDispose} à la fin de {programCs}. Le stockage réservé au GPU et les transferts pour de plus grandes géométries sont présentés dans {link}." tutorial.geometry.upload.notes.link: Gestion des ressources -tutorial.geometry.upload.title: Allouer un tampon et transférer le tableau -tutorial.input.description: "Les octets de sommets et les shaders sont prêts. Décrivez ensuite comment le GPU doit lire chaque sommet. Un attribut est une valeur unique, telle que la position ou la couleur. L’agencement d’entrée donne à chaque attribut un format et un décalage d’octets ; le stride donne la distance en octets d’un sommet au suivant. Ajoutez ce bloc d’initialisation après la création du shader :" -tutorial.input.details: "{inputLayoutAdd} ajoute un élément au stride actuel et augmente ce stride de la taille de l’élément. Il n’inspecte pas la structure C#. Ici, il produit la correspondance suivante entre la mémoire CPU et les entrées du shader :" -tutorial.input.guidance: "Modifier l’ordre des champs C# ou le remplissage sans mettre à jour cette description amènerait le GPU à lire les mauvais octets. Le {semanticIndex} par défaut est zéro, correspondant à {pOSITION0} et {cOLOR0}. Les deux éléments appartiennent au même tampon, de sorte que le pipeline contiendra un agencement d’entrée et nous lierons ce tampon au slot 0." +tutorial.geometry.upload.title: "Allocation et transfert du tampon" +tutorial.input.description: "Le GPU doit savoir où se trouvent les attributs de chaque sommet, comme la position et la couleur. La disposition d’entrée indique leur format et leur décalage, ainsi que le pas, la distance en octets entre deux sommets successifs. Ajoutez ce code après la création des shaders :" +tutorial.input.details: "{inputLayoutAdd} place chaque attribut immédiatement après le précédent et ajoute sa taille au pas entre sommets. Les décalages sont calculés à partir des formats fournis, sans examiner la structure C#. Pour ces deux champs, la disposition obtenue est la suivante :" +tutorial.input.guidance: "La valeur par défaut de {semanticIndex} est zéro, ce qui correspond à {pOSITION0} et {cOLOR0} dans le shader. La position et la couleur étant stockées ensemble dans un seul tampon de sommets, le pipeline utilise une disposition d’entrée à l’emplacement 0. Cette disposition doit être adaptée si l’ordre des champs ou le remplissage de la structure C# change." tutorial.input.table.headings.byteOffset: Décalage d’octets tutorial.input.table.headings.cField: "Champ C#" tutorial.input.table.headings.format: Format tutorial.input.table.headings.shaderInput: Entrée de shader tutorial.input.table.nextVertex.cField: Sommet suivant -tutorial.input.table.nextVertex.format: "Stride total : 28 octets" +tutorial.input.table.nextVertex.format: "Pas total : 28 octets" tutorial.input.table.nextVertex.shaderInput: Enregistrement d’entrée suivant tutorial.input.table.vertexColor.format: "{float4} (16 octets)" tutorial.input.table.vertexPosition.format: "{float3} (12 octets)" -tutorial.input.title: Décrire l’agencement d’entrée des sommets -tutorial.lifecycle.description: "L’application terminée répète cette séquence :" -tutorial.lifecycle.details: "Fermer la fenêtre met fin à {run}. Chaque image rendue a déjà attendu la fin de son travail GPU, nous pouvons donc maintenant libérer les ressources qu’elle a utilisées. Le nettoyage après {windowRun} doit être :" -tutorial.lifecycle.guidance: "Libérez la chaîne d’échange avant sa fenêtre native, et le contexte après toutes ses ressources. La file possède et recycle les tampons de commandes soumis ; la chaîne d’échange possède sa texture de sortie. Ces tampons de commandes et cette texture ne nécessitent donc pas d’appel {dispose} distinct dans cette application." -tutorial.lifecycle.title: Suivre le cycle de vie d’une image -tutorial.pipeline.behavior: "Après l’agencement d’entrée, ajoutez :" -tutorial.pipeline.context: "{cullNone} remplit le triangle sans éliminer aucune orientation de face. L’ordre de ses sommets détermine l’orientation de la face, donc la désactivation du culling empêche cet ordre de masquer notre premier triangle." -tutorial.pipeline.description: Nous avons maintenant des données de sommets, un agencement d’entrée et deux shaders. Le {graphicsPipeline} les connecte et spécifie comment le GPU assemble les sommets en primitives et écrit le résultat dans un attachement. -tutorial.pipeline.details: "Un pipeline combine des étapes de shader programmables avec des paramètres de fonction fixe, qui contrôlent les opérations GPU telles que l’assemblage de triangles, l’élimination des faces (culling) et le mélange. Pour ce triangle, choisissez ces paramètres :" -tutorial.pipeline.guidance: Le format de couleur provient de {swapChainDescFormat}. Il doit correspondre à l’image utilisée par la passe de rendu. {count1} signifie un échantillon par pixel. -tutorial.pipeline.item: "{triangleList} assemble chaque groupe consécutif de trois sommets en un triangle. Nous fournirons trois sommets et dessinerons une fois, de sorte qu’aucun tampon d’indices n’est nécessaire." -tutorial.pipeline.notes: "{depthNone} désactive les tests et l’écriture de profondeur, correspondant à la passe sans attachement de profondeur." -tutorial.pipeline.reference: "{opaque} désactive le mélange, de sorte que la couleur du shader de fragments remplace l’arrière-plan à l’intérieur du triangle." -tutorial.pipeline.title: Connecter les shaders et l’agencement de sommets -tutorial.pipeline.usage: Les objets de shader peuvent être libérés après la création du pipeline, comme dans le moteur de rendu d’exemple. Gardez le pipeline lui-même en vie pour chaque image qui dessine avec lui. Ajoutez {pipelineDispose} avant {vertexBufferDispose} dans le nettoyage. La création du pipeline est la dernière étape d’initialisation avant le rappel de rendu. -tutorial.pipeline.validation: La description du pipeline déclare la configuration d’attachement ; elle ne crée pas d’autre image. {inputLayouts} a une entrée car la position et la couleur sont stockées ensemble dans un seul tampon. -tutorial.presentation.title: Connecter le GPU à la fenêtre -tutorial.project.context: Activez {emphasis} ({allowUnsafeBlocks}) dans les paramètres de compilation du projet. Nous l’utiliserons pour transmettre des données de sommets au GPU et pour les appels natifs de l’assistant de fenêtre. +tutorial.input.title: "Disposition des sommets en entrée" +tutorial.lifecycle.description: "Chaque image suit cette séquence :" +tutorial.lifecycle.details: "À la fermeture de la fenêtre, {run} retourne et l’exécution se poursuit avec le nettoyage. Chaque image ayant déjà attendu la fin de ses commandes, les ressources utilisées par ces commandes peuvent être libérées. Le nettoyage complet après {windowRun} est le suivant :" +tutorial.lifecycle.guidance: "Libérez la chaîne d’échange avant sa fenêtre native, et le contexte après ses ressources. La file recycle les tampons de commandes soumis, tandis que la chaîne d’échange gère sa texture de sortie. Aucun de ces objets ne nécessite donc d’appel distinct à {dispose}." +tutorial.lifecycle.title: "Cycle d’image et libération" +tutorial.pipeline.behavior: "Après la disposition d’entrée, créez le pipeline :" +tutorial.pipeline.context: "{cullNone} désactive l’élimination des faces. Le triangle est donc dessiné que ses sommets apparaissent dans le sens horaire ou antihoraire." +tutorial.pipeline.description: "Un {graphicsPipeline} réunit la disposition des sommets, les deux shaders et les réglages d’assemblage des primitives et d’écriture dans les attachements." +tutorial.pipeline.details: "Les shaders traitent les sommets et les fragments. Les autres réglages du pipeline contrôlent l’assemblage des primitives, l’élimination des faces, le test de profondeur et le mélange des couleurs :" +tutorial.pipeline.guidance: "Le format du pipeline doit correspondre à l’attachement ; il provient donc de {swapChainDescFormat}. {count1} indique un échantillon par pixel." +tutorial.pipeline.item: "{triangleList} assemble chaque groupe de trois sommets consécutifs en un triangle." +tutorial.pipeline.notes: "{depthNone} désactive le test et l’écriture de profondeur, puisque la passe ne comporte pas d’attachement de profondeur." +tutorial.pipeline.reference: "{opaque} désactive le mélange. La couleur du fragment remplace ainsi le fond à l’intérieur du triangle." +tutorial.pipeline.title: "Pipeline graphique" +tutorial.pipeline.usage: "Les objets shader peuvent être libérés après la création du pipeline. Conservez le pipeline pendant le rendu et ajoutez {pipelineDispose} avant {vertexBufferDispose} dans le nettoyage." +tutorial.presentation.title: "Contexte graphique et présentation" +tutorial.project.context: "Activez {emphasis} ({allowUnsafeBlocks}) dans les paramètres de compilation. Les appels natifs du code de fenêtre et le transfert des sommets nécessitent du code unsafe." tutorial.project.context.emphasis: Autoriser le code non sécurisé -tutorial.project.description: "Créez le projet et accédez à son répertoire :" -tutorial.project.details: "Installez les paquets :" -tutorial.project.guidance: "{zenithNET} fournit l’API de rendu partagée. Les trois paquets de backend permettent au même programme de sélectionner l’implémentation adaptée à sa plateforme. {zenithNETCompiler} compile les shaders Slang – les petits programmes GPU que nous écrirons plus tard – pour cette implémentation. Silk.NET fournit la fenêtre et la boucle d’événements." -tutorial.project.title: Créer un projet console -tutorial.requirements.context: Vous pouvez suivre cette page à partir d’un projet vide. L’{link} et son {detail} sont disponibles comme référence pour les API de rendu et de fenêtrage utilisées ici. +tutorial.project.description: "Créez un projet console C# nommé {firstTriangle} ciblant .NET 10." +tutorial.project.details: "Ajoutez les paquets NuGet suivants au projet :" +tutorial.project.guidance: "{zenithNET} fournit l’API de rendu commune, et les trois paquets de backend en fournissent les implémentations propres aux plateformes. {zenithNETCompiler} compile les shaders Slang présentés plus bas pour le backend choisi. Silk.NET assure la création de la fenêtre et le traitement des événements." +tutorial.project.title: "Configuration du projet" +tutorial.requirements.context: "L’{link} et son {detail} fournissent les implémentations de référence de ce tutoriel." tutorial.requirements.context.detail: hôte partagé tutorial.requirements.context.link: exemple Bonjour triangle -tutorial.requirements.description: "Vous avez besoin du {emphasis}, d’un éditeur de code ou IDE et d’un ordinateur de bureau équipé d’un GPU et d’un pilote pris en charge par un backend de Zenith.NET. Une bonne connaissance de base de C# suffit ; les concepts graphiques sont introduits au fur et à mesure de leur utilisation. Il s’agit d’un projet console {net10} ordinaire. Un backend traduit les opérations de Zenith.NET en appels à une API graphique telle que DirectX 12, Metal ou Vulkan. L’application en choisit une au démarrage :" +tutorial.requirements.description: "Vous devez disposer du {emphasis} et connaître les bases de C#. L’application cible {net10}. Le GPU et son pilote doivent prendre en charge le backend choisi pour votre plateforme :" tutorial.requirements.description.emphasis: SDK .NET 10 -tutorial.requirements.details: Linux nécessite une session fenêtrée compatible X11 pour le chemin de gestion de fenêtre utilisé ici. Les fonctionnalités optionnelles de lancer de rayons et de mesh shading ne sont pas nécessaires pour ce triangle. -tutorial.requirements.guidance: Zenith.NET effectue le rendu dans une surface fournie par l’application. Silk.NET.Windowing créera la fenêtre de bureau et traitera ses événements. Sous macOS, la cible de présentation est une couche Metal ({cAMetalLayerCs}) ; l’assistant de fenêtre du tutoriel attache cette couche pour nous. +tutorial.requirements.guidance: "Zenith.NET rend dans une surface native fournie par l’application. Silk.NET.Windowing crée la fenêtre et gère les événements. Sous macOS, une couche Metal représentée par {cAMetalLayerCs} reçoit la sortie ; le code auxiliaire la rattache à la fenêtre." tutorial.requirements.table.headings.graphicsBackend: Backend graphique tutorial.requirements.table.headings.platform: Plateforme -tutorial.requirements.table.headings.windowSurface: Surface de fenêtre tutorial.requirements.table.linux.graphicsBackend: Vulkan 1.4 -tutorial.requirements.table.linux.platform: Linux -tutorial.requirements.table.linux.windowSurface: Fenêtre et affichage X11 ; XWayland convient également +tutorial.requirements.table.linux.platform: "Linux (X11 ou XWayland)" tutorial.requirements.table.macOS.graphicsBackend: Metal 4 tutorial.requirements.table.macOS.platform: macOS -tutorial.requirements.table.macOS.windowSurface: Couche Metal attachée à la fenêtre tutorial.requirements.table.windows.graphicsBackend: DirectX 12 tutorial.requirements.table.windows.platform: Windows -tutorial.requirements.table.windows.windowSurface: Handle de fenêtre Win32 -tutorial.requirements.title: Avant de commencer -tutorial.resize.context: "Exécutez à nouveau {dotnetRun}. La fenêtre devrait maintenant avoir un arrière-plan sombre uniforme qui continue de la remplir après le redimensionnement. Conservez ce rappel : le triangle sera dessiné à l’intérieur de sa passe de rendu existante." -tutorial.resize.description: "Les images de la chaîne d’échange doivent suivre les dimensions du tampon de trame. Utilisez {framebufferResize} pour répondre aux changements de taille de pixels, y compris les changements causés par la mise à l’échelle de l’affichage. Après le rappel de rendu, toujours avant {windowRun}, ajoutez :" -tutorial.resize.details: Silk.NET distingue les changements de taille de fenêtre des {link}. Nous avons besoin de ces derniers car la chaîne d’échange stocke des pixels. Une fenêtre réduite peut avoir un tampon de trame de taille zéro. Dans ce cas, les deux rappels ignorent leur travail GPU. Après un redimensionnement, la passe de rendu utilisera les nouvelles dimensions d’attachement pour sa fenêtre d’affichage et son découpage. -tutorial.resize.details.link: changements de taille du tampon de trame -tutorial.resize.guidance: Nous attendons après chaque soumission, de sorte qu’aucune image précédente n’utilise encore les images lorsque le gestionnaire de redimensionnement les remplace. L’implémentation actuelle de {present} attend également sur la file graphique. Cette boucle simple maintient le travail d’une image terminé avant que la suivante ne commence ; {link} couvre une planification plus avancée. +tutorial.requirements.title: "Prérequis" +tutorial.resize.context: "Compilez et lancez de nouveau l’application. Le fond doit continuer à remplir la fenêtre lorsque vous la redimensionnez : chaque nouvelle passe ajuste son viewport et son rectangle de découpe aux dimensions de l’attachement. Conservez le rappel de rendu ; le triangle sera dessiné dans cette passe." +tutorial.resize.description: "La chaîne d’échange doit suivre les changements de dimensions du framebuffer. Ajoutez un gestionnaire de {framebufferResize} après le rappel de rendu et avant {windowRun} :" +tutorial.resize.details: "Réagissez aux {link}, exprimés en pixels, plutôt qu’aux changements de taille logique de la fenêtre. Si la réduction de la fenêtre met l’une des dimensions du framebuffer à zéro, le gestionnaire de redimensionnement laisse la chaîne d’échange inchangée. Le rappel de rendu retourne lui aussi immédiatement tant qu’une dimension est nulle. Le rendu reprend lorsque le framebuffer retrouve des dimensions utilisables." +tutorial.resize.details.link: "changements de taille du framebuffer" +tutorial.resize.guidance: "Le rappel de rendu attend la fin des commandes soumises pour chaque image avant d’appeler {present}. Le gestionnaire de redimensionnement peut donc remplacer les images de la chaîne d’échange sans interrompre le travail d’une image précédente. L’article {link} détaille ce lien entre achèvement du travail et durée de vie des ressources." tutorial.resize.guidance.link: Synchronisation -tutorial.resize.title: Réagir au redimensionnement -tutorial.shaders.compilation.context: La compilation a lieu une fois lors de l’initialisation. {appContextBaseDirectory} localise le shader copié à côté de l’exécutable, indépendamment du répertoire de travail actuel. Ces shaders ne consomment que des entrées de sommets, il n’y a donc pas encore de tampons de constantes, de textures ou de handles de ressources à lier. -tutorial.shaders.compilation.description: Dans les propriétés du fichier pour {triangleSlang}, définissez {emphasis} sur {detail}. Cela rend le shader disponible à côté de l’exécutable. +tutorial.resize.title: "Redimensionnement" +tutorial.shaders.compilation.context: "{appContextBaseDirectory} permet de charger la copie du shader depuis le répertoire de sortie de l’application. Le fichier reste ainsi localisable même si l’application est lancée depuis un autre répertoire de travail." +tutorial.shaders.compilation.description: "Pour {triangleSlang}, réglez la propriété {emphasis} sur {detail}. La compilation du projet copiera le shader près de l’exécutable." tutorial.shaders.compilation.description.detail: Copier si plus récent tutorial.shaders.compilation.description.emphasis: Copier dans le répertoire de sortie -tutorial.shaders.compilation.details: "Revenez à {programCs}. Après le transfert des sommets, ajoutez ces instructions d’initialisation avant le rappel de rendu :" -tutorial.shaders.compilation.guidance: "{zenithCompiler} renvoie une description de shader contenant le code pour l’API graphique demandée. {createShader} crée l’objet de backend correspondant. L’API graphique et les noms des points d’entrée sont tous deux importants : utilisez {contextGraphicsApi}, et écrivez {vSMain} et {fSMain} exactement comme dans le fichier Slang." -tutorial.shaders.compilation.title: Compiler pour le backend sélectionné -tutorial.shaders.context: "{fSInput} connecte la sortie du shader de sommets à l’entrée du shader de fragments. Lorsqu’il est écrit par le shader de sommets, {sVPOSITION} fournit une position dans l’espace de découpage : les quatre coordonnées que le GPU utilise pour déterminer ce qui se trouve à l’intérieur de l’image visible. {cOLOR0} transporte la couleur à interpoler entre les sommets. Les deux étapes doivent s’accorder sur son type et sa sémantique." -tutorial.shaders.description: Un shader est un programme exécuté par le GPU. Ce dessin a besoin d’un shader de sommets pour positionner les sommets et d’un shader de fragments pour produire les couleurs à l’intérieur du triangle. Nous les écrirons en Slang, un langage de shaders, et compilerons deux points d’entrée à partir du même fichier. Un point d’entrée est la fonction où l’exécution d’une étape de shader commence. -tutorial.shaders.details: "Créez {triangleSlang}, en commençant par ces deux structures :" -tutorial.shaders.fragment.description: "Ajoutez le point d’entrée de fragment au même fichier :" -tutorial.shaders.fragment.details: La rastérisation détermine les emplacements d’image que le triangle couvre. Elle produit des fragments (les données traitées par le shader de fragments) avec des couleurs de sommets interpolées sur la zone couverte. {fSMain} renvoie cette couleur interpolée via {sVTARGET}, qui identifie le premier attachement de couleur. -tutorial.shaders.fragment.guidance: L’interpolation de couleur des sommets est distincte du mélange d’attachement. Le mélange combine la sortie d’un fragment avec la couleur déjà stockée dans l’attachement. Notre état de mélange opaque désactive cette combinaison, de sorte que la couleur interpolée remplace l’arrière-plan à l’intérieur du triangle. -tutorial.shaders.fragment.title: Colorer les fragments -tutorial.shaders.guidance: "{vSInput} décrit ce que le shader de sommets reçoit depuis le tampon de sommets. Les sémantiques {pOSITION0} et {cOLOR0} identifient les entrées ; les noms de champs C# seuls n’établissent pas ce mappage." -tutorial.shaders.title: Écrire les deux étapes de shader -tutorial.shaders.vertex.description: "Ajoutez le point d’entrée de sommet à {triangleSlang} :" -tutorial.shaders.vertex.details: Le GPU appelle ce point d’entrée pour chaque sommet d’entrée. Il ajoute la coordonnée homogène {w} à la position et transmet la couleur. Après l’étape de sommet, la position est divisée par w ; ici, cette division laisse x, y et z inchangés. C’est pourquoi les positions choisies ci-dessus peuvent être comprises directement en coordonnées de périphérique normalisées. -tutorial.shaders.vertex.title: Positionner chaque sommet -tutorial.surface.description: "Le contexte doit également savoir où afficher sa sortie. Ajoutez ce qui suit {emphasis} :" +tutorial.shaders.compilation.details: "Dans {programCs}, ajoutez l’initialisation des shaders après le transfert des sommets et avant le rappel de rendu :" +tutorial.shaders.compilation.guidance: "{zenithCompiler} compile le code source pour {contextGraphicsApi}, puis {createShader} crée un objet shader à partir de la description compilée. Les noms de points d’entrée {vSMain} et {fSMain} sélectionnent les deux fonctions définies dans le fichier Slang." +tutorial.shaders.compilation.title: "Compilation des shaders" +tutorial.shaders.context: "{fSInput} relie les deux étapes de shader. Le shader de sommets écrit une position dans l’espace de clipping dans {sVPOSITION} ; le GPU s’en sert pour déterminer la partie visible du triangle. Le champ {cOLOR0} transmet la couleur du sommet, qui est interpolée sur le triangle avant de parvenir au shader de fragments. Son type et sa sémantique doivent correspondre entre les deux étapes." +tutorial.shaders.description: "Les shaders sont des programmes exécutés sur le GPU. Le shader de sommets détermine la position de chaque sommet ; le shader de fragments détermine la couleur aux emplacements de l’image couverts par le triangle. Les deux étapes seront écrites dans un même fichier Slang, chacune avec son point d’entrée, c’est-à-dire la fonction où commence son exécution." +tutorial.shaders.details: "Créez {triangleSlang} avec ces structures d’entrée et de sortie :" +tutorial.shaders.fragment.description: "Ajoutez le point d’entrée de fragments dans le même fichier :" +tutorial.shaders.fragment.details: "La rastérisation détermine les emplacements couverts par le triangle et y génère des fragments. Chaque fragment reçoit une couleur interpolée à partir des couleurs des trois sommets. {fSMain} renvoie cette couleur, et {sVTARGET} dirige le résultat vers le premier attachement de couleur." +tutorial.shaders.fragment.title: "Traitement des fragments" +tutorial.shaders.guidance: "{vSInput} définit l’entrée du shader de sommets. {pOSITION0} et {cOLOR0} identifient les attributs par leur sémantique ; les noms C# n’établissent pas cette correspondance." +tutorial.shaders.title: "Étapes des shaders" +tutorial.shaders.vertex.description: "Ajoutez le point d’entrée de sommets à {triangleSlang} :" +tutorial.shaders.vertex.details: "Le GPU appelle ce point d’entrée pour chaque sommet, ajoute la coordonnée homogène {w} et transmet la couleur. La position est ensuite divisée par w. Ici w vaut 1 : x, y et z restent inchangés et correspondent aux coordonnées normalisées du périphérique." +tutorial.shaders.vertex.title: "Traitement des sommets" +tutorial.surface.description: "Définissez la cible de présentation native {emphasis} :" tutorial.surface.description.emphasis: après {windowCenter} et avant {windowRun} -tutorial.surface.details: "{surface} décrit une cible de présentation native et ses dimensions en pixels. Le tampon de trame (framebuffer) est l’image de pixels associée à la fenêtre. {framebufferSize} donne ses dimensions en pixels ; les dimensions logiques de la fenêtre peuvent différer lorsque la mise à l’échelle de l’affichage est activée." -tutorial.surface.guidance: La surface correspond au backend sélectionné ci-dessus. Windows fournit un handle de fenêtre, Linux fournit un affichage et une fenêtre X11, et l’assistant macOS fournit la couche Metal attachée. C’est la seule partie spécifique à la plateforme pour connecter notre fenêtre au rendu. -tutorial.surface.title: Décrire la surface native -tutorial.swapChain.context: "La chaîne d’échange utilise à la fois le contexte et la fenêtre native. Remplacez la ligne {windowDispose} en bas de {programCs} par cet ordre de nettoyage :" -tutorial.swapChain.description: "Utilisez la description de surface pour créer les images qui seront présentées. Immédiatement après le bloc de surface, ajoutez :" -tutorial.swapChain.details: La {swapChain} gère les images affichées dans la fenêtre. À chaque image, {drawable} nous donne l’image actuelle sous forme de {texture}, le type d’API pour les données d’image. Après le dessin, {present} demande l’affichage du résultat et passe au drawable suivant. -tutorial.swapChain.guidance: "{b8G8R8A8UNorm} stocke quatre canaux de couleur de 8 bits dans l’ordre bleu, vert, rouge et alpha. {uNorm} signifie que les valeurs entières de 0 à 255 représentent des valeurs de 0 à 1. Le shader renverra toujours une valeur RGBA logique ; ce format détermine la façon dont ces canaux sont stockés dans l’image. Plus tard, le pipeline graphique utilisera {swapChainDescFormat} pour correspondre à cet attachement." -tutorial.swapChain.title: Créer la chaîne d’échange +tutorial.surface.details: "Le framebuffer est l’image de la fenêtre en pixels. {surface} décrit la cible de présentation native et ses dimensions ; {framebufferSize} donne la taille en pixels. Avec la mise à l’échelle de l’affichage, cette taille peut différer de la taille logique de la fenêtre." +tutorial.surface.guidance: "La surface fournit les handles natifs du backend choisi : une fenêtre Win32 sous Windows, un affichage et une fenêtre X11 sous Linux, ou la couche Metal attachée sous macOS." +tutorial.surface.title: "Surface native" +tutorial.swapChain.context: "La chaîne dépend du contexte et de la fenêtre. Remplacez {windowDispose} à la fin de {programCs} par cet ordre de libération :" +tutorial.swapChain.description: "Créez la chaîne d’échange immédiatement après la surface :" +tutorial.swapChain.details: "La {swapChain} gère les images présentées. {drawable} fournit l’image courante sous forme de {texture}, la ressource image de l’API. Après le rendu, {present} demande son affichage et passe à la suivante." +tutorial.swapChain.guidance: "{b8G8R8A8UNorm} stocke quatre canaux de 8 bits dans l’ordre bleu, vert, rouge, alpha. {uNorm} fait correspondre les entiers de 0 à 255 aux valeurs de 0 à 1. Le shader produit des valeurs RGBA ; le format détermine leur stockage en mémoire. Le pipeline reprend le format de couleur {swapChainDescFormat} pour correspondre à l’attachement." +tutorial.swapChain.title: "Chaîne d’échange" tutorial.title: Premier triangle -tutorial.troubleshooting.description: "Lisez d’abord toute erreur dans la console, puis utilisez les points de contrôle précédents pour identifier l’étape qui a échoué :" -tutorial.troubleshooting.details: Utilisez le {link} et le {detail} pour comparer les données de sommets, l’agencement d’entrée et l’opération de dessin. Cet exemple place la gestion des fenêtres et la soumission dans un hôte partagé ; ce tutoriel conserve le flux applicatif dans {programCs}. Poursuivez avec {context} pour apprendre le dessin indexé, les transformations et les tests de profondeur. +tutorial.troubleshooting.description: "Les diagnostics console et les trois points de contrôle permettent d’isoler l’étape en échec :" +tutorial.troubleshooting.details: "Le {link} et le {detail} servent de référence pour les données des sommets, la disposition d’entrée et les commandes de dessin. Dans cet exemple, la fenêtre et la soumission sont gérées par un hôte commun ; ce tutoriel conserve le déroulement de l’application dans {programCs}. L’exemple {context} introduit le dessin indexé, les transformations et le test de profondeur." tutorial.troubleshooting.details.context: Cube en rotation tutorial.troubleshooting.details.detail: shader Slang tutorial.troubleshooting.details.link: moteur de rendu d’exemple @@ -507,19 +496,18 @@ tutorial.troubleshooting.table.drawing.check: Vérifiez la taille du transfert, tutorial.troubleshooting.table.drawing.symptom: L’arrière-plan apparaît mais pas le triangle tutorial.troubleshooting.table.headings.check: Vérification tutorial.troubleshooting.table.headings.symptom: Symptôme -tutorial.troubleshooting.table.input.check: Vérifiez le stride de 28 octets et les décalages de position/couleur de 0 et 12. +tutorial.troubleshooting.table.input.check: "Vérifiez le pas de 28 octets et les décalages de la position et de la couleur : respectivement 0 et 12 octets." tutorial.troubleshooting.table.input.symptom: Les positions ou les couleurs des sommets sont corrompues tutorial.troubleshooting.table.shaders.check: Vérifiez le fichier {triangleSlang} copié, l’orthographe du point d’entrée et le diagnostic signalé par le compilateur. -tutorial.troubleshooting.table.shaders.symptom: L’étape de couleur d’effacement fonctionne, mais le chargement des shaders échoue +tutorial.troubleshooting.table.shaders.symptom: "Le fond s’affiche, mais le chargement des shaders échoue" tutorial.troubleshooting.table.window.check: Confirmez que le projet .NET se compile et que l’étape de fenêtre seule s’exécute dans une session de bureau. Sous Linux, vérifiez que X11 ou XWayland est disponible. tutorial.troubleshooting.table.window.symptom: Aucune fenêtre ne s’ouvre -tutorial.troubleshooting.title: Vérifier l’étape qui a échoué -tutorial.window.context: "{usingZenithTutorials} importe l’espace de noms de l’assistant. Chaque fichier C# utilise ses propres directives using ordinaires, de sorte que l’importation d’interopérabilité est nécessaire dans les deux fichiers. L’alias {buffer} fait référence au type de tampon de Zenith.NET et le distingue de {systemBuffer}." -tutorial.window.description: Ajoutez {cocoaHelperCs} au projet, en conservant son espace de noms. Ajoutez {interopUsing} en haut de ce fichier, avant sa déclaration d’espace de noms. L’assistant attache une couche Metal à la fenêtre sous macOS ; les autres branches de plateforme ne l’appellent pas. -tutorial.window.details: "Remplacez le fichier {programCs} généré par le code suivant. Il utilise des instructions de niveau supérieur, qui s’exécutent dans l’ordre sans méthode {main} explicite. Les sections suivantes vous indiqueront où ajouter du code à ce même fichier :" -tutorial.window.guidance: "{graphicsAPINone} demande à Silk.NET de créer une fenêtre sans son propre contexte graphique. Nous allons créer ce contexte avec Zenith.NET. {initialize} crée la fenêtre native et rend ses handles disponibles. Un handle est un identifiant fourni par le système de fenêtrage. {center} centre la fenêtre et {run} traite les événements jusqu’à sa fermeture. L’exécution se poursuit ensuite vers {dispose}, qui libère la fenêtre." -tutorial.window.notes: Exécutez {dotnetRun}. Une fenêtre vide doit s’ouvrir et répondre au déplacement, au redimensionnement et à la fermeture. Son contenu n’est pas encore défini car nous n’avons soumis aucune commande de rendu. Fermez-la avant de continuer. -tutorial.window.title: Ouvrir une fenêtre +tutorial.troubleshooting.title: "Diagnostic des erreurs" +tutorial.window.description: "Téléchargez {cocoaHelperCs} dans le projet. Cette classe auxiliaire attache la couche Metal à la fenêtre macOS." +tutorial.window.details: "Remplacez le contenu généré de {programCs} par le code suivant. Les instructions de niveau supérieur s’exécutent dans l’ordre, sans méthode {main} explicite. Les prochaines sections préciseront où ajouter chaque extrait :" +tutorial.window.guidance: "{graphicsAPINone} laisse à Zenith.NET la création du contexte graphique. {initialize} crée la fenêtre native et rend ses handles disponibles. {center} la place au centre de l’écran. {run} traite les événements jusqu’à sa fermeture, puis l’exécution passe à {dispose} pour la libérer." +tutorial.window.notes: "Compilez et lancez l’application. Vérifiez que la fenêtre s’ouvre et se ferme correctement, et que vous pouvez la déplacer et la redimensionner. Son contenu n’est pas encore défini, car aucune commande de rendu n’a été soumise. Fermez la fenêtre avant de poursuivre." +tutorial.window.title: "Création de la fenêtre" ui.action.copy: Copier ui.action.navigate: Naviguer ui.action.open: Ouvrir @@ -542,12 +530,12 @@ ui.content.tutorial: Tutoriel ui.contents.close: Fermer la table des matières ui.contents.open: Ouvrir la table des matières ui.contents.title: Table des matières -ui.footer.caption: RHI moderne pour .NET. +ui.footer.caption: "RHI moderne pour .NET" ui.footer.label: Pied de page ui.language.label: Langue ui.language.unavailable: Non traduit ui.members.clear: Effacer la recherche de membres -ui.members.close: Fermer le chercheur de membres +ui.members.close: "Fermer la recherche de membres" ui.members.empty: Aucun membre correspondant. ui.members.open: Aller au membre ui.members.placeholder: Nom ou signature… @@ -587,7 +575,7 @@ ui.reference.properties: Propriétés ui.reference.related: Voir aussi ui.reference.relationships: Héritage et métadonnées ui.reference.remarks: Remarques -ui.reference.returns: Retourne +ui.reference.returns: "Valeur de retour" ui.reference.structs: Structures ui.reference.typeParameters: Paramètres de type ui.reference.value: Valeur diff --git a/documents/locales/fr-FR/translation.md b/documents/locales/fr-FR/translation.md index dba1c860..694b098b 100644 --- a/documents/locales/fr-FR/translation.md +++ b/documents/locales/fr-FR/translation.md @@ -8,6 +8,16 @@ La navigation, l’ordre des chapitres, les ancres, les liens, la mise en forme, Modifier uniquement les valeurs du fichier `strings.yml` de cette langue. L’ensemble des clés doit être strictement identique à celui de l’anglais. Ne pas ajouter, supprimer ou renommer de clés de sa propre initiative, même si les textes semblent identiques ou ne sont pas encore apparus dans l’interface. Signaler toute erreur de l’original aux responsables du projet en indiquant la clé concernée. Corriger d’abord la source anglaise et les pages communes, puis les traductions. +## Style et contexte + +Adopter le ton d’un manuel technique : précis, sobre et accessible. Expliquer les relations entre opérations avant leurs contraintes. Dans les tutoriels, conserver des étapes explicites et des résultats vérifiables. La rigueur ne demande ni tournures passives ni phrases inutilement longues. + +Réviser chaque article dans son ordre de lecture, avec les paragraphes voisins, tableaux et extraits de code. Les clés délimitent le stockage, pas les unités de traduction. Vérifier les accords et les prépositions des liens et fragments mis en valeur dans la phrase complète. + +Ne pas terminer par un point les titres, libellés, textes courts visibles de l’accueil et légende du pied de page. Conserver la ponctuation normale dans les paragraphes, diagnostics et instructions d’accessibilité. Employer un terme établi par notion, sans ajouter ponctuellement son équivalent anglais entre parenthèses. Préserver les identifiants d’API, fichiers et réglages. + +Conserver une phrase si elle explique l’opération en cours, un choix de conception, un résultat vérifiable ou une condition nécessaire. Supprimer les listes de fonctions inutilisées, les réserves générales et les prérequis répétés. Traduire les titres et les phrases découpées par la mise en forme comme un tout, dans l’ordre naturel du français. Les emplacements `{accent}` et `{lineBreak}` du titre d’accueil sont déplaçables : la présentation ne doit pas imposer la syntaxe anglaise. La suppression d’un passage et de ses clés est coordonnée par la maintenance dans le texte source, le balisage commun et tous les dictionnaires. + ## Texte et espaces réservés Traduire des phrases ou paragraphes complets dans un français technique clair et naturel. Préserver les conditions, négations, unités, étapes et contraintes de durée de vie. Ne pas ajouter de garanties techniques, de prérequis de plateforme, de versions de paquets ou de notes de version absents de l’original. Conserver les noms de produits, de paquets et de fichiers, ainsi que les identifiants C# et Slang, en respectant leur casse. diff --git a/documents/locales/ja-JP/strings.yml b/documents/locales/ja-JP/strings.yml index 09dc6e2d..2bb6213d 100644 --- a/documents/locales/ja-JP/strings.yml +++ b/documents/locales/ja-JP/strings.yml @@ -1,604 +1,592 @@ ### YamlMime:Resources -concepts.execution.context.description: "{graphicsContext} は 1 つのバックエンドデバイスを表し、そのグラフィックス、コンピュート、転送の各キューを提供します。ワークロード用のバッファー、テクスチャ、シェーダー、パイプラインは同じコンテキストを通じて作成してください。別のコンテキストによって作成されたリソースやハンドルを、このコンテキストのコマンドバッファーにそのままバインドすることはできません。" -concepts.execution.context.details: プラットフォームとプレゼンテーションサーフェスに適したバックエンドを選択してください。API は共有されますが、デバイスのサポート状況は依然として重要です。{capabilities} はデバイス名と、{rayTracingSupported} および {meshShadingSupported} フラグを公開します。{link} や {detail} サンプルのように、オプションのワークロードを作成する前に対応するフラグを確認してください。これらのフラグは、フォーマット、メモリ、またはプラットフォームの制限に関する完全なリストではありません。 -concepts.execution.context.details.detail: メッシュシェーディング -concepts.execution.context.details.link: レイトレーシング -concepts.execution.context.title: コンテキストがリソースとキューを接続する -concepts.execution.description: Zenith.NET アプリケーションは GPU リソースを作成し、それらを使用するコマンドを記録して、それらのコマンドをキューにサブミットします。GPU がサブミットを実行している間も CPU は処理を続行できます。記録呼び出しが戻った後でも、その処理が終了するまでリソースを有効に保ってください。 -concepts.execution.ownership.description: "ここでの所有権とは、破棄に対する責任を意味します。C# の参照はマネージドオブジェクトへの到達可能性を維持しますが、明示的な {dispose} がネイティブリソースを破棄することを防ぐわけではありません。同様に、バッファーを使用するコマンドをサブミットしても、そのバッファーの所有権がキューに移るわけではありません。" -concepts.execution.ownership.details: シャットダウン時には、新しい作業のサブミットを停止し、関係するすべてのキューでの最後の使用を待機し、アプリケーションのリソースを解放してから、コンテキストを破棄してください。コンテキストの破棄はその独自のキューや内部ヘルパーを解放しますが、アプリケーションのすべての作業を待機したり、アプリケーションが作成したすべてのリソースを解放したりするわけではありません。 -concepts.execution.ownership.guidance: レンダリング中も同じライフサイクルのルールを適用してください。リソースの最後の使用に対する完了値を保持し、そのバイトがいつ上書き可能になるか、またはリソースがいつ交換可能になるかを把握できるようにします。ビューと基盤となるリソースの有効期間については、{link} を参照してください。 -concepts.execution.ownership.guidance.link: リソース管理 -concepts.execution.ownership.table.applicationResources.object: アプリケーションが作成したリソース -concepts.execution.ownership.table.applicationResources.ownership: アプリケーションが最後の GPU 使用後に解放します。 -concepts.execution.ownership.table.commandBuffers.object: 借用したコマンドバッファー -concepts.execution.ownership.table.commandBuffers.ownership: キューが管理およびリサイクルします。 -concepts.execution.ownership.table.headings.object: オブジェクト -concepts.execution.ownership.table.headings.ownership: 誰が解放するか? -concepts.execution.ownership.table.queues.object: コンテキストキューとそのタイムライン -concepts.execution.ownership.table.queues.ownership: コンテキストとキューが管理します。 -concepts.execution.ownership.table.swapChainDrawable.ownership: スワップチェーンが管理します。 -concepts.execution.ownership.title: 所有権と GPU 完了を明確に区別する -concepts.execution.pipelines.description: グラフィックスパイプラインは、シェーダー、頂点入力レイアウト、頂点をプリミティブに組み立てるルール、アタッチメントフォーマット、レンダー状態を結合します。頂点、インデックス、定数データをバインドし、描画コマンドを発行する前に設定してください。そのアタッチメントフォーマットとサンプル数は、レンダーパスのアタッチメントと一致している必要があります。 -concepts.execution.pipelines.details: コンピュートパイプラインは、GPU スレッドのグループを起動するディスパッチ用のシェーダーエントリポイントを提供します。ディスパッチの前に、パイプラインとその定数を設定してください。コンピュートディスパッチはグラフィックスレンダーパスの外側に配置します。パイプラインの変更は、後続のコマンドがその入力を解釈する方法の変更を意味します。選択したパイプラインに必要なデータは、使用する前にバインドしてください。 -concepts.execution.pipelines.guidance: "{link} は完全なグラフィックスシーケンスを示しています。{detail} はディスパッチを記録し、その後に結果を表示するグラフィックスパスを記録します。" -concepts.execution.pipelines.guidance.detail: コンピュートサンプル -concepts.execution.pipelines.guidance.link: 三角形の描画コールバック -concepts.execution.pipelines.title: パイプラインがコマンドによるデータの解釈方法を決定する -concepts.execution.queues.description: 1 つのフレームで描画、コンピュート、コピーを組み合わせる場合は、{graphicsQueue} から始めてください。依存する作業を 1 つのキューにまとめることで、その順序付けを追跡しやすくなります。 -concepts.execution.queues.details: "キューは、まとめられたコマンドを受け付けて実行します。別々のキューが別々のハードウェアエンジンに対応するとは限らないため、同時に実行されるとは限りません。処理を重ねて進める利点がある場合に別のキューを使い、一方のキューが他方の結果を使う場合は明示的な依存関係を設定してください。" -concepts.execution.queues.guidance: 後続のコマンドが先行の書き込みに依存する場合、アプリケーションはそれらの書き込みが後続のコマンドから利用可能であることも保証しなければなりません。両方のコマンドバッファーを同じキューにサブミットするだけでは、そのような依存関係が自動的にすべて確立されるわけではありません。コマンドは異なる GPU ステージを使用する可能性があり、後続のアクセスにはバリアやテクスチャ遷移が必要になる場合があります。{link} で、サブミットの順序とリソースの可視性の違いについて説明しています。 -concepts.execution.queues.guidance.link: 同期 -concepts.execution.queues.table.computeQueue.workToRecord: グラフィックスレンダーパスを含まない、コンピュートディスパッチおよび互換性のある転送作業。 -concepts.execution.queues.table.graphicsQueue.workToRecord: レンダーパスと描画、およびフレームで使用されるコンピュート操作と転送操作。 -concepts.execution.queues.table.headings.queue: キュー -concepts.execution.queues.table.headings.workToRecord: 記録する作業 -concepts.execution.queues.table.transferQueue.workToRecord: 描画やコンピュートディスパッチを含まない、アップロード、ダウンロード、コピーの作業。 -concepts.execution.queues.title: 実行する作業に応じたキューを選択する -concepts.execution.recording.context: キューは完了をポーリングし、終了したコマンドバッファーをリサイクルします。新しい記録ごとに {queueCommandBuffer} を呼び出してください。リサイクルされたインスタンスが返される場合があります。借用したコマンドバッファーを独自に破棄したり、2 回サブミットしたり、サブミット後も記録を続けたりしないでください。特定のコマンドバッファーへの記録は一度に 1 つのスレッドから行ってください。キューの内部ロックは、コマンドバッファーへの同時編集を保護しません。 -concepts.execution.recording.description: "{queueCommandBuffer} は、すでに記録が開始された {commandBuffer} を返します。コマンドとその依存関係を記録し、一度 {submit} を呼び出します。サブミットにより記録が終了し、そのキュー上の完了ポイントを識別する {timelineValue} が返されます。" -concepts.execution.recording.details: "たとえば、{commandBuffer} にフレームを記録した後、三角形のチュートリアルでは次のようにサブミットして完了を待機します:" -concepts.execution.recording.guidance: "{submit} は作業をスケジュールし、{wait} はそのサブミットが完了するまで CPU の続行を待機させます。描画の記録、レンダーパスの終了、コマンドバッファーのサブミットはそれぞれ別の操作です。描画の記録もパスの終了も、GPU を待機することはありません。" -concepts.execution.recording.title: 記録してもコマンドは実行されない -concepts.execution.title: 実行モデル -concepts.platforms.description: アプリケーションがネイティブウィンドウとフレームループを自ら所有するか、UI レンダリングコントロールを使用するかを選択します。その選択によって、誰が出力テクスチャを取得し、コマンドをサブミットし、結果を提示するかが決まります。出力テクスチャとは、現在のフレームの出力として使用されるテクスチャのことです。オフスクリーンのグラフィックスやコンピュート処理には、ウィンドウやスワップチェーンは不要です。 -concepts.platforms.frame.context: そのパスの内部にパイプラインバインディングと描画コマンドを追加してください。戻る前にパスを終了します。提供されたコマンドバッファーを独自にサブミットしたり個別に提示したりしないでください。また、コマンドバッファーや出力テクスチャを破棄しないでください。ハンドラーが出力テクスチャを別のレイアウトで使用する場合は、コントロールの最終遷移のために {colorAttachment} に戻してください。 -concepts.platforms.frame.description: 各統合機能は {iZenithView} を実装しています。アプリケーションはその {graphicsContext} を提供し、{updateRequested} でシーンデータを更新し、{renderEventArgs} を使用して {renderRequested} でレンダリングを記録します。 -concepts.platforms.frame.details: "コントロールが各フレームの一連の処理を管理します。出力テクスチャとコマンドバッファーを取得し、出力テクスチャを {colorAttachment} に遷移させ、ハンドラーを呼び出した後、そのフレームワークで必要なサブミットとプレゼンテーションを行います。" -concepts.platforms.frame.guidance: "コンテキストが割り当てられた {view} という名前の初期化済み {iZenithView} の場合、このハンドラーは完全なクリアパスを記録します。これには {usingZenithNET} が必要です:" -concepts.platforms.frame.notes: 各コントロールは各フレームの開始時に {undefined} から遷移するため、アプリケーションは出力テクスチャの以前の内容が保持されることに依存できません。フレームごとに必要な画像をクリアまたはレンダリングしてください。持続的な累積やキャッシュされたレンダリングはアプリケーションが所有するテクスチャに保持し、そのテクスチャをビュー経由で表示してください。 -concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat} は統合のデフォルトのカラーフォーマットを提供します。アタッチメントフォーマット、サンプル数、寸法を一致させる際は、実際のイベントの出力テクスチャを確認してください。" -concepts.platforms.frame.title: UI コントロールから提供されたフレームに記録する -concepts.platforms.integration.context: WinForms、WPF、および Windows の WinUI パスには Windows が必要です。MAUI アプリケーションにはターゲットプラットフォームのワークロードが必要であり、{useZenithView} を使用してコントロールハンドラーを登録する必要があります。{extensionsCs} を参照してください。フレームワークのサポートとバックエンドのサポートの両方が満たされている必要があります。 -concepts.platforms.integration.description: "各コントロールはイベントインターフェイスを共有していますが、すべてが同じ方法で提示されるわけではありません:" -concepts.platforms.integration.details: ビットマップリードバックは、UI が表示する前にレンダリングされたピクセルを CPU メモリにコピーします。共有テクスチャの相互運用はそのリードバックを回避しますが、GPU コピーと同期が依然として必要になる場合があります。したがって、共有の {renderRequested} インターフェイスが同じプレゼンテーションコストやネイティブ相互運用要件を意味するわけではありません。 -concepts.platforms.integration.guidance: "アプリケーションのフレームワーク用のパッケージを使用してください。例:" -concepts.platforms.integration.table.avalonia.integration: Avalonia -concepts.platforms.integration.table.avalonia.presentation: テクスチャにレンダリングし、ピクセルを {writeableBitmap} にダウンロードします。{zenithViewCs} および {surfaceCs} を参照してください。 -concepts.platforms.integration.table.headings.integration: 統合 -concepts.platforms.integration.table.headings.presentation: 画像が UI に届く仕組み -concepts.platforms.integration.table.maui.integration: .NET MAUI -concepts.platforms.integration.table.maui.presentation: Android、iOS、Mac Catalyst ではネイティブサーフェスを使用し、Windows では共有テクスチャコンポジションを使用します。{link} を参照してください。 -concepts.platforms.integration.table.maui.presentation.link: プラットフォーム実装 -concepts.platforms.integration.table.uno.integration: Uno パス -concepts.platforms.integration.table.uno.presentation: ピクセルを {writeableBitmap} にダウンロードします。{zenithViewUnoCs} を参照してください。 -concepts.platforms.integration.table.winForms.integration: WinForms -concepts.platforms.integration.table.winForms.presentation: コントロールの {hWND} 用に Zenith.NET スワップチェーンを作成します。{zenithViewCs} を参照してください。 -concepts.platforms.integration.table.winUI.integration: Windows 上の WinUI -concepts.platforms.integration.table.winUI.presentation: インポートされた共有 Direct3D 11 テクスチャにレンダリングし、{swapChainPanel} に接続されたコンポジションスワップチェーンにコピーします。{zenithViewWinUICs} を参照してください。 -concepts.platforms.integration.table.wpf.integration: WPF -concepts.platforms.integration.table.wpf.presentation: 共有 Direct3D 11 テクスチャをインポートし、Direct3D 相互運用を介して {d3DImage} によって表示されるサーフェスにコピーします。{surfaceCs} を参照してください。 -concepts.platforms.integration.title: フレームワークだけでなくプレゼンテーションパスも選択する -concepts.platforms.lifecycle.context: UI ビューの場合、一致するレンダリングリソースを作成する際に、イベントの出力テクスチャの {descWidth}、{descHeight}、{descFormat}、{descSampleCount} を使用してください。コントロールがその出力テクスチャの解像度を決定します。論理寸法やディスプレイスケールが常にテクスチャ寸法と等しいとは仮定しないでください。 -concepts.platforms.lifecycle.description: ネイティブスワップチェーンの場合、ピクセル単位のフレームバッファーサイズを渡してください。ディスプレイのスケーリングが有効な場合、論理単位で表されたウィンドウサイズとは異なることがあります。サイズがゼロのフレームバッファーはスキップし、ピクセルサイズが変化したときにスワップチェーンをリサイズし、フレームごとに {swapChainDrawable} を取得してください。出力テクスチャはスワップチェーンが所有しており、プレゼンテーションやリサイズ後に変更される可能性があります。 -concepts.platforms.lifecycle.details: "{swapChainResize} は既存のサーフェスの寸法を変更します。{swapChainRefresh} はネイティブハンドルを含むサーフェス記述を置き換えます。どちらの操作の前にも、影響を受けるリソースの未完了の使用を完了させてください。ネイティブプレゼンテーションターゲットを破棄する前に、スワップチェーンを解放してください。" -concepts.platforms.lifecycle.guidance: ウィンドウに従ってサイズが変わるアプリケーション所有の深度テクスチャやオフスクリーンテクスチャを再作成し、そのハンドルを含む定数を更新してください。アタッチメントフォーマットとサンプル数に互換性が維持されている場合、サイズ変更をまたいでパイプラインを使い続けることができます。{link} は深度テクスチャを置き換えながらパイプラインを維持します。 -concepts.platforms.lifecycle.guidance.link: 回転する立方体のレンダラー -concepts.platforms.lifecycle.title: 出力テクスチャのサイズとライフサイクルをホストに委ねる -concepts.platforms.ownership.description: アプリケーションは、割り当てたコンテキストおよびレンダリングのために作成したリソースを所有します。コントロールは独自のプレゼンテーションリソースを所有します。ビューの {graphicsContext} プロパティを変更すると、スケジューラはコントロールのリソースを再作成しますが、新しいコンテキスト用にアプリケーションのパイプライン、バッファー、テクスチャを再作成するわけではありません。 -concepts.platforms.ownership.details: リソースの置き換えはビューのフレームライフサイクルと協調させてください。アプリケーションのリソースや割り当てられたコンテキストを破棄する前に、ビューのフレームアクティビティを停止し、未完了の GPU 使用を終了させてください。ビューを削除しても、コンテキストの所有権がコントロールに移るわけではありません。 -concepts.platforms.ownership.guidance: 共有の {frameSchedulerCs} は、ビューの UI ディスパッチャーを介してフレーム処理をディスパッチします。フレームハンドラーはフレームの更新と記録に集中させてください。そこでの長時間の CPU 処理は UI の遅延にもつながります。 -concepts.platforms.ownership.title: アプリケーションリソースをコントロールの所有権外に保つ -concepts.platforms.surface.context: ウィンドウライブラリや UI フレームワークが特定のオペレーティングシステムをサポートしていても、そこで選択した GPU バックエンドが利用可能であるとは限りません。デバイス機能、ドライバー、およびネイティブサーフェスのサポートが一致している必要があります。オプションのレイトレーシングやメッシュシェーディングのワークロードを作成する前に、{contextCapabilities} で確認してください。 -concepts.platforms.surface.description: "{link} は Silk.NET を使用してウィンドウを作成し、イベントを処理します。Zenith.NET は、{surface} の記述と {swapChain} を介してそのウィンドウに接続します。サーフェスにはネイティブハンドルとサイズが含まれます。その記述を構築しても、オペレーティングシステムのウィンドウが作成または所有されるわけではありません。" -concepts.platforms.surface.description.link: 三角形チュートリアル -concepts.platforms.surface.details: "ハンドルは選択したバックエンドと一致している必要があります:" -concepts.platforms.surface.guidance: チュートリアルの {appCs} は Windows、macOS、X11 の選択肢を示しています。その Linux ホストは Xlib ハンドルを提供するため、Wayland セッションで使用するには XWayland が必要です。ネイティブ Wayland アプリケーションの場合は、{surfaceWayland} を通じて異なるハンドルを提供することになります。 -concepts.platforms.surface.table.android.backend: Android 上の Vulkan。 -concepts.platforms.surface.table.apple.backend: Apple プラットフォーム上の Metal。 -concepts.platforms.surface.table.headings.backend: バックエンドパス -concepts.platforms.surface.table.headings.factory: サーフェスファクトリ -concepts.platforms.surface.table.headings.handles: ホストから提供されるハンドル -concepts.platforms.surface.table.wayland.backend: ネイティブ Wayland ホストを使用した Vulkan。 -concepts.platforms.surface.table.wayland.handles: Wayland ディスプレイおよびサーフェス -concepts.platforms.surface.table.win32.backend: Windows 上の DirectX 12 または Vulkan。 -concepts.platforms.surface.table.xlib.backend: X11 または XWayland を使用した Linux 上の Vulkan。 -concepts.platforms.surface.table.xlib.handles: X11 ディスプレイおよびウィンドウ -concepts.platforms.surface.title: アプリケーションがプレゼンテーションを所有する場合はネイティブサーフェスを提供する -concepts.platforms.title: プラットフォーム統合 -concepts.resources.allocation.context: "独自のアロケーターが必要でなければ、まずコンテキストで作成するリソースを使ってください。ヒープを使う場合は、それらを使用するすべての GPU 処理が完了してから、配置したリソースを先に解放し、最後にヒープ自体を解放します。" -concepts.resources.allocation.description: "{heap} は、明示したバイトオフセットにリソースを配置するためのメモリを提供します。アプリケーションがオフセットを選び、使用中の領域を追跡します。" -concepts.resources.allocation.details: "配置前に、正確なバッファーまたはテクスチャの記述を指定して {contextGetSizeAndAlignment} を呼び出します。返されたアライメントの倍数をオフセットに選び、返されたサイズを確保して、リソースがヒープの総バイト数の範囲内に収まるようにしてください。使用中の割り当て領域は重ねないでください。テクスチャの格納にはバックエンド固有のパディングやアライメントが含まれることがあるため、ピクセル数と 1 ピクセル当たりのバイト数の積では割り当てサイズを求められません。" -concepts.resources.allocation.guidance: "配置したバッファーの常駐特性は、ヒープの常駐特性と一致させてください。ここで扱う通常の GPU テクスチャには GPU 専用ヒープを使います。サイズとアライメントは配置の要件であり、すべてのバックエンドで任意のリソースを任意のヒープに配置できるという保証ではありません。" -concepts.resources.allocation.title: 割り当て制御が必要な場合はヒープにリソースを配置する -concepts.resources.bufferUsages.table.constant.role: 定数バッファーバインディングを介して読み取られるシェーダーパラメーター。 +concepts.execution.context.description: "{graphicsContext} は特定のバックエンドを介してアプリケーションを GPU デバイスに接続し、描画、計算、転送のキューを提供します。一緒に使うリソースは同じコンテキストに属している必要があります。バッファー、テクスチャ、シェーダー、パイプラインとそのハンドルを、コンテキストをまたいでバインドすることはできません。" +concepts.execution.context.details: "{capabilities} はデバイス名と対応機能を提供します。レイトレーシングやメッシュシェーディング用のリソースを作成する前に、{rayTracingSupported} と {meshShadingSupported} で対応を確認します。{link}と{detail}のサンプルでは、初期化時にこの確認を行っています。" +concepts.execution.context.details.detail: "メッシュシェーディング" +concepts.execution.context.details.link: "レイトレーシング" +concepts.execution.context.title: "グラフィックスコンテキスト" +concepts.execution.description: "GPU の処理は CPU 側で準備します。アプリケーションがリソースを作成し、それらを使うコマンドを記録して、キューに送信します。送信後は GPU がコマンドを実行する間も CPU が処理を続けられます。リソースは GPU の実行が終わるまで保持する必要があります。" +concepts.execution.ownership.description: "所有権は誰がオブジェクトを解放するかを、GPU の完了はいつ解放できるかを決めます。C# の参照が残っていても、{dispose} を呼ぶとネイティブリソースは解放されます。コマンドを送信しても、そのリソースの所有権はキューへ移りません。" +concepts.execution.ownership.details: "終了時は新しい送信を止め、関係するすべてのキューでリソースの最後の使用が終わるのを待ちます。その後、アプリケーションのリソースを解放し、最後にコンテキストを解放します。コンテキストは自身のキューと内部の補助オブジェクトを解放するため、この処理はアプリケーションの作業が終わってから行います。" +concepts.execution.ownership.guidance: "描画中にデータを上書きしたりリソースを置き換えたりする場合は、それを使う処理の完了を追跡します。その使用が終わるのを待ってから、データを変更するか記憶領域を解放します。ビューとその参照先リソースの寿命は、{link}で説明します。" +concepts.execution.ownership.guidance.link: "リソース管理" +concepts.execution.ownership.table.applicationResources.object: "アプリケーションが作成したリソース" +concepts.execution.ownership.table.applicationResources.ownership: "アプリケーションが最後の GPU 使用後に解放します。" +concepts.execution.ownership.table.commandBuffers.object: "借用したコマンドバッファー" +concepts.execution.ownership.table.commandBuffers.ownership: "キューが管理して再利用します。" +concepts.execution.ownership.table.headings.object: "オブジェクト" +concepts.execution.ownership.table.headings.ownership: "解放の責任" +concepts.execution.ownership.table.queues.object: "コンテキストキューとそのタイムライン" +concepts.execution.ownership.table.queues.ownership: "コンテキストとキューが管理します。" +concepts.execution.ownership.table.swapChainDrawable.ownership: "スワップチェーンが管理します。" +concepts.execution.ownership.title: "所有権と寿命" +concepts.execution.pipelines.description: "グラフィックスパイプラインは、シェーダー、頂点入力レイアウト、プリミティブの組み立て、アタッチメントのフォーマット、描画状態を定義します。頂点、インデックス、定数のデータをバインドする前に選択してください。アタッチメントのフォーマットとサンプル数は、レンダーパスと一致させる必要があります。" +concepts.execution.pipelines.details: "コンピュートパイプラインは、ディスパッチで実行するシェーダーのエントリーポイントを選びます。グラフィックスのレンダーパス外で、パイプラインと定数をバインドしてからディスパッチします。" +concepts.execution.pipelines.guidance: "{link}ではグラフィックスの手順を、{detail}では計算結果を表示するパスの前にディスパッチを加える手順を確認できます。" +concepts.execution.pipelines.guidance.detail: "コンピュートサンプル" +concepts.execution.pipelines.guidance.link: "三角形の描画コールバック" +concepts.execution.pipelines.title: "パイプラインの状態" +concepts.execution.queues.description: "描画、計算、コピーを含むフレームでは、通常は {graphicsQueue} から始めます。依存する操作を同じキューにまとめると、順序を扱いやすくなります。" +concepts.execution.queues.details: "独立した処理を別々のキューに送信できますが、各キューが独立したハードウェア実行ユニットに対応するとは限りません。処理を並行して実行する利点がある場合に、キューを追加します。一方のキューがもう一方の生成データを使う場合は、送信間に明示的な依存関係を設定します。" +concepts.execution.queues.guidance: "同じキュー内でも、依存する操作にはバリアやテクスチャ遷移が必要になる場合があります。後のアクセスで、それ以前の書き込み結果を読み取れるようにするためです。このメモリ依存関係は送信順序とは別の要件であり、指定方法は{link}で説明します。" +concepts.execution.queues.guidance.link: "同期" +concepts.execution.queues.table.computeQueue.workToRecord: "コンピュートディスパッチと対応する転送操作。グラフィックスのレンダーパスは含みません。" +concepts.execution.queues.table.graphicsQueue.workToRecord: "レンダーパス、描画、計算、転送の操作。" +concepts.execution.queues.table.headings.queue: "キュー" +concepts.execution.queues.table.headings.workToRecord: "対応する操作" +concepts.execution.queues.table.transferQueue.workToRecord: "アップロード、リードバック、コピー。描画とコンピュートディスパッチは含みません。" +concepts.execution.queues.title: "キューの選択" +concepts.execution.recording.context: "キューは完了したコマンドバッファーを回収して再利用します。記録ごとに {queueCommandBuffer} で取得し、同時に記録するスレッドを一つに限定して、一度だけ送信します。送信後はキューに管理を任せ、変更、再送信、解放を行わないでください。" +concepts.execution.recording.description: "{queueCommandBuffer} が返す {commandBuffer} は、既に記録を開始しています。操作と依存関係を記録した後、一度だけ {submit} を呼びます。記録が終了して送信され、そのキューの完了点を示す {timelineValue} が返ります。" +concepts.execution.recording.details: "三角形のチュートリアルでは、{commandBuffer} にフレームを記録した後、次のように送信して完了を待ちます。" +concepts.execution.recording.guidance: "記録によってコマンド列を構築し、{submit} でその実行をスケジュールします。続いて {wait} を呼ぶと、送信した処理が完了するまで CPU スレッドが待機します。チュートリアルでは次のフレームを始める前に現在のフレームが終わるため、処理の順序を追いやすくなります。" +concepts.execution.recording.title: "記録と送信" +concepts.execution.title: "実行モデル" +concepts.platforms.description: "画面への提示は、アプリケーションまたは UI コントロールが管理します。この選択によって、フレームの出力テクスチャを取得し、コマンドを記録・送信して結果を提示する担当が決まります。この出力テクスチャを drawable と呼びます。" +concepts.platforms.frame.context: "パス内でパイプラインのバインドと描画を記録し、ハンドラーから戻る前にパスを終了します。コントロールがコマンドを送信し、結果を提示します。ハンドラーでは送信を行わず、渡されたコマンドバッファーや drawable を解放しないでください。drawable のレイアウトを変更した場合は、コントロールが最後の遷移を行えるよう、戻る前に {colorAttachment} に戻します。" +concepts.platforms.frame.description: "コントロールは {iZenithView} を実装します。アプリケーションは {graphicsContext} を設定し、{updateRequested} でシーンを更新し、{renderRequested} で渡された {renderEventArgs} を使ってコマンドを記録します。" +concepts.platforms.frame.details: "各フレームで、コントロールは drawable とコマンドバッファーを取得し、drawable を {colorAttachment} に遷移させてから、更新と描画のハンドラーを呼びます。その後、記録した処理を送信し、フレームワークの提示方式に従って画像を表示します。" +concepts.platforms.frame.guidance: "ファイルに {usingZenithNET} を追加します。{view} という名前の {iZenithView} が初期化され、グラフィックスコンテキストも設定済みなら、次のハンドラーで drawable をクリアできます。" +concepts.platforms.frame.notes: "最初の遷移は {undefined} を使うため、以前の画像内容は破棄できます。毎フレーム、画像全体を描画するかクリアしてください。蓄積する描画結果やキャッシュはアプリケーション所有のテクスチャに保存し、そのテクスチャをコントロールの drawable に描画します。" +concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat} は、これらの統合で使う既定のカラーフォーマットを提供します。" +concepts.platforms.frame.title: "UI コントロールでの描画" +concepts.platforms.integration.context: "WinForms、WPF、Windows 向け WinUI の統合は Windows 上で動作します。MAUI では対象プラットフォームのワークロードをインストールし、{extensionsCs} のように {useZenithView} でコントロールハンドラーを登録します。" +concepts.platforms.integration.description: "イベントのインターフェースは共通ですが、提示方式はフレームワークごとに異なります。" +concepts.platforms.integration.details: "GPU の画像を UI に届ける方法は、実装によって異なります。ビットマップへのリードバックでは、表示前にピクセルを CPU メモリへコピーします。共有テクスチャの相互運用では、この CPU コピーを省けますが、GPU コピーや同期が必要な場合があります。統合を選ぶ際は、共通の {renderRequested} イベントだけでなく、提示方法も検討してください。" +concepts.platforms.integration.guidance: "使用する UI フレームワークの統合パッケージを NuGet から追加します。Avalonia では {avaloniaPackage} を使います。" +concepts.platforms.integration.table.avalonia.integration: "Avalonia" +concepts.platforms.integration.table.avalonia.presentation: "テクスチャにレンダリングし、ピクセルを {writeableBitmap} にリードバックします。{zenithViewCs} および {surfaceCs} を参照してください。" +concepts.platforms.integration.table.headings.integration: "統合" +concepts.platforms.integration.table.headings.presentation: "提示方式" +concepts.platforms.integration.table.maui.integration: ".NET MAUI" +concepts.platforms.integration.table.maui.presentation: "Android、iOS、Mac Catalyst ではネイティブサーフェスを使用し、Windows では共有テクスチャコンポジションを使用します。{link} を参照してください。" +concepts.platforms.integration.table.maui.presentation.link: "プラットフォーム実装" +concepts.platforms.integration.table.uno.integration: "Uno パス" +concepts.platforms.integration.table.uno.presentation: "ピクセルを {writeableBitmap} にリードバックします。{zenithViewUnoCs} を参照してください。" +concepts.platforms.integration.table.winForms.integration: "WinForms" +concepts.platforms.integration.table.winForms.presentation: "コントロールの {hWND} 用に Zenith.NET スワップチェーンを作成します。{zenithViewCs} を参照してください。" +concepts.platforms.integration.table.winUI.integration: "Windows 上の WinUI" +concepts.platforms.integration.table.winUI.presentation: "インポートされた共有 Direct3D 11 テクスチャにレンダリングし、{swapChainPanel} に接続されたコンポジションスワップチェーンにコピーします。{zenithViewWinUICs} を参照してください。" +concepts.platforms.integration.table.wpf.integration: "WPF" +concepts.platforms.integration.table.wpf.presentation: "共有 Direct3D 11 テクスチャをインポートし、Direct3D 相互運用を介して {d3DImage} によって表示されるサーフェスにコピーします。{surfaceCs} を参照してください。" +concepts.platforms.integration.title: "フレームワークと提示方式" +concepts.platforms.lifecycle.context: "対応するアタッチメントを作るときは、描画イベントから渡された drawable の {descWidth}、{descHeight}、{descFormat}、{descSampleCount} を使います。このテクスチャの寸法が、実際の描画先の寸法です。コントロールのレイアウト上のサイズや表示倍率から推測しないでください。" +concepts.platforms.lifecycle.description: "スワップチェーンのサイズには、フレームバッファーの幅と高さをピクセル単位で使います。表示倍率によっては、ウィンドウの論理寸法とは異なります。どちらかの寸法がゼロの間は、描画もスワップチェーンのリサイズも行いません。{swapChainDrawable} は毎フレーム取得します。このテクスチャはスワップチェーンが所有し、提示やリサイズの後に置き換わることがあります。" +concepts.platforms.lifecycle.details: "フレームバッファーの寸法が変わったら、古い画像への GPU アクセスが終わるのを待ってから {swapChainResize} を呼びます。ネイティブの提示先を置き換える場合も、アクセスの完了後に、新しいサーフェス記述とハンドルを {swapChainRefresh} に渡します。終了時は、ネイティブの提示先を破棄する前にスワップチェーンを解放します。" +concepts.platforms.lifecycle.guidance: "アプリケーションの深度テクスチャやオフスクリーンテクスチャがウィンドウと同じ寸法を使う場合は、リサイズ時に再作成し、それらのハンドルを含む定数も更新します。アタッチメントのフォーマットとサンプル数が合っていれば、パイプラインは再利用できます。{link}では、テクスチャをリサイズしながらパイプラインを保持する構成を確認できます。" +concepts.platforms.lifecycle.guidance.link: "回転する立方体のレンダラー" +concepts.platforms.lifecycle.title: "スワップチェーンの寸法と寿命" +concepts.platforms.ownership.description: "設定したコンテキストと描画リソースはアプリケーションが、提示用リソースはコントロールが所有します。ビューの {graphicsContext} を変えると、スケジューラーは新しいコンテキストでコントロールのリソースを再作成します。アプリケーションのパイプライン、バッファー、テクスチャも、同じコンテキストで作り直してください。" +concepts.platforms.ownership.details: "描画リソースを置き換える前にビューのフレーム処理を止め、そのリソースを使う GPU 処理の完了を待ちます。その後、古いリソースやコンテキストを解放します。ビューを削除した場合も、設定したコンテキストの解放はアプリケーションが担当します。" +concepts.platforms.ownership.guidance: "共通の {frameSchedulerCs} は、ビューの UI ディスパッチャーを通してフレームハンドラーを実行します。ハンドラーはシーンデータの更新とコマンドの記録に集中させてください。そこで長い CPU 処理を行うと、UI の応答も遅れます。" +concepts.platforms.ownership.title: "アプリケーションとコントロールの所有権" +concepts.platforms.surface.description: "{link}では、Silk.NET がウィンドウを作成してイベントを処理します。Zenith.NET は {surface} 記述を通じてネイティブウィンドウのハンドルと寸法を受け取り、それを使って {swapChain} を作成します。OS のウィンドウは引き続きアプリケーションが管理します。" +concepts.platforms.surface.description.link: "三角形のチュートリアル" +concepts.platforms.surface.details: "サーフェスのハンドルはバックエンドと対応させます。" +concepts.platforms.surface.guidance: "{appCs} のサンプルホストは Windows、macOS、X11 に対応しています。Linux のウィンドウは Xlib ハンドルを渡すため、Wayland セッションで実行するには XWayland が必要です。ネイティブ Wayland アプリケーションでは、{surfaceWayland} にディスプレイとサーフェスのハンドルを渡します。" +concepts.platforms.surface.table.android.backend: "Android 上の Vulkan。" +concepts.platforms.surface.table.apple.backend: "Apple プラットフォーム上の Metal。" +concepts.platforms.surface.table.headings.backend: "バックエンドとプラットフォーム" +concepts.platforms.surface.table.headings.factory: "サーフェスファクトリ" +concepts.platforms.surface.table.headings.handles: "ホストから提供されるハンドル" +concepts.platforms.surface.table.wayland.backend: "ネイティブ Wayland ホストを使用した Vulkan。" +concepts.platforms.surface.table.wayland.handles: "Wayland ディスプレイおよびサーフェス" +concepts.platforms.surface.table.win32.backend: "Windows 上の DirectX 12 または Vulkan。" +concepts.platforms.surface.table.xlib.backend: "X11 または XWayland を使用した Linux 上の Vulkan。" +concepts.platforms.surface.table.xlib.handles: "X11 ディスプレイおよびウィンドウ" +concepts.platforms.surface.title: "ネイティブの提示サーフェス" +concepts.platforms.title: "プラットフォーム統合" +concepts.resources.allocation.context: "ヒープに配置したリソースは、その寿命全体にわたってヒープの記憶領域を使います。最後の GPU 使用が終わったら、リソースを先に解放し、その後ヒープを解放します。" +concepts.resources.allocation.description: "アプリケーションでメモリ割り当てを管理する場合は、{heap} を使います。ヒープは、指定したバイトオフセットにリソースを配置する記憶領域です。オフセットの選択と使用領域の管理はアプリケーションが行います。" +concepts.resources.allocation.details: "各リソースの作成に使うバッファーまたはテクスチャ記述を渡して、{contextGetSizeAndAlignment} を呼びます。返されたアラインメントの倍数となるオフセットに、返されたサイズ分の領域を確保します。領域はヒープ内に収め、使用中の別の割り当てと重ねてはいけません。テクスチャにはバックエンド固有のパディングが含まれる場合があるため、ピクセル数とピクセル当たりのバイト数だけでは割り当てサイズを算出できません。" +concepts.resources.allocation.guidance: "ヒープに配置するバッファーは、そのヒープと同じ常駐区分を指定します。テクスチャの格納には GPU 専用ヒープを使います。" +concepts.resources.allocation.title: "ヒープへの配置" +concepts.resources.bufferUsages.table.constant.role: "定数バッファーバインドを介して読み取られるシェーダーパラメーター。" concepts.resources.bufferUsages.table.headings.role: "役割" -concepts.resources.bufferUsages.table.headings.usage: 用途 -concepts.resources.bufferUsages.table.index.role: インデックス描画で使用されるインデックス。 +concepts.resources.bufferUsages.table.headings.usage: "用途" +concepts.resources.bufferUsages.table.index.role: "インデックス描画で使用されるインデックス。" concepts.resources.bufferUsages.table.indirect.role: "間接描画または間接ディスパッチのコマンドが読み取る引数。" concepts.resources.bufferUsages.table.none.role: "バッファーの用途フラグは宣言されていません。" -concepts.resources.bufferUsages.table.storageReadOnly.role: "読み取り専用のシェーダーバインディングを介してアクセスするバッファーデータ。" -concepts.resources.bufferUsages.table.storageReadWrite.role: "読み書き可能なシェーダーバインディングを介してアクセスするバッファーデータ。" +concepts.resources.bufferUsages.table.storageReadOnly.role: "読み取り専用のシェーダーバインドを介してアクセスするバッファーデータ。" +concepts.resources.bufferUsages.table.storageReadWrite.role: "読み書き可能なシェーダーバインドを介してアクセスするバッファーデータ。" concepts.resources.bufferUsages.table.transferDst.role: "GPU コピーの転送先ストレージ。" concepts.resources.bufferUsages.table.transferSrc.role: "GPU コピーの転送元データ。" -concepts.resources.bufferUsages.table.vertex.role: 描画のためにフェッチされる頂点属性。 -concepts.resources.bufferUsages.title: バッファーの用途 -concepts.resources.description: "リソースを使用する処理に合わせて、その記述を選びます。描画先となり、シェーダーでサンプリングされ、さらに CPU に読み戻されるテクスチャには、3 つすべての用途の宣言と、それらの処理間の同期が必要です。メモリの配置とリソースの有効期間も別途検討します。" -concepts.resources.memory.context: CPU アクセス可能なバッファーの場合、{map} は CPU にアドレスを与えます。GPU が同じバイトへのアクセスを停止するのを待つことはありません。同様に {unmap} も作業をサブミットしたり完了を待ったりしません。CPU 書き込み可能なデータを上書きする前に、以前の内容を必要とする GPU 読み取りを終了させてください。 -concepts.resources.memory.description: "{bufferDesc} には {residency} フィールドがあります。CPU と GPU がデータにどのようにアクセスするかに応じて選択してください:" -concepts.resources.memory.details: 常駐特性は、割り当てに対する想定された CPU アクセスを記述します。これは、すべてのデバイスが物理的に分離された CPU および GPU メモリを持つことを意味するわけではありません。三角形チュートリアルでは、小さな頂点バッファーを直接初期化するために {cpuWriteOnly} を使用します。大規模な静的メッシュは、代わりに 1 回限りのアップロードを伴う GPU 専用ストレージの恩恵を受けることができます。 -concepts.resources.memory.guidance: "{textureDesc} には常駐特性フィールドがありません。通常のコンテキスト作成テクスチャは GPU ストレージを使用します。その公開 API は CPU データ転送のためのアップロードおよびダウンロード操作を提供し、直接マッピングメソッドは公開しません。明示的なヒープは、以下で説明するように配置の制御を提供します。" -concepts.resources.memory.table.cpuReadOnly.cPUAccess: "GPU コピーの完了後にマップされたメモリを読み取る。" -concepts.resources.memory.table.cpuReadOnly.typicalRole: "GPU が生成したリードバックデータ" -concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "先行する GPU 読み取りの完了後にマップされたメモリへ書き込む。" +concepts.resources.bufferUsages.table.vertex.role: "描画のためにフェッチされる頂点属性。" +concepts.resources.bufferUsages.title: "バッファーの用途" +concepts.resources.description: "リソース記述は、アプリケーションが記憶領域をどう使えるかを定めます。例えば、描画先にし、シェーダーでサンプリングし、CPU に読み戻すテクスチャには、三つの操作に対応する用途フラグが必要です。メモリ配置は CPU のアクセス方法を決めます。データにアクセスできる時点や記憶領域を解放できる時点は、同期と寿命の管理によって決まります。" +concepts.resources.memory.context: "CPU からアクセスできるバッファーでは、{map} がデータを読み書きするためのアドレスを提供します。マッピングも {unmap} も、GPU の処理を待機しません。GPU が書いた結果を CPU で読む前にはその書き込みを待ち、同じバイトを書き換える前には、その領域への GPU アクセスが終わるのを待ちます。" +concepts.resources.memory.description: "{bufferDesc} の {residency} は、想定する CPU アクセスを指定します。" +concepts.resources.memory.details: "常駐区分は CPU アクセスの要件を表します。CPU と GPU が物理メモリを共有するシステムでも、この区分を使います。三角形では {cpuWriteOnly} を使い、小さな頂点バッファーを直接初期化します。大きな静的ジオメトリでは、GPU 専用の記憶領域へアップロードする方が適している場合があります。" +concepts.resources.memory.guidance: "コンテキストから直接作成したテクスチャは GPU の記憶領域を使うため、{textureDesc} に常駐区分のフィールドはありません。CPU メモリとのデータ交換には、アップロードとリードバックを使います。" +concepts.resources.memory.table.cpuReadOnly.cPUAccess: "読み取りのみ" +concepts.resources.memory.table.cpuReadOnly.typicalRole: "CPU へ読み戻すために GPU が生成したデータ" +concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "書き込みのみ" concepts.resources.memory.table.cpuWriteOnly.typicalRole: "CPU が供給または更新するデータ" -concepts.resources.memory.table.gpuOnly.cPUAccess: "アップロードバッファーまたはリードバックバッファーを介してバイトを転送する。" +concepts.resources.memory.table.gpuOnly.cPUAccess: "なし" concepts.resources.memory.table.gpuOnly.typicalRole: "静的ジオメトリと GPU の作業用データ" -concepts.resources.memory.table.headings.cPUAccess: CPU アクセス -concepts.resources.memory.table.headings.residency: 常駐特性 -concepts.resources.memory.table.headings.typicalRole: 典型的な役割 -concepts.resources.memory.title: "必要な CPU アクセスに合わせてメモリを選ぶ" -concepts.resources.textureUsages.description: "転送用の用途フラグは GPU コピーの方向を表します。CPU アクセスは、それとは別のメモリ配置の選択であり、後で説明します。" -concepts.resources.textureUsages.details: "用途フラグの組み合わせは複数の役割を宣言するだけで、処理の実行やアクセス順序の制御は行いません。テクスチャには適切な{link}が引き続き必要であり、選択したデバイス上でそのフォーマットが要求する用途をサポートしている必要があります。" +concepts.resources.memory.table.headings.cPUAccess: "想定する CPU アクセス" +concepts.resources.memory.table.headings.residency: "常駐区分" +concepts.resources.memory.table.headings.typicalRole: "典型的な役割" +concepts.resources.memory.title: "CPU アクセスとメモリ配置" +concepts.resources.textureUsages.description: "転送フラグは、リソースを GPU コピーの転送元または転送先として使うことを宣言します。CPU から直接アクセスできるかどうかは、メモリ配置によって別途決まります。" +concepts.resources.textureUsages.details: "用途フラグは、テクスチャを何に使えるかを宣言します。用途を切り替える際は、それに応じた{link}が必要です。また、使用するデバイスが、指定したテクスチャフォーマットでその用途をサポートしている必要があります。" concepts.resources.textureUsages.details.link: "レイアウトと同期" concepts.resources.textureUsages.table.colorAttachment.role: "レンダーパスのカラーアタッチメント。" concepts.resources.textureUsages.table.depthStencilAttachment.role: "レンダーパスの深度/ステンシルアタッチメント。" concepts.resources.textureUsages.table.headings.role: "役割" -concepts.resources.textureUsages.table.headings.usage: 用途 +concepts.resources.textureUsages.table.headings.usage: "用途" concepts.resources.textureUsages.table.none.role: "テクスチャの用途フラグは宣言されていません。" -concepts.resources.textureUsages.table.sampled.role: "サンプリング用テクスチャのバインディングを介して読み取るテクスチャデータ。" -concepts.resources.textureUsages.table.storage.role: "ストレージテクスチャのバインディングを介してシェーダーが読み書きするテクスチャデータ。" +concepts.resources.textureUsages.table.sampled.role: "サンプリング用テクスチャのバインドを介して読み取るテクスチャデータ。" +concepts.resources.textureUsages.table.storage.role: "ストレージテクスチャのバインドを介してシェーダーが読み書きするテクスチャデータ。" concepts.resources.textureUsages.table.transferDst.role: "GPU コピーの転送先画像ストレージ。" concepts.resources.textureUsages.table.transferSrc.role: "GPU コピーの転送元画像データ。" -concepts.resources.textureUsages.title: テクスチャの用途 -concepts.resources.title: リソース管理 -concepts.resources.transfers.context: ダウンロードは、内部のリードバックストレージへの GPU コピーを記録します。ライブラリは、完了したコマンドバッファーを再利用のためにリセットするときに、それらのバイトを指定された CPU 転送先にコピーします。サブミット値の {wait} が戻るまで、転送先の割り当てを維持し、マネージドメモリを固定したままにしてください。 -concepts.resources.transfers.description: "アップロードは CPU データを GPU リソースへコピーし、ダウンロードはリソースのデータを CPU メモリへコピーします。リソース自体のメソッドは、その転送が完了してから戻ります。" -concepts.resources.transfers.details: "これらの待機が対象とするのは、各メソッドがサブミットした転送です。別のキューですでにリソースを読み書きしていた処理との依存関係は検出しません。リソースのメソッドを呼ぶ前に、その依存関係を設定してください。マップされたメモリ経由の直接コピーでも、関連する GPU 処理の完了を確認するのは呼び出し側の責任です。" -concepts.resources.transfers.guidance: "コピーを他の作業と一緒に記録する必要がある場合は、{commandBufferUpload} または {commandBufferDownload} を使用してください。ポインターの有効期間はそれぞれ異なります:" -concepts.resources.transfers.item: "アップロードは呼び出し中に CPU 側の転送元を内部のアップロードバッファー、別名ステージングメモリへコピーします。転送元ポインターは、その呼び出しの間だけ有効であれば十分です。" -concepts.resources.transfers.notes: "テクスチャの行ストライドは CPU データの隣接する行の間のバイト距離であり、スライスストライドは隣接する深度スライスの間のバイト距離です。これらはテクスチャ内部の GPU メモリレイアウトを表しません。GPU 処理の完了とリードバックの違いは{link}を参照してください。" -concepts.resources.transfers.notes.link: 同期 -concepts.resources.transfers.table.bufferDownload.transfer: "{cpuReadOnly} の直接 CPU コピー。それ以外の場合は転送キューのダウンロードをサブミットして待機します。" -concepts.resources.transfers.table.bufferUpload.transfer: "{cpuWriteOnly} の直接 CPU コピー。それ以外の場合は転送キューのアップロードをサブミットして待機します。" -concepts.resources.transfers.table.headings.method: 方法 -concepts.resources.transfers.table.headings.transfer: "データの転送方法" +concepts.resources.textureUsages.title: "テクスチャの用途" +concepts.resources.title: "リソース管理" +concepts.resources.transfers.context: "リードバックでは、まず GPU データを内部の読み戻し領域へコピーします。ライブラリは完了したコマンドバッファーを回収するときに、そのデータを指定した CPU の宛先へコピーします。リードバックの送信値に対して {wait} を呼ぶと、両方の処理が完了します。戻るまで宛先を確保したままにし、管理対象メモリは固定してください。" +concepts.resources.transfers.description: "アップロードは CPU データを GPU リソースへコピーし、リードバックはリソースのデータを CPU メモリへコピーします。バッファーとテクスチャの次のメソッドは、転送を完了してから戻ります。" +concepts.resources.transfers.details: "呼び出す前に、他のキューとの競合するアクセスを解消します。メソッド内の待機は自身の転送だけを対象とし、他のキューとの依存関係を設定するものではありません。マッピングしたメモリを直接コピーする場合は、競合する GPU アクセスの完了を呼び出し側で待つ必要があります。" +concepts.resources.transfers.guidance: "他の GPU 処理とまとめて転送を送信するには、{commandBufferUpload} または {commandBufferDownload} で記録します。アップロードの転送元とリードバックの転送先では、メモリを有効に保つ必要のある期間が異なります。" +concepts.resources.transfers.item: "アップロードの呼び出し中に、ライブラリは元データをステージングメモリと呼ばれる内部の一時領域へコピーします。GPU は後でこの領域を読むため、アプリケーションの元ポインターが必要なのは、呼び出しが戻るまでです。" +concepts.resources.transfers.notes: "テクスチャ転送の行ストライドは、CPU データの隣り合う行の間隔をバイトで表します。スライスストライドは、深さ方向に隣り合うスライスの間隔です。転送処理はこれらの値を使い、CPU データとテクスチャの GPU 記憶領域との間でコピーします。GPU の完了と宛先へのコピーが別の段階になる理由は、{link}で説明します。" +concepts.resources.transfers.notes.link: "同期" +concepts.resources.transfers.table.bufferDownload.transfer: "{cpuReadOnly} では、マッピングしたメモリから直接コピーします。それ以外は転送キューにリードバックを送信し、完了を待ちます。" +concepts.resources.transfers.table.bufferUpload.transfer: "{cpuWriteOnly} では、マッピングしたメモリへ直接コピーします。それ以外は転送キューにアップロードを送信し、完了を待ちます。" +concepts.resources.transfers.table.headings.method: "方法" +concepts.resources.transfers.table.headings.transfer: "転送の動作" concepts.resources.transfers.table.textureTransfers.method: "{textureUpload} / {textureDownload}" -concepts.resources.transfers.table.textureTransfers.transfer: "グラフィックスキューを使い、選択したサブリソースをコピー用のレイアウトへ遷移させ、コピー後に指定された最終レイアウトへ遷移させて、完了を待ちます。" -concepts.resources.transfers.title: "即時に完了する転送とコマンドに記録する転送を選ぶ" -concepts.resources.usages.description: "{bufferUsages} と {textureUsages} は、リソースの想定される役割を宣言するフラグ列挙型です。これらはそれぞれ {bufferDescUsages} と {textureDescUsages} に割り当てられます。フラグ列挙型を使用すると、リソースに複数の役割がある場合に {value} を使用して複数のメンバーを組み合わせることができます。" -concepts.resources.usages.title: リソースを作成する前に必要な用途を宣言する -concepts.resources.views.description: "{bufferView} は、バッファー領域とその解釈を記述します。{textureView} は、互換性のあるテクスチャタイプ、フォーマット、およびサブリソース範囲を選択します。ビューは基盤となるストレージを共有します。データをコピーしたり、リソース作成時に欠落していた用途を追加したりすることはありません。また、その範囲はシェーダーの境界チェックのポータブルな保証にはなりません。" -concepts.resources.views.details: "デフォルトビューにはリソース自体のハンドルを使い、別の領域や互換性のある別の解釈が必要ならビューを作成します。GPU 処理が利用する可能性がある間は、ビューとその基になるリソースの両方への C# 参照を保持してください。リソースハンドルだけでは、どちらのオブジェクトも存続しません。最後の GPU 使用が完了してから解放してください。どちらかを置き換えたら、その古い{link}を含む定数も更新します。" +concepts.resources.transfers.table.textureTransfers.transfer: "コピーとテクスチャ遷移をグラフィックスキューに送信し、完了を待ちます。終了時には、選択したサブリソースが指定した最終レイアウトになります。" +concepts.resources.transfers.title: "即時転送とコマンドへの記録" +concepts.resources.usages.description: "{bufferUsages} と {textureUsages} は、リソースの用途を宣言するフラグ列挙型です。それぞれ {bufferDescUsages} と {textureDescUsages} に設定します。複数の用途には、必要なメンバーを {value} で組み合わせます。" +concepts.resources.usages.title: "リソースの用途" +concepts.resources.views.description: "{bufferView} はバッファーの範囲とデータの解釈方法を記述します。{textureView} はサブリソース範囲と、互換性のあるテクスチャ種別やフォーマットを選択します。どちらも既存の記憶領域を参照し、その作成時に宣言した用途に従います。ビューの範囲はアクセス範囲を示すものであり、シェーダーの境界検査が全バックエンドで同じように働くことを保証するものではありません。" +concepts.resources.views.details: "リソース自身のハンドルは既定のビューを提供します。別の範囲や互換性のある解釈方法を選ぶ場合は、独立したビューを作成します。ビューと元リソースはどちらも、GPU が使い終わるまで保持してください。ハンドルだけでは、どちらのオブジェクトも保持されません。いずれかを置き換えたら、古い{link}を含む定数も更新します。" concepts.resources.views.details.link: "リソースハンドル" -concepts.resources.views.guidance: "{link} はリサイズ時に置き換えられる深度テクスチャを示しています。{detail} は、書き込み可能な出力から分離して保持される入力テクスチャを示しています。どちらも、リソースの有効期間をそれを実際に使用する処理に従わせています。" -concepts.resources.views.guidance.detail: コンピュートサンプル -concepts.resources.views.guidance.link: 回転する立方体のレンダラー -concepts.resources.views.title: "ビューとその基になるリソースを共に使用可能に保つ" -concepts.shaders.binding.context: "コンピュートサンプルでは、{input} には {inputTextureSampledHandle} が、{output} には {outputTextureStorageHandle} が入力されます。Slang の型付き {descriptorHandle} は、各リソースへのアクセス方法をシェーダーに伝えます:" -concepts.shaders.binding.description: "{setConstantBuffer} は、現在のパイプラインの定数データ用にバッファーとバイトオフセットをバインドします。これは既存の GPU から見えるストレージをバインドするものであり、C# の値をアップロードするわけではありません。最初にバッファーを埋め、以前の GPU 読み取り側が終了していることを確認してから、そのバイトを上書きしてください。" -concepts.shaders.binding.details: "定数バッファーの前にパイプラインを設定してください。リソースがすでに作成およびアップロードされているコンピュートワークロードの場合、記録はこの順序を使用します:" -concepts.shaders.binding.guidance: このコード片は、記録中の {commandBuffer}、{computePipeline}、{bufferUsagesConstant} 用途でアップロードされた {constantBuffer}、およびワークロードのスレッドグループ数を前提としています。オフセット 0 はバッファーの先頭をバインドします。複数の定数データレコードが 1 つのバッファーを共有する場合、各レコードの開始オフセットはバックエンドのバインディングアライメントを満たす必要があります。その要件は、レコード内のフィールドレイアウトとは別個のものです。 -concepts.shaders.binding.notes: "{resourceHandle} は 2 つの 32 ビットフィールドを格納しますが、その解釈はバックエンドに属します。これをコンテキスト間で転送可能なユニバーサル記述子インデックス、アドレス、または値として扱わないでください。ハンドルはリソースを作成せず、欠落している用途を追加せず、同期も実行しません。" -concepts.shaders.binding.reference: リソースおよびそのハンドルの取得に使用したビューへの参照を保持し、シェーダーの最後の使用が完了した後にのみ破棄してください。テクスチャまたはビューを交換する際は、その古いハンドルを含む定数を更新してください。{link} でそのライフサイクルの関係について説明しています。 -concepts.shaders.binding.reference.link: リソース管理 -concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: シェーダー型 {t} の構造化要素を読み取ります。 -concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: シェーダー型 {t} の構造化要素の読み取りまたは書き込みを行います。 -concepts.shaders.binding.table.headings.access: 想定されるアクセス +concepts.resources.views.title: "ビューと参照先リソース" +concepts.shaders.binding.context: "コンピュートのサンプルでは、{input} に {inputTextureSampledHandle}、{output} に {outputTextureStorageHandle} を設定します。Slang の {descriptorHandle} の型引数が、各リソースへのアクセス方法を定めます。" +concepts.shaders.binding.description: "{setConstantBuffer} は、現在のパイプラインが定数を読み取るバッファーとバイトオフセットを選択します。シェーダーが使う前に、パラメーターのデータをその領域へアップロードします。以前の GPU 処理が同じ領域をまだ読んでいる場合は、完了を待ってから更新してください。" +concepts.shaders.binding.details: "コマンドバッファー、コンピュートパイプライン、データを設定した定数バッファー、スレッドグループ数が用意できたら、次の順にディスパッチを記録します。定数バッファーは選択中のパイプラインにバインドされるため、先にパイプラインを選択します。" +concepts.shaders.binding.guidance: "ここでは {commandBuffer} に、{computePipeline} と {constantBuffer} のパラメーターを使うディスパッチを記録しています。定数バッファーには {bufferUsagesConstant} の用途が必要で、オフセット 0 はその先頭を指定します。一つのバッファーを複数の定数レコードで共有する場合、各開始オフセットはバックエンドのバインド時アラインメント要件にも従います。これは、レコード内部のフィールド配置とは別の要件です。" +concepts.shaders.binding.notes: "{resourceHandle} は二つの 32 ビットフィールドを持ち、解釈はバックエンドに依存します。値はリソースを作成したコンテキスト内でのみ有効です。" +concepts.shaders.binding.reference: "ハンドルの取得元リソースとビューは、シェーダーの最後のアクセスが完了するまで保持します。テクスチャやビューの置換後は、古いハンドルを含む定数を更新してください。所有権の規則は{link}で説明します。" +concepts.shaders.binding.reference.link: "リソース管理" +concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: "シェーダー型 {t} の構造化要素の読み取り" +concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: "シェーダー型 {t} の構造化要素の読み書き" +concepts.shaders.binding.table.headings.access: "想定されるアクセス" concepts.shaders.binding.table.headings.cHandle: "C# ハンドル" -concepts.shaders.binding.table.headings.slangFieldType: Slang フィールド型 -concepts.shaders.binding.table.samplerHandle.access: テクスチャサンプリング状態を提供します。 -concepts.shaders.binding.table.textureSampledHandle.access: テクスチャを読み取ります。 -concepts.shaders.binding.table.textureStorageHandle.access: ストレージテクスチャの読み取りまたは書き込みを行います。 -concepts.shaders.binding.title: 定数バッファーとそれが記述するリソースをバインドする -concepts.shaders.compilation.description: "{zenithCompiler} は指定された Slang エントリポイントをコンパイルし、{shaderDesc} を返します。コンテキストの {graphicsApi} を使用して、シェーダーを作成するバックエンド (DirectX 12 用の DXIL、Metal 用の Metal ライブラリ、Vulkan 用の SPIR-V) をターゲットにします。" -concepts.shaders.compilation.details: "たとえば、既存の {context} があり、三角形のシェーダーが実行可能ファイルの横にコピーされている場合は次のようになります:" -concepts.shaders.compilation.guidance: "{vSMain} はシェーダーファイル内のエントリポイント名と完全に一致している必要があります。パイプライン作成中はシェーダーオブジェクトを有効に維持し、{link} に示されているようにパイプライン作成後に破棄してください。フレームごとに再コンパイルするのではなく、この初期化を 1 回実行します。" -concepts.shaders.compilation.guidance.link: 最初の三角形 -concepts.shaders.compilation.title: 選択したコンテキスト用にエントリポイントをコンパイルする -concepts.shaders.description: "シェーダーはアプリケーションから提供されたデータを受け取ります。頂点属性は個々の頂点を記述し、バッファーはパラメーターや配列を保持し、リソースハンドルはシェーダーがアクセスする他のリソースを識別します。C# の宣言と Slang の宣言は、それらの値の意味について一致している必要があります。フィールド名を一致させるだけでは不十分です。レイアウト、リソースアクセス、バインディングのすべてが一致している必要があります。" -concepts.shaders.dispatch.description: "{dispatch} はスレッドグループの数を受け取ります。コンピュートサンプルの {numthreads} エントリポイントは、グループあたり 16 × 16 スレッドを実行します。画像寸法を 16 で除算し、切り上げてグループ数を求めます。たとえば、17 × 19 の画像には 2 × 2 のグループが必要です。最後のグループに画像外のスレッドが含まれる可能性があるため、シェーダーはそのピクセル座標を画像寸法と照合してチェックします。" -concepts.shaders.dispatch.details: コンパイラは、宣言されたエントリポイントのグループサイズを {shaderDescThreadGroupSize} に格納します。{dispatch} に指定されたピクセル寸法をグループ数に変換することはありません。完全なバインディングとディスパッチの例については、シェーダー付きの {computeShaderRendererCs} を使用し、別のパスが出力を消費する前には {link} を使用してください。 -concepts.shaders.dispatch.details.link: 同期 -concepts.shaders.dispatch.title: ピクセルではなくスレッドグループをディスパッチする -concepts.shaders.layout.context: "{link} はそのオフセットを明示しています。この宣言にはスコープ内に {systemRuntimeInteropServices} と {zenithNET} が必要です:" +concepts.shaders.binding.table.headings.slangFieldType: "Slang フィールド型" +concepts.shaders.binding.table.samplerHandle.access: "テクスチャのサンプリング状態" +concepts.shaders.binding.table.textureSampledHandle.access: "テクスチャの読み取り" +concepts.shaders.binding.table.textureStorageHandle.access: "ストレージテクスチャの読み書き" +concepts.shaders.binding.title: "定数バッファーとリソースハンドル" +concepts.shaders.compilation.description: "{zenithCompiler} は Slang の指定エントリーポイントを {shaderDesc} にコンパイルします。コンテキストの {graphicsApi} に応じ、DirectX 12 には DXIL、Metal には Metal ライブラリ、Vulkan には SPIR-V を生成します。" +concepts.shaders.compilation.details: "{context} という名前のグラフィックスコンテキストを作成してから、実行ファイルと同じディレクトリにコピーした三角形のシェーダーをコンパイルします。" +concepts.shaders.compilation.guidance: "エントリーポイント名 {vSMain} は、シェーダーファイル内の宣言と一致させます。シェーダーのコンパイルとパイプラインの作成は初期化時に行い、描画中はパイプラインを再利用します。作成が終われば、{link}で示すようにシェーダーオブジェクトを解放できます。" +concepts.shaders.compilation.guidance.link: "最初の三角形" +concepts.shaders.compilation.title: "シェーダーのコンパイル" +concepts.shaders.description: "C# と Slang の宣言では、各値をどこに格納し、シェーダーがどうアクセスするかを一致させます。頂点入力レイアウトは頂点属性を、シェーダーバッファーの宣言はパラメーターや配列を記述します。リソースハンドルは、シェーダーが使うリソースを識別します。" +concepts.shaders.dispatch.description: "{dispatch} は、実行するスレッドグループ数を指定します。コンピュートサンプルでは {numthreads} を宣言しているため、一グループは 16 × 16 スレッドです。画像の幅と高さをそれぞれ 16 で割って切り上げると、画像全体を覆えます。17 × 19 の画像には 2 × 2 グループが必要です。シェーダーで各スレッドの座標を調べ、画像の外側なら処理を省きます。" +concepts.shaders.dispatch.details: "宣言したグループサイズは {shaderDescThreadGroupSize} から取得でき、{dispatch} に渡すグループ数の計算に使えます。計算の全体は {computeShaderRendererCs} で確認できます。ディスパッチ後の画像へのアクセスは、{link}の要件に従います。" +concepts.shaders.dispatch.details.link: "同期" +concepts.shaders.dispatch.title: "スレッドグループ" +concepts.shaders.layout.context: "{link}では、画像の寸法と二つのテクスチャハンドルを使ってこの配置を示しています。各フィールドの開始位置はオフセットで明示します。次の宣言では {systemRuntimeInteropServices} と {zenithNET} の名前空間を使用します。" concepts.shaders.layout.context.link: "コンピュートサンプルの C# 定数" -concepts.shaders.layout.description: "頂点入力の場合、パイプラインの {inputLayout} がフォーマット、オフセット、ストライド、セマンティクスを記述します。三角形の {float3} 位置に続く {float4} 色は 28 バイトを占め、色はバイト 12 にあります。{inputLayoutAdd} はこのパックされたレイアウトを計算します。C# の構造体を検査するわけではありません。C# フィールドにパディングが含まれている場合は、フィールドがパックされていると仮定せずに、一致するレイアウトを提供してください。" -concepts.shaders.layout.details: "定数バッファーはシェーダーパラメーターを保持し、構造化バッファーは宣言された型の要素の配列を保持します。どちらも Slang の宣言に従って読み取られます。{inputLayout} は使用しません。パディングを含め、コンパイルされたシェーダー表現のフィールドオフセットと要素サイズを確認してください。アンマネージド C# 型はバイト単位でのコピーに適していますが、それだけでシェーダー型と一致することが証明されるわけではありません。特に、頂点の密集した {float3} レイアウトをすべてのシェーダーバッファーに適用しないでください。" -concepts.shaders.layout.guidance: リソースハンドルは、既存のリソースを参照する小さな値です。ハンドルを定数バッファーにコピーしても、リソースの内容はコピーされません。 -concepts.shaders.layout.notes: "{computeShaderSlang} 内の対応する宣言は次のとおりです:" -concepts.shaders.layout.reference: "寸法が最初の 8 バイトを占め、その後に 2 つの 8 バイトリソースハンドルが続きます。C# サンプルは合計 256 バイトを予約しています。そのサイズはサンプルが選択したストレージサイズであり、すべての Slang 構造体や定数ペイロードが 256 バイトを占めるという規則ではありません。合計サイズをパディングしても、間違ったオフセットにあるフィールドは修正されません。" -concepts.shaders.layout.title: 頂点入力とシェーダーデータには異なるレイアウト規則がある -concepts.shaders.matrices.description: コンパイラは、各行の要素をまとめて格納する行優先 (row-major) の行列ストレージを要求します。{link} は 3 つの {matrix4x4} 値をオフセット 0、64、128 に配置します。その {detail} は、モデル、ビュー、プロジェクションの順序で {mulVectorMatrix} を使用します。 -concepts.shaders.matrices.description.detail: シェーダー -concepts.shaders.matrices.description.link: 回転する立方体のレンダラー -concepts.shaders.matrices.details: 格納順序は行列要素がどのようにメモリを占有するかを決定し、乗算順序は変換を決定します。両側の一貫性を維持してください。これら 2 つの選択を確認せずに転置を追加すると、別の不一致を招きながら 1 つの不一致を覆い隠してしまう可能性があります。 -concepts.shaders.matrices.title: 行列の格納と乗算の一貫性を維持する -concepts.shaders.title: シェーダーデータとバインディング -concepts.synchronization.backends.description: DirectX 12 と Vulkan は、レイアウトおよびアクセス情報とともにテクスチャ遷移をエンコードします。Metal は Zenith.NET の {transition} 実装において操作を持ちません。Metal は記録された作業をレンダーエンコーダーおよびコンピュートエンコーダーにグループ化します。バックエンドはこれらのグループを終了するときに可視性バリアを挿入し、先行の書き込みを後続の作業で利用可能にします。明示的な {barrier} 呼び出しは、同じエンコーダー内の連続するコンピュートディスパッチなどの依存関係を処理します。 -concepts.synchronization.backends.details: この違いはワークロードを変更する際に重要になります。{link} では、ディスパッチの後にグラフィックスレンダーパスが続き、Metal 上でもエンコーダー境界が作成されます。2 つの依存するコンピュートディスパッチは、テクスチャの宣言されたレイアウトを変更するだけではその境界を作成しません。共有 API で要求される遷移を維持し、実際のプロデューサーコマンドとコンシューマーコマンドの間の依存関係を個別に特定してください。 -concepts.synchronization.backends.details.link: コンピュートサンプル -concepts.synchronization.backends.title: 遷移はすべてのバックエンドで同一ではない -concepts.synchronization.barriers.context: "{barrierStagesAll} はより広いスコープであり、自動依存関係検出機能ではありません。処理を実際にカバーするステージを選択し、それらの操作をサポートするキューでのみ使用してください。" -concepts.synchronization.barriers.description: "2 つのコンピュートディスパッチを考えてみましょう。1 つ目がシミュレーションデータを書き込み、2 つ目が次のステップを実行するためにそのデータを読み取ります。両方ともストレージバッファーを使用するため、変更すべきテクスチャレイアウトはありません。コマンドバッファー上のディスパッチの間に次を挿入します:" -concepts.synchronization.barriers.details: 第 1 引数はプロデューサーステージを識別し、第 2 引数はコンシューマーステージを識別します。バリアは、GPU 上に対応する実行およびメモリの依存関係を確立します。バックエンドはそれらのステージを実行規則およびメモリアクセス規則に変換します。このバリアはテクスチャのレイアウトを変更せず、デバイス上のすべての処理を待機するわけでもありません。 -concepts.synchronization.barriers.guidance: "{link} は依存するディスパッチ間でこのパターンを使用しています。依存関係が発生する場所にバリアを配置してください。コンシューマーがすでに記録された後に配置されたバリアは、そのコンシューマーを先行のプロデューサーの後に順序付けることはできません。" -concepts.synchronization.barriers.guidance.link: FluidTank シミュレーション -concepts.synchronization.barriers.title: バリアで依存するコマンドを順序付ける -concepts.synchronization.dependencies.description: 共有リソースごとに、最初にアクセスする操作、それに続く操作、およびいずれかのアクセスが書き込みを行うかどうかを特定します。同じデータを 2 回読み取る場合、内容を保護するための順序付けは不要ですが、レイアウト変更やプレゼンテーションによって他の要件が課されることがあります。書き込みに続く読み取り、読み取りに続く上書き、または 2 回の書き込みには依存関係が必要になる場合があります。 -concepts.synchronization.dependencies.details: "次に、それらの操作が実行される場所に応じたメカニズムを選択します:" -concepts.synchronization.dependencies.guidance: "これらの仕組みは関連していますが、互いの代わりにはなりません。コマンドを順にサブミットするだけでは、すべてのメモリ依存関係を満たせません。キューの待機は新しいテクスチャレイアウトを宣言せず、コマンドバリアは呼び出し元の CPU スレッドを待機させません。" -concepts.synchronization.dependencies.table.cpuAccess.mechanism: 該当する完了値に対して {wait} を呼び出します。 -concepts.synchronization.dependencies.table.cpuAccess.situation: データへのアクセスまたは解放の前に CPU が待機する必要がある場合 -concepts.synchronization.dependencies.table.crossQueue.mechanism: その {timelineValue} をコンシューマー側のコマンドバッファーの {submit} に渡します。 -concepts.synchronization.dependencies.table.crossQueue.situation: 別のキューでのサブミットがデータを生成する場合 -concepts.synchronization.dependencies.table.headings.mechanism: メカニズム -concepts.synchronization.dependencies.table.headings.situation: 状況 -concepts.synchronization.dependencies.table.layoutChange.mechanism: 以前のレイアウトと次のレイアウトを指定した {commandBufferTransition}。 -concepts.synchronization.dependencies.table.layoutChange.situation: テクスチャサブリソースの使用方法の変更 -concepts.synchronization.dependencies.table.pipelineStages.mechanism: プロデューサーステージとコンシューマーステージを指定した {commandBufferBarrier}。 -concepts.synchronization.dependencies.table.pipelineStages.situation: コマンドストリーム内の依存する GPU ステージ -concepts.synchronization.dependencies.title: プロデューサーとコンシューマーから始める -concepts.synchronization.description: 先行のコマンドによって書き込まれたデータを読み取るコマンドは、それらの書き込みが完了し、自身に対して可視化されていることに依存します。書き込み側がプロデューサーであり、読み取り側がコンシューマーです。CPU も共有データの読み取り、上書き、解放の前に完了ポイントを必要とします。Zenith.NET は、これらの異なる依存関係のためにバリア、テクスチャ遷移、タイムラインを提供します。 -concepts.synchronization.layouts.context: "{undefined} は、以前の内容を保持する必要がないことを意味します。これは新しい画像や完全にクリアされるアタッチメントに適しています。内容が読み込まれたり、サンプリングされたり、蓄積されたりする画像のレイアウト追跡を回避するための手段ではありません。" -concepts.synchronization.layouts.description: "用途フラグはテクスチャがサポートする役割を記述します。{textureLayout} は、特定の操作のために特定のサブリソースがどのようにアクセスされるかを記述します。サブリソースとは、選択されたミップレベルと配列レイヤーです。そのレイアウトを変更することでそのアクセスの準備が行われますが、テクスチャが異なるピクセルフォーマットに変換されるわけではありません。たとえば、コンピュートサンプルは {storage} レイアウトで出力テクスチャを書き込み、その後グラフィックスパスでそれをサンプリングします。それらの使用の間に次を記録します:" -concepts.synchronization.layouts.details: このコード片は、{outputTexture} が {sampledStorage} 用途で作成され、その選択されたサブリソースが {storage} レイアウトにあることを前提としています。{default} はミップレベル 0 と配列レイヤー 0 を選択します。この操作は、テクスチャのすべてのミップやレイヤーを遷移させるわけではありません。 -concepts.synchronization.layouts.guidance: アプリケーションが以前のレイアウトを提供します。{transition} はアプリケーションから見えるレイアウトトラッカーを保持せず、先行のコマンドからその値を推測することもありません。リソースがレンダリングステージ間を通過する場所では、常にレイアウトを追跡してください。 -concepts.synchronization.layouts.title: 各テクスチャサブリソースのレイアウトを追跡する -concepts.synchronization.readback.description: "{isCompleted} は、GPU タイムラインが値に達したかどうかのみを問い合わせます。それ自体がコマンドバッファーを回収したり、ステージングされたダウンロードをアプリケーションの宛先ポインターにコピーしたりするわけではありません。" -concepts.synchronization.readback.details: "{commandBufferDownload} は、まず内部リードバックストレージへのコピーを記録します。完了したコマンドバッファーを再利用のためにリセットすると、指定されたポインターへの CPU コピーが行われます。そのダウンロードのサブミット値に対する {wait} が戻るまで、転送先を有効に保ち、マネージドメモリを固定してください。データの読み取りやメモリの解放はその後に行います。別のキューの後続サブミットを待っても、ダウンロードを管理するキュー自体はポーリングされません。" -concepts.synchronization.readback.guidance: そのため、{isCompleted} をポーリングして非同期ダウンロードの宛先を直ちに読み取るだけでは不十分です。{link} で直接コピーパスとステージング転送パスについて説明しています。 -concepts.synchronization.readback.guidance.link: リソース管理 -concepts.synchronization.readback.title: GPU 完了とダウンロードされた CPU データは別のステップである -concepts.synchronization.reuse.description: "最初のレンダラーでは、毎フレーム直後に待機する方法がわかりやすいでしょう。複数フレームの処理を重ねて進めるには、未完了のフレームごとに変更可能なデータを分け、各フレームの最終使用の完了値を保持してください。定数バッファーの更新、テクスチャの交換、パイプラインの破棄の前に、対象リソースへのすべての未完了アクセスを終わらせてください。" -concepts.synchronization.reuse.details: リサイズ時やシャットダウン時には、古い作業を待機する前に新しい使用を停止してください。{swapChainResize}、リソースの破棄、コンテキストの破棄は、アプリケーションの作業に対する一般的な待機の役割を果たしません。前の各フレームがすでにサブミットを完了しているため、三角形チュートリアルはコールバック間で安全にリサイズできます。 -concepts.synchronization.reuse.guidance: "現在の {swapChainPresent} も、プレゼンテーション操作の後にグラフィックスキューでシグナルを送って待機します。そのため、三角形の明示的なサブミット待機を削除するだけでは、複数フレームの処理を重ねて進める表示ループにはなりません。グラフィックスキューでの待機は、別のキューで実行中の独立した処理の完了も保証しません。" -concepts.synchronization.reuse.title: 最後のアクセス後にのみデータを再利用する -concepts.synchronization.timelines.context: "CPU がこれらのリソースの読み取り、上書き、解放を行う前に、その最後の使用を待機してください:" -concepts.synchronization.timelines.description: タイムラインは増加する値を使用してキュー上の完了を追跡します。{submit} はそのタイムラインとサブミットに関連付けられた値を含む {timelineValue} を返します。異なるタイムラインの完了値は、数値の {value} フィールドだけで比較することはできません。 -concepts.synchronization.timelines.details: "{producer} と {consumer} が同じコンテキストの 2 つのキューからすでに記録されたコマンドバッファーであると仮定します。プロデューサーはコンシューマーが使用するデータを書き込みます。次のようにサブミットします:" -concepts.synchronization.timelines.guidance: 生成された値を渡すと、コンシューマーキューは GPU 上でそれを待機します。CPU はここで {producedWait} を呼び出しません。{consumed} が完了するまで共有リソースを有効に保ち、コンシューマーに必要なテクスチャレイアウトの変更を記録してください。 -concepts.synchronization.timelines.notes: "{wait} はそのタイムライン値を待機し、完了したサブミットがないか所有キューを確認します。完了したコマンドバッファーは再利用のためにリセットされ、ステージングされたダウンロードは指定された CPU 宛先にコピーされます。{queueTimelineSignal} は、すでにそのキューにサブミットされた作業の後に完了ポイントをエンキューすることもできます。{signal} を呼び出しても、GPU がすでにそのポイントに達したことを意味するわけではありません。" -concepts.synchronization.timelines.title: 完了およびキューの引き渡しにタイムラインを使用する -concepts.synchronization.title: 同期 -home.actions.reference: API を参照 -home.actions.tutorial: 三角形から始める -home.entries.description: 最初のフレーム。焦点を絞ったサンプル。API の詳細。 -home.entries.label: ドキュメントを探索 -home.entries.reference.action: API を探索 -home.entries.reference.category: リファレンス -home.entries.reference.description: アプリケーションの基盤となる型、シグネチャ、メンバーを確認できます。 -home.entries.reference.title: API リファレンス -home.entries.samples.action: サンプルを参照 -home.entries.samples.category: サンプル -home.entries.samples.description: ソースコードを通じて、焦点を絞ったレンダリングやコンピュートの技術を調べます。 -home.entries.samples.title: サンプル -home.entries.title: 開発を始めましょう。 -home.entries.tutorial.action: チュートリアルを開始 -home.entries.tutorial.category: チュートリアル -home.entries.tutorial.description: セットアップから最初のフレームまで、完全なレンダリングアプリケーションを構築します。 -home.entries.tutorial.title: 最初の三角形 -home.introduction.accent: "C# で構築。" -home.introduction.description: 単一の .NET API を通じて、リソースの作成、コマンドの記録、グラフィックスやコンピュート処理のサブミットを行います。 -home.introduction.title: 独自のレンダラーを構築。 -home.meta.description: "DirectX、Metal、Vulkan を横断する、グラフィックスとコンピュートのための統一された C# API です。" -home.scene.description: 回転するジオメトリの研究です。ドラッグまたは矢印キーで視点を調整できます。 -home.scene.label: ジオメトリ表示 -home.scene.surface: サーフェス -home.scene.wireframe: ワイヤーフレーム -home.title: ".NET 向けモダン RHI" -learning.concepts.description: レンダリングパスを組み合わせる前に、コマンド、リソース、シェーダーデータ、同期がどのように連携するかを理解します。 -learning.concepts.execution.description: GPU 処理を記録してサブミットし、そのリソースを有効に維持します。 -learning.concepts.platforms.description: ネイティブウィンドウまたは UI レンダリングコントロールを接続します。 -learning.concepts.resources.description: リソースの用途、メモリ配置、ビューを選択します。 -learning.concepts.shaders.description: "C# のレイアウトとリソースハンドルを Slang と一致させます。" -learning.concepts.synchronization.description: 依存するアクセスを順序付け、処理が完了するタイミングを把握します。 -learning.concepts.title: 基本概念 -learning.description: 完全な三角形チュートリアルから始めます。その後、焦点を絞ったサンプルと概念ガイドを活用して、より大規模なレンダラーの背景にあるリソース、データ、依存関係を理解します。 -learning.entries.samples.action: サンプルを参照 -learning.entries.samples.description: "ジオメトリ、コンピュート、レイクエリ、メッシュシェーディングに関する C# と Slang のサンプルを確認できます。" -learning.entries.tutorial.action: チュートリアルを開く -learning.entries.tutorial.description: コンソールアプリケーションを作成し、ウィンドウを開いて三角形を描画します。 -learning.meta.description: Zenith.NET の基本を学び、そのプログラミングモデルを調べます。 -learning.title: 学習 -reference.description: リソース型、コマンドシグネチャ、プラットフォーム統合を調べます。 -reference.entries.commands.description: グラフィックス、コンピュート、転送コマンドを記録します。 -reference.entries.commands.label: 処理を記録 -reference.entries.context.description: 選択したバックエンド用の GPU リソースを作成します。 -reference.entries.context.label: ここから開始 -reference.meta.description: Zenith.NET の型とメンバーを調べます。 -reference.navigation.core: コア API を参照します。 -reference.title: API リファレンス -samples.computeShader.description: コンピュートディスパッチで画像をグレースケールに変換し、結果のテクスチャを表示します。サンプリングされる入力テクスチャと書き込み可能な出力テクスチャのリソースハンドル、切り上げられたスレッドグループ数、シェーダー内の境界チェックを示します。付属の {assetsTexturesShokoPng} アセットを保持してください。レンダラーはこれを一度処理し、以降のフレームで結果を提示します。 +concepts.shaders.layout.description: "頂点入力の {inputLayout} は、各属性のフォーマット、オフセット、セマンティクスと、頂点間のストライドを記述します。三角形では {float3} の位置の後に {float4} の色を置きます。色のバイトオフセットは 12、頂点一つのサイズは 28 バイトです。{inputLayoutAdd} は属性のフォーマットからこの密な配置を計算します。C# の構造体にパディングがある場合は、それを含めたオフセットとストライドを指定してください。" +concepts.shaders.layout.details: "定数バッファーはシェーダーのパラメーターを、構造化バッファーは型付き要素の配列を格納します。これらの配置は {inputLayout} ではなく、Slang の宣言に従います。C# のフィールドオフセット、要素サイズ、パディングを、コンパイル済みシェーダーの配置に合わせてください。C# のアンマネージ型はバイト列としてコピーできますが、そのメモリ配置がシェーダーの配置と一致するとは限りません。頂点内で密に格納した {float3} も、シェーダーバッファーでは別のアラインメントが必要になる場合があります。" +concepts.shaders.layout.guidance: "シェーダーのパラメーターには、数値とともにリソースハンドルを含められます。ハンドルは既存の記憶領域を指すため、定数バッファーにコピーしてもリソースの内容はコピーされません。" +concepts.shaders.layout.notes: "{computeShaderSlang} の対応する宣言は次のとおりです。" +concepts.shaders.layout.reference: "二つの寸法値が先頭の 8 バイトを占め、その後に二つの 8 バイトのハンドルが続きます。C# サンプルはレコード全体に 256 バイトを確保します。別のレコードでは、フィールドの内容と必要な配置、アラインメントからサイズを決めます。" +concepts.shaders.layout.title: "データ配置" +concepts.shaders.matrices.description: "コンパイラーは行ごとに連続する行優先の行列配置を選択します。{link}では三つの {matrix4x4} をオフセット 0、64、128 に格納します。対応する{detail}では、{mulVectorMatrix} をモデル、ビュー、投影の順に適用します。" +concepts.shaders.matrices.description.detail: "シェーダー" +concepts.shaders.matrices.description.link: "回転する立方体のレンダラー" +concepts.shaders.matrices.details: "格納順序はメモリ内の行列要素の配置を、乗算順序は変換を定めます。C# と Slang で対応する規約を使います。" +concepts.shaders.matrices.title: "行列の規約" +concepts.shaders.title: "シェーダーデータとバインド" +concepts.synchronization.backends.description: "DirectX 12 と Vulkan は、テクスチャ遷移をレイアウトとアクセスの変更として記録します。Zenith.NET の Metal バックエンドでは、{transition} に相当する GPU 操作はありません。代わりにコマンドを描画・計算エンコーダーにまとめ、エンコーダー終了時に可視性バリアを挿入します。連続するコンピュートディスパッチなど、同じエンコーダー内の依存には明示的な {barrier} 呼び出しを使います。" +concepts.synchronization.backends.details: "{link}では、グラフィックスのレンダーパスを開始すると計算エンコーダーが終了し、計算結果を描画処理から読み取れるようになります。連続する二つのコンピュートディスパッチは同じエンコーダー内にとどまるため、間にテクスチャ遷移を記録しても、依存を指定するバリアが必要です。このため、複数のバックエンドで使うコマンド列では、レイアウトとアクセス依存の両方を扱います。" +concepts.synchronization.backends.details.link: "コンピュートサンプル" +concepts.synchronization.backends.title: "バックエンドごとの動作" +concepts.synchronization.barriers.context: "関係するアクセスを含み、キューが対応しているステージを選びます。{barrierStagesAll} は対応するすべてのステージを含みます。依存関係が一部のステージだけに関わる場合は、その範囲に限定できます。" +concepts.synchronization.barriers.description: "同じコマンドバッファーに記録した二つのコンピュートディスパッチで、最初がシミュレーションデータを書き、次がそれを読む場合を考えます。その間にバリアを置くと、後のディスパッチが完了済みの書き込み結果を読み取れます。ストレージバッファーでは、テクスチャレイアウトを遷移させずにアクセスを順序付けられます。" +concepts.synchronization.barriers.details: "最初の引数はデータを生成したステージ、二つ目はそれを使用するステージを指定します。この二つで、ディスパッチ間に必要な実行順序とメモリの可視性を表します。" +concepts.synchronization.barriers.guidance: "{link}では、シミュレーションの各段階の間にこの形のバリアを置きます。どのバリアも、データを生成するディスパッチの後、使用するディスパッチの前に記録します。" +concepts.synchronization.barriers.guidance.link: "FluidTank シミュレーション" +concepts.synchronization.barriers.title: "パイプラインバリア" +concepts.synchronization.dependencies.description: "各リソースで、同じデータに触れるアクセスを確認します。一方でも書き込みを行う場合は、必要な順序を保ちます。二つの読み取りは競合しませんが、テクスチャレイアウトや提示の要件は満たす必要があります。CPU からの更新やリソースの解放も、対象領域を GPU が使い終わるまで待ちます。" +concepts.synchronization.dependencies.details: "操作の実行場所に応じて、使う仕組みを選びます。" +concepts.synchronization.dependencies.guidance: "一つの処理に複数の同期手段が必要な場合もあります。例えば、別のキューで生成したテクスチャには、送信間の依存関係と、次の用途に適したレイアウトの両方が必要です。どちらも、それ自体は CPU の待機を必要としません。CPU がデータにアクセスしたり解放したりする場合に、CPU 側で待機します。" +concepts.synchronization.dependencies.table.cpuAccess.mechanism: "該当する完了値に対して {wait} を呼び出します。" +concepts.synchronization.dependencies.table.cpuAccess.situation: "CPU のアクセスやリソース解放に GPU の完了が必要な場合" +concepts.synchronization.dependencies.table.crossQueue.mechanism: "生成側の {timelineValue} を使用側の {submit} に渡します。" +concepts.synchronization.dependencies.table.crossQueue.situation: "別のキューで生成したデータを使用する場合" +concepts.synchronization.dependencies.table.headings.mechanism: "メカニズム" +concepts.synchronization.dependencies.table.headings.situation: "状況" +concepts.synchronization.dependencies.table.layoutChange.mechanism: "以前のレイアウトと次のレイアウトを指定した {commandBufferTransition}。" +concepts.synchronization.dependencies.table.layoutChange.situation: "テクスチャサブリソースの使用方法の変更" +concepts.synchronization.dependencies.table.pipelineStages.mechanism: "生成側ステージと使用側ステージを指定した {commandBufferBarrier}。" +concepts.synchronization.dependencies.table.pipelineStages.situation: "コマンドストリーム内の依存する GPU ステージ" +concepts.synchronization.dependencies.title: "アクセス間の依存" +concepts.synchronization.description: "同期は、共有データへのアクセス順序を定め、後の操作が必要な結果を読み取れるようにします。書き込みから読み取りへの依存では、書き込む側を生成側、読む側を使用側と呼びます。バリアとテクスチャ遷移は GPU のアクセスを調整し、タイムラインは送信間の依存を設定したり、CPU で GPU の完了を待ったりするために使います。" +concepts.synchronization.layouts.context: "以前の内容を破棄できる場合は、遷移前のレイアウトに {undefined} を指定できます。例えば、新しい画像や全体をクリアするアタッチメントが該当します。ロード、サンプリング、蓄積のために内容を保持する場合は、直前のアクセスのレイアウトを使います。" +concepts.synchronization.layouts.description: "用途フラグは、テクスチャの許可された用途を宣言します。{textureLayout} は、コマンド列のある時点で、mip レベルと配列レイヤーで特定したサブリソースにどうアクセスするかを表します。アクセス方法が変わるときに遷移を記録します。例えばコンピュートサンプルでは、{storage} レイアウトで出力テクスチャへ書き込んだ後、グラフィックスパスでサンプリングする準備をします。" +concepts.synchronization.layouts.details: "ここでは {outputTexture} を {sampledStorage} 用途で作成し、対象サブリソースは {storage} です。{default} は mip レベル 0 と配列レイヤー 0 を選びます。他のレベルとレイヤーには影響しません。" +concepts.synchronization.layouts.guidance: "{transition} には、サブリソースを前回使用したときのレイアウトを渡します。アプリケーションはコマンドを記録し、テクスチャを描画ステージ間で渡す際に、この状態を追跡します。" +concepts.synchronization.layouts.title: "テクスチャレイアウト" +concepts.synchronization.readback.description: "{isCompleted} は GPU の完了を報告します。記録したリードバックには、その後にもう一つの処理があります。内部の読み戻し領域からアプリケーションの宛先メモリへ結果をコピーする処理です。" +concepts.synchronization.readback.details: "{commandBufferDownload} は、この内部領域への GPU コピーを記録します。送信完了後、ライブラリはコマンドバッファーの回収時に CPU コピーを行います。リードバックの送信値に対して {wait} を呼ぶと、GPU を待機した後、そのキューの完了済みバッファーを処理し、両方のコピーが完了します。戻るまで宛先を確保し、管理対象メモリは固定したままにしてください。" +concepts.synchronization.readback.guidance: "{isCompleted} の確認だけでは、最後の CPU コピーは行われません。別のキューで待機しても、リードバックを管理するキューのバッファーは回収されません。アップロードとリードバックが直接アクセスや一時領域を使う条件は、{link}で説明します。" +concepts.synchronization.readback.guidance.link: "リソース管理" +concepts.synchronization.readback.title: "リードバックの完了" +concepts.synchronization.reuse.description: "三角形では、各フレームの完了を待ってからデータを再利用します。フレームの処理を並行して進める場合は、処理中の各フレームに個別の変更可能な記憶領域を用意し、再び使える時点を追跡します。データを変更する前にはその領域への GPU アクセスを、リソースを解放する前にはそのすべての使用を待ちます。" +concepts.synchronization.reuse.details: "リサイズと終了も、同じ順序で処理します。新しい使用を止め、既存の使用が終わるのを待ってから、リソースを置き換えるか解放します。{swapChainResize} やリソース、コンテキストの解放を呼ぶ前に、この順序を確保してください。三角形では毎フレーム待機しているため、コールバックの間でリサイズできます。" +concepts.synchronization.reuse.guidance: "{swapChainPresent} は提示後にグラフィックスキューへシグナルを送り、完了を待ちます。そのため、明示的な送信待ちを除いても、三角形は提示時に待機します。別キューへ独立して送信した処理は、完了を個別に追跡する必要があります。" +concepts.synchronization.reuse.title: "リソースの再利用" +concepts.synchronization.timelines.context: "使用側の処理後に CPU で結果を読んだり、共有データを上書きしたり、リソースを解放したりする場合は、その送信を待ちます。" +concepts.synchronization.timelines.description: "タイムラインは増加する値でキューの完了を表します。{submit} が返す {timelineValue} はタイムラインと送信の値を含みます。異なるタイムラインの数値 {value} は直接比較できません。" +concepts.synchronization.timelines.details: "同じコンテキストの二つのキューで記録した {producer} と {consumer} があり、後者が前者の書いたデータを使うとします。次の依存関係で送信します。" +concepts.synchronization.timelines.guidance: "使用側のキューは、渡された完了値に到達するのを待ってからコマンドを実行します。CPU は {producedWait} を呼ばずに処理を続けられます。共有リソースは {consumed} が完了するまで保持し、使用側のアクセスに必要なテクスチャ遷移も記録します。" +concepts.synchronization.timelines.notes: "{queueTimelineSignal} の戻り値も、{wait} で待機したり、別キューの依存関係に使ったりできます。{signal} は、それまでに送信した処理の後に完了点を置きます。GPU がその処理を終えると、完了点に到達します。" +concepts.synchronization.timelines.title: "タイムラインとキュー間の依存" +concepts.synchronization.title: "同期" +home.actions.reference: "API を参照" +home.actions.tutorial: "三角形から始める" +home.entries.description: "チュートリアル、サンプル、API リファレンス" +home.entries.label: "ドキュメントの構成" +home.entries.reference.action: "API を探索" +home.entries.reference.category: "リファレンス" +home.entries.reference.description: "API の型、メンバー、宣言を調べる" +home.entries.reference.title: "API リファレンス" +home.entries.samples.action: "サンプルを参照" +home.entries.samples.category: "サンプル" +home.entries.samples.description: "描画と計算の手法を実行できるサンプルで学ぶ" +home.entries.samples.title: "サンプル" +home.entries.title: "ドキュメント" +home.entries.tutorial.action: "チュートリアルを開始" +home.entries.tutorial.category: "チュートリアル" +home.entries.tutorial.description: "空のプロジェクトから、最初の三角形を描くまで" +home.entries.tutorial.title: "最初の三角形" +home.introduction.accent: "クロスプラットフォームのグラフィックス" +home.introduction.description: "Zenith.NET は、共通の API で DirectX、Metal、Vulkan の描画と計算を扱うライブラリです" +home.introduction.title: ".NET でつくる{lineBreak}{accent}" +home.meta.description: "DirectX、Metal、Vulkan に共通の API を使い、.NET でクロスプラットフォームの描画・計算アプリケーションを開発" +home.scene.description: "回転する図形を操作できます。ドラッグまたは矢印キーで視点を調整してください。" +home.scene.label: "ジオメトリ表示" +home.scene.surface: "サーフェス" +home.scene.wireframe: "ワイヤーフレーム" +home.title: ".NET 向けのモダンな RHI" +learning.concepts.description: "リソース用途の選択、シェーダーデータの記述、GPU 実行の調整" +learning.concepts.execution.description: "コマンドの記録と送信、リソースの寿命" +learning.concepts.platforms.description: "ネイティブの提示と UI 描画コントロール" +learning.concepts.resources.description: "リソースの用途、メモリ配置、ビュー" +learning.concepts.shaders.description: "C# と Slang のデータ配置とバインドの規約" +learning.concepts.synchronization.description: "依存関係、可視性、完了" +learning.concepts.title: "基本概念" +learning.description: "まずは三角形のチュートリアルで、最初のアプリケーションを作成します。その後は必要に応じて、リソース管理、シェーダーデータ、同期の解説を読むか、実装したい手法のサンプルを選んでください。" +learning.entries.samples.action: "サンプルを参照" +learning.entries.samples.description: "ジオメトリ、計算、レイクエリ、メッシュシェーディングの C# と Slang による実装" +learning.entries.tutorial.action: "チュートリアルを開く" +learning.entries.tutorial.description: "ウィンドウを開き、三角形を描くコンソールアプリケーション" +learning.meta.description: "Zenith.NET のプログラミングモデルを学ぶチュートリアルと概念解説" +learning.title: "学習" +reference.description: "リソース、コマンド、プラットフォーム統合のリファレンス" +reference.entries.commands.description: "描画、計算、転送のコマンド" +reference.entries.commands.label: "コマンドを記録" +reference.entries.context.description: "選択したバックエンドの GPU リソース作成" +reference.entries.context.label: "ここから開始" +reference.meta.description: "Zenith.NET の名前空間、型、メンバー" +reference.navigation.core: "コア API リファレンス" +reference.title: "API リファレンス" +samples.computeShader.description: "サンプルは {assetsTexturesShokoPng} を読み込み、コンピュートディスパッチでグレースケールに変換して、出力テクスチャを表示します。変換は一度だけ行い、以降のフレームでは同じ結果を表示します。レンダラーでは、サンプリング用と書き込み用テクスチャのバインド、画像全体を覆うためのグループ数の切り上げ、シェーダー内の境界検査を確認できます。" samples.computeShader.details: "{computeShaderRendererCs} · {computeShaderSlang}" -samples.computeShader.title: コンピュートシェーダー -samples.cube.description: インデックス描画、定数バッファー内のモデル・ビュー・プロジェクション行列、深度テストを追加します。深度テクスチャはリサイズ時に再作成されます。クリップ空間ジオメトリから変換されたオブジェクトへ移行する際にご利用ください。レンダラーは {d32FloatS8UInt} 深度/ステンシルアタッチメントを使用します。 +samples.computeShader.title: "コンピュートシェーダー" +samples.cube.description: "立方体では、インデックス付き描画、定数バッファー内のモデル・ビュー・投影行列、深度テストを加えます。{d32FloatS8UInt} の深度ステンシルテクスチャはリサイズ時に再作成します。" samples.cube.details: "{spinningCubeRendererCs} · {spinningCubeSlang}" -samples.cube.title: 回転する立方体 -samples.description: "調べたい機能に応じた焦点を絞ったサンプルを選択してください。各サンプルから C# レンダラーとその Slang シェーダーにリンクしています。空のプロジェクトから完全なアプリケーションを段階的に理解したい場合は、{link} から始めてください。" -samples.description.link: 最初の三角形 -samples.execution.description: "{link} には、1 つのデスクトップアプリケーション内に 6 つの独立したレンダラーが含まれています。.NET 10 SDK と、以下で説明するサポート対象のデスクトップバックエンドを使用してください。アプリケーションをビルドして実行し、コンソールメニューからサンプルを選択します。" -samples.execution.description.link: ZenithTutorials -samples.execution.details: ホストは Windows では DirectX 12、macOS では Metal、Linux では Vulkan を選択します。選択したバックエンドでサポートされているデバイス、ドライバー、シェーダーコンパイラ環境を使用してください。Linux のウィンドウパスには X11 または XWayland が必要です。{link} はパッケージの依存関係を宣言し、実行時に必要なシェーダーとテクスチャのアセットをコピーします。 -samples.execution.details.link: プロジェクトファイル -samples.execution.guidance: 各サンプルはウィンドウ処理とプレゼンテーションのコードを共有しています。学習したい機能に応じて、任意のサンプルを個別に選択できます。 -samples.execution.title: チュートリアルサンプルを実行する -samples.host.description: "{appCs} はコンテキスト、ウィンドウ、スワップチェーンを作成します。コマンドバッファーを取得し、選択したレンダラーを呼び出し、フレームをサブミットして提示します。{iRendererCs} はレンダラーの更新、レンダリング、リサイズ、破棄の各メソッドを定義します。" -samples.host.details: コンピュートとレイトレーシングはオフスクリーンテクスチャを生成します。{texturePresenterCs} と {presentTextureSlang} は、それらのテクスチャをウィンドウの現在のフレームの出力テクスチャに描画します。ホストは引き続きサブミットとスワップチェーンのプレゼンテーションを所有します。 -samples.host.title: 共有ホストとプレゼンテーション -samples.indirectDrawing.description: インデックス付きの間接引数バッファーと構造化バッファー内のインスタンスごとのデータを使用して、立方体の複数のコピーを描画します。CPU が描画引数を提供し、変換を更新します。GPU 生成の引数を追加する前に、間接引数のレイアウトとインスタンスデータへのシェーダーアクセスを理解するためにご利用ください。 +samples.cube.title: "回転する立方体" +samples.description: "各サンプルは C# のレンダラーと Slang シェーダーを組み合わせ、一つの手法を扱います。アプリケーションの準備から描画までの手順は、{link}で説明します。" +samples.description.link: "最初の三角形" +samples.execution.description: "{link} プロジェクトを実行し、コンソールメニューからサンプルを選びます。" +samples.execution.description.link: "ZenithTutorials" +samples.execution.title: "サンプルの実行" +samples.host.description: "{appCs} はコンテキスト、ウィンドウ、スワップチェーンを初期化します。各フレームではコマンドバッファーを取得し、選択したレンダラーを呼び、送信と提示を行います。{iRendererCs} は更新、描画、リサイズ、解放の操作を定義します。" +samples.host.details: "コンピュートとレイトレーシングのレンダラーは、オフスクリーンテクスチャを生成します。{texturePresenterCs} と {presentTextureSlang} がその内容を現在の drawable に描画し、共通ホストがコマンドを送信してフレームを提示します。" +samples.host.title: "ホストと提示" +samples.indirectDrawing.description: "間接描画では、インデックス付き描画の引数バッファーとインスタンスごとの構造化データを使い、複数の立方体を描きます。CPU が引数を設定し、変換を更新します。" samples.indirectDrawing.details: "{indirectDrawingRendererCs} · {indirectDrawingSlang}" -samples.indirectDrawing.title: 間接描画 -samples.meshShading.description: タスクシェーダーを使用して球体のインスタンスをカリングし、そのインデックスをジオメトリを出力するメッシュシェーダーに渡します。レンダラーはパイプラインを作成する前に {contextCapabilitiesMeshShadingSupported} を確認します。タスクステージとメッシュステージを通じてリソースハンドルとペイロードデータを追跡するためにご利用ください。 +samples.indirectDrawing.title: "間接描画" +samples.meshShading.description: "タスクシェーダーが球のインスタンスをカリングし、残ったインデックスを、ジオメトリを生成するメッシュシェーダーへ渡します。パイプライン作成前に {contextCapabilitiesMeshShadingSupported} を確認します。" samples.meshShading.details: "{meshShadingRendererCs} · {meshShadingSlang}" -samples.meshShading.title: メッシュシェーディング -samples.rayTracing.description: "地面とプロシージャルな球体のボトムレベルおよびトップレベルのアクセラレーション構造を構築し、コンピュートシェーダー内でインラインのレイクエリを実行します。レンダラーはワークロードを構築する前に {contextCapabilitiesRayTracingSupported} を確認します。アクセラレーション構造の入力とシェーダー側のレイ走査の確認にご利用ください。" +samples.meshShading.title: "メッシュシェーディング" +samples.rayTracing.description: "床と手続き的な球の下位・上位アクセラレーション構造を構築し、コンピュートシェーダー内でインラインレイクエリを実行します。初期化前に {contextCapabilitiesRayTracingSupported} を確認します。" samples.rayTracing.details: "{rayTracingRendererCs} · {rayTracingSlang}" -samples.rayTracing.title: レイトレーシング -samples.title: サンプル -samples.triangle.description: 頂点バッファーと一致する入力レイアウトを作成し、グラフィックスパイプラインを介して 3 つの頂点を描画します。リソースの作成とレンダーパス内のコマンドを結びつけるためにご利用ください。 +samples.rayTracing.title: "レイトレーシング" +samples.title: "サンプル" +samples.triangle.description: "頂点バッファーと対応する入力レイアウトを関連付け、グラフィックスパイプラインで三つの頂点から三角形を描きます。" samples.triangle.details: "{helloTriangleRendererCs} · {helloTriangleSlang} · {link}" -samples.triangle.details.link: 完全なチュートリアル -samples.triangle.title: Hello Triangle -samples.workloads.description: "メインリポジトリの {link} には、複数の機能を組み合わせたアプリケーションが含まれています。それらのプロジェクトはライブラリのソースコードを参照します。Zenith.NET のチェックアウトから、目的のプロジェクトを実行してください。例:" -samples.workloads.description.link: Experiments ディレクトリ -samples.workloads.details: ウィンドウ表示の実験では、Windows、macOS、Linux/X11 で同じホスト選択を使用します。Avalonia、WinForms、WPF、WinUI/Uno、MAUI 内での描画、コントロールのフレームライフサイクル、実装リンクについては、{link} を参照してください。 -samples.workloads.details.link: プラットフォーム統合 +samples.triangle.details.link: "完全なチュートリアル" +samples.triangle.title: "Hello Triangle" +samples.workloads.description: "メインリポジトリの {link} にある応用例は、ライブラリのソースを直接参照しています。" +samples.workloads.description.link: "Experiments ディレクトリ" +samples.workloads.details: "ウィンドウ付きの実験は同じ Windows、macOS、Linux/X11 の提示経路を使います。Avalonia、WinForms、WPF、WinUI/Uno、MAUI のコントロールは、フレーム処理と実装ソースを含めて{link}で紹介します。" +samples.workloads.details.link: "プラットフォーム統合" samples.workloads.table.cornellBox.example: "{link}" -samples.workloads.table.cornellBox.example.link: CornellBox -samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: パストレーシング、デノイズ、トーンマッピング、アップスケーリング、ImGui コントロールを実証します。レイトレーシングのサポートと、デスクトップバックエンド用のシェーダーコンパイル環境が必要です。 +samples.workloads.table.cornellBox.example.link: "CornellBox" +samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: "パストレーシング、ノイズ除去、トーンマッピング、アップスケーリング、ImGui による操作を扱います。レイトレーシング対応が必要です。" samples.workloads.table.fluidTank.example: "{link}" -samples.workloads.table.fluidTank.example.link: FluidTank -samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: コンピュートによる流体シミュレーション、シミュレーションステージ間の依存関係、マルチパスのサーフェスレンダリングを実証します。デスクトップバックエンドとシェーダーコンパイル環境が必要です。 -samples.workloads.table.headings.example: 例 -samples.workloads.table.headings.whatItDemonstratesAndRequires: 実証内容と要件 +samples.workloads.table.fluidTank.example.link: "FluidTank" +samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: "計算による流体シミュレーション、段階間の依存、複数パスの表面描画を扱います。" +samples.workloads.table.headings.example: "例" +samples.workloads.table.headings.whatItDemonstratesAndRequires: "手法と要件" samples.workloads.table.inkCanvas.example: "{link}" -samples.workloads.table.inkCanvas.example.link: InkCanvas -samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: ネイティブウィンドウでの Skia 描画と入力処理を実証します。ターゲットプラットフォーム用のバックエンドと Skia ネイティブライブラリが必要です。 +samples.workloads.table.inkCanvas.example.link: "InkCanvas" +samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: "ネイティブウィンドウで Skia の描画と入力処理を行います。対象プラットフォームのバックエンドと Skia ネイティブライブラリが必要です。" samples.workloads.table.platformDetection.example: "{link}" -samples.workloads.table.platformDetection.example.link: PlatformDetection -samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: 各バックエンドのコンテキスト作成を試行し、デバイス機能を報告します。コンテキスト作成が失敗した場合はサポートされていないと報告されます。この結果は、ドライバーやランタイム依存関係の欠如を示している可能性もあります。 -samples.workloads.title: より大規模なワークロードを探索する -tutorial.context.description: これでウィンドウを開くことができるようになりましたが、ウィンドウ内にレンダリングを行う GPU オブジェクトはまだ作成していません。{graphicsContext} は、選択したグラフィックスバックエンドとそのコマンドキューへのアクセスを提供します。 -tutorial.context.details: "このブロックを {emphasis} に挿入します:" -tutorial.context.details.emphasis: using ディレクティブの後、{iWindowWindow} の前 -tutorial.context.guidance: 分岐処理により、Windows では DirectX 12、macOS では Metal、Linux では Vulkan が選択されます。その後のレンダリングコードは共通の Zenith.NET API を使用します。開発中は検証を要求し、{validationMessage} を通じて報告されるメッセージを出力します。診断情報は、バックエンドおよびマシンで利用可能な検証コンポーネントによって異なります。 -tutorial.context.title: グラフィックスコンテキストを作成する -tutorial.description: ウィンドウを開き、滑らかなグラデーションの三角形を描画する .NET コンソールアプリケーションを作成します。頂点データ、シェーダー、パイプライン状態がどのように連携するかを学び、画像を生成するコマンドを記録してサブミットします。 -tutorial.details: 各セクションを順番に進めてください。まず空のウィンドウを開き、次に背景色を表示し、最後に三角形を描画します。各チェックポイントで、次の段階に進む前にアプリケーションの一部が正しく動作することを確認します。初期化は 1 回実行され、描画コールバックは呼び出されるたびに新しいフレームを記録します。 -tutorial.draw.context: "{draw} の引数は次のとおりです:" -tutorial.draw.description: "{windowRender} コールバックで、{beginRenderPass} と {endRenderPass} の間にある {addTheTriangleDrawCommandsHereLater} を次の 3 つのコマンドに置き換えます:" -tutorial.draw.details: "{setPipeline} は、先ほど作成したシェーダーと状態を選択します。頂点データをバインドする前に設定してください。バックエンドはパイプラインの入力レイアウトを使用してバインディングを解釈します。" -tutorial.draw.guidance: "{setVertexBufferVertexBuffer} は、バイトオフセット 0 から始まるバッファーを入力スロット 0 にバインドします。そのスロットは {inputLayouts} の単一エントリに対応します。これによりデータが再コピーされたり再アップロードされたりすることはありません。" -tutorial.draw.notes: この時点では、コマンドはまだ記録されただけです。描画コールバックの最後にある {submitWait} と {present} の呼び出しが処理を実行し、その結果を表示します。三角形は画像の一部しか覆わないため、クリア操作は引き続き必要です。背景も各フレームで定義された色を受け取る必要があります。 -tutorial.draw.table.firstInstance.meaning: インスタンスの番号付けをゼロから開始します。 -tutorial.draw.table.firstVertex.meaning: バッファー内の最初の頂点から開始します。 -tutorial.draw.table.headings.argument: 引数 -tutorial.draw.table.headings.description: 値 -tutorial.draw.table.headings.meaning: 意味 -tutorial.draw.table.instanceCount.meaning: 三角形のコピーを 1 つ描画します。 -tutorial.draw.table.vertexCount.meaning: 3 つの頂点を読み取ります。 -tutorial.draw.title: パス内で三角形を描画する -tutorial.execution.description: "{firstTriangle} ディレクトリからビルドして実行します:" -tutorial.execution.details: 暗い背景に対して、上が赤、右下が緑、左下が青の角を持つ三角形がウィンドウに表示されるはずです。内部はこれらの色間で滑らかなグラデーションを示す必要があります。 -tutorial.execution.guidance: ウィンドウのサイズを変更してください。リサイズコールバックがフレームバッファーのサイズを更新し、スワップチェーンをリサイズします。レンダーパスはその画像に一致するビューポートを確立します。頂点位置は正規化座標のままであるため、三角形はウィンドウの幅と高さに対する同じ比率を維持します。アスペクト比を変更すると形状が引き伸ばされることがあります。オブジェクトのアスペクト比を維持するには、この最初の描画の範囲を超えるプロジェクションまたはビューポートポリシーが必要です。 -tutorial.execution.title: 実行、リサイズ、および閉じる -tutorial.frame.commands.context: "{endRenderPass} の後、2 つ目の遷移によって画像がプレゼンテーション用に準備されます。{submit} は記録を完了してコマンドバッファーをサブミットし、{wait} は GPU がそのサブミットを完了するのを待機します。その後、{present} はレンダリングされた画像の表示を要求します。" -tutorial.frame.commands.description: レンダーパスは、同じアタッチメントを使用する描画操作をグループ化します。ここでは、カラーアタッチメントはスワップチェーンの出力テクスチャ、すなわち描画を受け取る画像です。{colorAttachmentClear} は、指定した RGBA カラーでクリアし、パスの終了時に結果を保持するよう指示する記述を作成します。{beginRenderPass} はこれらの命令を記録し、コマンドがサブミットされた後に GPU がクリアを実行します。 -tutorial.frame.commands.details: 角括弧には単一のカラーアタッチメントが含まれています。引数 {null} は、深度およびステンシルテスト用の深度値とステンシルマスクを格納する深度/ステンシルアタッチメントが存在しないことを意味します。 -tutorial.frame.commands.guidance: "{beginRenderPass} は、アタッチメントをカバーするビューポートとシザーを設定します。ビューポートはレンダリング座標をピクセルにマッピングし、シザーは書き込み可能なピクセルを制限します。これらのデフォルト設定は出力テクスチャ全体をカバーし、この三角形の描画に適しています。" -tutorial.frame.commands.title: クリア、サブミット、およびプレゼンテーション -tutorial.frame.description: まず画像を単一の背景色で塗りつぶします。この操作はクリアと呼ばれます。その色がウィンドウに表示されれば、サーフェス、コマンドのサブミット、およびプレゼンテーションパスが正常に連携しています。このチェックポイントにより、ジオメトリやシェーダーを追加する前にフレームループを検証できます。 -tutorial.frame.details: "描画コールバックは、フレームを描画するタイミングで Silk.NET が呼び出すコードです。このコールバックではイベントの経過時間引数は不要なため、{value} と命名されています。これを {emphasis} に登録します:" +samples.workloads.table.platformDetection.example.link: "PlatformDetection" +samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: "各バックエンドのコンテキスト作成を試み、デバイスの機能を報告します。作成に失敗した場合は非対応と表示しますが、原因にはデバイス、ドライバー、実行時依存の不足が考えられます。" +samples.workloads.title: "より大きなアプリケーション" +tutorial.context.description: "{graphicsContext} はバックエンドを介してアプリケーションを GPU に接続し、描画リソースを作成するためのメソッドを提供します。" +tutorial.context.details: "コンテキストの初期化を{emphasis}に追加します。" +tutorial.context.details.emphasis: "using ディレクティブの後、{iWindowWindow} の前" +tutorial.context.guidance: "各分岐でプラットフォームに応じたバックエンドを選び、検証を要求します。{validationMessage} のメッセージはコンソールに出力します。" +tutorial.context.imports: "{programCs} の先頭に、次の using ディレクティブを追加します。" +tutorial.context.title: "グラフィックスコンテキスト" +tutorial.description: "このチュートリアルでは、空の .NET コンソールプロジェクトから始め、ウィンドウを開いて色付きの三角形を描くアプリケーションを作成します。" +tutorial.details: "このチュートリアルでは、空のウィンドウ、単色の背景、色付きの三角形の三段階で結果を確認します。各段階でアプリケーションを実行し、表示を確かめてから次へ進んでください。" +tutorial.draw.context: "{draw} の引数は次のとおりです。" +tutorial.draw.description: "{windowRender} コールバックの {addTheTriangleDrawCommandsHereLater} を、次のコマンドで置き換えます。位置は {beginRenderPass} と {endRenderPass} の間です。" +tutorial.draw.details: "{setPipeline} はシェーダーと描画状態を選択します。頂点のバインドはパイプラインの入力レイアウトに従って解釈されるため、その前に呼びます。" +tutorial.draw.guidance: "{setVertexBufferVertexBuffer} は、転送済みの頂点データをバイトオフセット 0 から入力スロット 0 にバインドします。これは {inputLayouts} の唯一の要素に対応します。" +tutorial.draw.notes: "これらの呼び出しは描画コマンドを記録します。既存の {submitWait} がコマンドを送信して GPU の完了を待ち、その後 {present} が完成した画像の表示を要求します。三角形の外側にも決まった背景色を表示するため、パスの先頭のクリア処理は残します。" +tutorial.draw.table.firstInstance.meaning: "インスタンスの番号付けをゼロから開始します。" +tutorial.draw.table.firstVertex.meaning: "バッファー内の最初の頂点から開始します。" +tutorial.draw.table.headings.argument: "引数" +tutorial.draw.table.headings.description: "値" +tutorial.draw.table.headings.meaning: "意味" +tutorial.draw.table.instanceCount.meaning: "三角形を一つ描きます。" +tutorial.draw.table.vertexCount.meaning: "3 つの頂点を読み取ります。" +tutorial.draw.title: "描画コマンド" +tutorial.execution.description: "{firstTriangle} プロジェクトをビルドして実行します。" +tutorial.execution.details: "暗い背景の上に、上が赤、右下が緑、左下が青の三角形が表示されます。内部の色は頂点色を補間したもので、滑らかなグラデーションになります。" +tutorial.execution.guidance: "リサイズすると画像のピクセル寸法が変わりますが、頂点座標は変わりません。ビューポートは同じ座標を新しい幅と高さに対応付けるため、ウィンドウの縦横比を変えると三角形が伸縮します。" +tutorial.execution.title: "アプリケーションの実行" +tutorial.frame.commands.context: "{endRenderPass} の後、二回目の遷移で出力テクスチャを提示可能な状態にします。{submit} は記録を終えてコマンドを送信し、{wait} はその完了まで待機します。続く {present} が描画済み画像の表示を要求します。" +tutorial.frame.commands.description: "レンダーパスは、同じアタッチメントに書き込む描画操作をまとめます。このパスではスワップチェーンの drawable が色の出力先です。{colorAttachmentClear} は、アタッチメントを RGBA 色で初期化し、パス終了時に内容を保持するよう指定します。{beginRenderPass} は、この設定でパスを開始するコマンドを記録します。" +tutorial.frame.commands.details: "コレクションにはカラーアタッチメントを一つ入れます。{null} は深度ステンシルアタッチメントを使わない指定です。" +tutorial.frame.commands.guidance: "{beginRenderPass} は、アタッチメント全体を覆うビューポートとシザーを設定します。ビューポートは描画座標をピクセル位置に変換し、シザーは書き込める範囲を制限します。" +tutorial.frame.commands.title: "クリア、送信、提示" +tutorial.frame.description: "まず、ウィンドウを単色の背景で埋めます。この操作をクリアと呼びます。背景が表示されれば、サーフェス、コマンド送信、提示の流れが動いています。ここに三角形の頂点とシェーダーを加えていきます。" +tutorial.frame.details: "Silk.NET は描画のタイミングでコールバックを呼びます。この例では経過時間の引数を使わないため、パラメーター名を {value} にしています。コールバックを{emphasis}に登録します。" tutorial.frame.details.emphasis: "{windowRun} の前" -tutorial.frame.target.description: "{graphicsQueueCommandBuffer} は、すでに記録が開始されたコマンドバッファーを取得します。記録は GPU に対する処理を記述するものであり、その処理を即時に実行するわけではありません。" -tutorial.frame.target.details: 最初の {transition} は、カラーアタッチメントとしてのアクセスのために出力テクスチャを準備します。{default} はミップレベル 0 と配列レイヤー 0 を選択します。画像全体をクリアして以前の内容を破棄するため、以前のレイアウトとして {undefined} を使用します。既存の内容を保持する必要があるパスでは、代わりに実際の以前のレイアウトを使用する必要があります。 -tutorial.frame.target.guidance: 各フレームでスワップチェーンの現在の出力テクスチャを使用してください。プレゼンテーションによって利用可能な画像が変わる可能性があるため、以前のフレームから保存したテクスチャは永続的なウィンドウのレンダーターゲットにはなりません。 -tutorial.frame.target.title: 出力テクスチャを準備する -tutorial.frame.title: 背景色を表示する -tutorial.geometry.data.description: この配列を {emphasis} に追加します。後続のリソース作成ステップも、示された順序でこのコールバックの前に配置します。 +tutorial.frame.target.description: "{graphicsQueueCommandBuffer} は記録可能なコマンドバッファーを返します。記録は GPU の処理を定義する段階であり、実行は送信後に始まります。" +tutorial.frame.target.details: "テクスチャレイアウトは、操作がテクスチャにどうアクセスするかを表します。最初の {transition} で、出力テクスチャをカラーアタッチメントとして使える状態にします。ここでの {default} は mip レベル 0 と配列レイヤー 0、つまり出力テクスチャの基本画像を選びます。このパスでは画像全体をクリアするため、{undefined} を指定して以前の内容を破棄できます。" +tutorial.frame.target.guidance: "提示すると別の画像に切り替わることがあるため、毎フレーム、現在の drawable を取得します。" +tutorial.frame.target.title: "drawable の準備" +tutorial.frame.title: "最初のフレーム" +tutorial.geometry.data.description: "頂点配列を{emphasis}に追加します。以後のリソース初期化も、説明する順序でこのコールバックの前に置きます。" tutorial.geometry.data.description.emphasis: "{windowRender} の前" -tutorial.geometry.data.details: 配列の各エントリが 1 つの {vertex} を作成します。内側の 2 つの {new} 式は、その {vector3} 位置と {vector4} 色を作成します。頂点は上、右下、左下のコーナーを記述します。頂点シェーダーは 4 番目の位置座標 {w} を提供します。w が 1 の場合、x と y は正規化デバイス座標を直接表します。-1 と +1 が画像の端で、0 が中心です。これらの座標はウィンドウのピクセルサイズに依存しません。 -tutorial.geometry.data.guidance: 各色には赤、緑、青、アルファの成分が含まれます。3 つのコーナーすべてでアルファは 1 です。3 つの位置はすべて z = 0 であり、同じ平面上に配置されます。これらの位置はレンダリングしたい座標をすでに直接記述しているため、カメラや変換行列は不要です。この単一の平坦な三角形では、ブレンディングと深度テストも無効にし、深度バッファーも省略します。 -tutorial.geometry.data.title: コーナーの位置を選択する -tutorial.geometry.description: 頂点は、描画に使用されるデータと結びついた点です。この三角形には、各コーナーに 1 つずつ、計 3 つの頂点があります。各頂点には位置と色が含まれます。GPU は色を補間し、三角形全体の中間値を計算します。 -tutorial.geometry.format.description: "この宣言を {emphasis} に追加します:" -tutorial.geometry.format.description.emphasis: "{programCs} の末尾、クリーンアップステートメントの後" -tutorial.geometry.format.details: "{file} はこの型を {programCs} に限定し、コンストラクターがその位置と色のフィールドを初期化します。{layoutKindSequential} はフィールドを宣言順に維持します。{position} は 3 つの 32 ビット浮動小数点数を含み、{color} は 4 つを含みます。この構造体では、位置はバイト 0 から、色はバイト 12 から始まり、完全な頂点は 28 バイトを占めます。この同じレイアウトをグラフィックスパイプラインに記述します。" -tutorial.geometry.format.title: 頂点を定義する -tutorial.geometry.title: GPU に 3 つの頂点を提供する -tutorial.geometry.upload.context: "{fixed} は、アドレスが使用されている間にガベージコレクターが配列を移動するのを防ぎます。この CPU 書き込み可能バッファーの場合、{upload} は戻る前にメモリをマップ、コピー、アンマップするため、その後配列を固定したままにする必要はありません。バッファーはレンダリング全体を通じて存続する必要があり、頂点は変化しないためアップロードは 1 回だけ行えば十分です。" -tutorial.geometry.upload.description: "マネージド配列は CPU データです。{buffer} は、GPU が頂点を読み取るためのストレージを提供します。配列の後に次を追加します:" -tutorial.geometry.upload.details: "合計サイズは {sizeofVertexVerticesLength} です。頂点あたり 28 バイト、3 つの頂点で合計 84 バイトになります。{bufferUsagesVertex} は頂点入力アクセスを許可します。{cpuWriteOnly} は、CPU がこの小さなバッファーを直接初期化することを可能にします。記述子の ストライド は要素サイズを記録し、後で作成する入力レイアウトが個々の属性の読み取り方法を頂点フェッチに伝えます。" -tutorial.geometry.upload.guidance: バッファーを作成しただけではデータは格納されません。{upload} は、宛先のバイトオフセット 0 から始まる割り当てに配列をコピーします。そのソース記述はポインターとコピーするバイト数を提供します。 -tutorial.geometry.upload.notes: "{programCs} の末尾のクリーンアップで、{swapChainDispose} の直前に {vertexBufferDispose} を追加します。より大規模な静的ジオメトリについては、GPU 専用メモリと転送アップロードを選択する基準について {link} で説明しています。" -tutorial.geometry.upload.notes.link: リソース管理 -tutorial.geometry.upload.title: バッファーを割り当てて配列をアップロードする -tutorial.input.description: "頂点バイトとシェーダーの準備が整いました。次に、GPU が各頂点をどのように読み取るかを記述します。属性とは、位置や色などの 1 つの値です。入力レイアウトは各属性にフォーマットとバイトオフセットを与え、ストライド は 1 つの頂点から次の頂点までのバイト単位の距離を与えます。シェーダー作成後に次の初期化ブロックを追加します:" -tutorial.input.details: "{inputLayoutAdd} は現在の ストライド に要素を追加し、その ストライド を要素のサイズ分だけ増加させます。C# の構造体を検査するわけではありません。ここでは、CPU メモリとシェーダー入力との間で次の一致関係を生成します:" -tutorial.input.guidance: "この記述を更新せずに C# フィールドの順序やパディングを変更すると、GPU は間違ったバイトを読み取ることになります。デフォルトの {semanticIndex} はゼロで、{pOSITION0} および {cOLOR0} と一致します。両方の要素は同じバッファーに属するため、パイプラインには 1 つの入力レイアウトが含まれ、そのバッファーをスロット 0 にバインドします。" -tutorial.input.table.headings.byteOffset: バイトオフセット +tutorial.geometry.data.details: "各要素は {vertex} を作り、内側の二つの {new} が {vector3} の位置と {vector4} の色を渡します。位置は上、右下、左下の頂点です。頂点シェーダーで第四成分 {w} を加えます。w が 1 なので x と y は正規化デバイス座標でもあり、-1 と +1 が画像の端、0 が中央を表します。この意味はピクセル寸法に依存しません。" +tutorial.geometry.data.guidance: "各色は赤、緑、青、アルファの成分を持ち、アルファは 1 です。三つの頂点はすべて z = 0 で、同じ平面上にあります。" +tutorial.geometry.data.title: "頂点の位置と色" +tutorial.geometry.description: "三角形の各頂点には位置と色があります。GPU は三つの位置から形を決め、頂点色を補間して内部の色を求めます。" +tutorial.geometry.format.description: "頂点の宣言を{emphasis}に追加します。" +tutorial.geometry.format.description.emphasis: "{programCs} の末尾、解放処理の後" +tutorial.geometry.format.details: "{file} は型の使用範囲を {programCs} に限定し、{layoutKindSequential} はフィールドの宣言順を保ちます。{position} は三つの 32 ビット浮動小数点数を含み、バイトオフセット 0 から始まります。{color} は四つを含み、バイトオフセット 12 から始まります。したがって、頂点一つの大きさは 28 バイトです。後で入力レイアウトにこの配置を指定し、GPU が各フィールドを正しく読めるようにします。" +tutorial.geometry.format.imports: "ベクトル型と構造体のレイアウト属性を使うため、{programCs} の先頭に次の using ディレクティブを追加します。" +tutorial.geometry.format.title: "頂点の表現" +tutorial.geometry.title: "頂点データ" +tutorial.geometry.upload.context: "{fixed} は、配列のアドレスを使用している間、ガベージコレクターが配列を移動しないようにします。この CPU 書き込み可能なバッファーでは、{upload} がメモリをマッピングし、データをコピーして、マッピングを解除してから戻ります。そのため、配列の固定が必要なのは呼び出し中だけです。頂点は初期化時に一度アップロードし、バッファーは描画が終わるまで保持します。" +tutorial.geometry.upload.description: "描画時に GPU が読み取れるよう、頂点を {buffer} に格納します。配列の直後に、バッファーの確保とアップロードを追加します。" +tutorial.geometry.upload.details: "サイズは {sizeofVertexVerticesLength}、つまり 28 バイトの頂点三つで 84 バイトです。{bufferUsagesVertex} は頂点入力用途、{cpuWriteOnly} は CPU による直接初期化を許可します。記述のストライドは要素サイズを表します。各属性の読み方は、後で作る入力レイアウトが定めます。" +tutorial.geometry.upload.guidance: "確保しただけではデータは入りません。{upload} が、データ記述に渡した元ポインターとバイト数を使い、配列をバッファーのオフセット 0 にコピーします。" +tutorial.geometry.upload.imports: "Zenith.NET のバッファー型を {systemBuffer} と区別するため、{programCs} の using ディレクティブに {bufferAlias} を追加します。" +tutorial.geometry.upload.notes: "{programCs} 末尾の解放処理で、{swapChainDispose} の直前に {vertexBufferDispose} を加えます。大きな静的ジオメトリ向けの GPU 専用メモリと転送は{link}で説明します。" +tutorial.geometry.upload.notes.link: "リソース管理" +tutorial.geometry.upload.title: "バッファーの確保と転送" +tutorial.input.description: "GPU は位置や色などの頂点属性がどこにあるかを知る必要があります。入力レイアウトで各属性のフォーマットとバイトオフセットを指定し、ストライドで次の頂点までのバイト数を示します。シェーダー作成後に次のコードを加えます。" +tutorial.input.details: "{inputLayoutAdd} は属性を順番に並べ、各属性のサイズをストライドに加算します。オフセットは C# の構造体を調べて得るのではなく、ここで指定したフォーマットから計算されます。この二つのフィールドでは、次の配置になります。" +tutorial.input.guidance: "{semanticIndex} の既定値は 0 で、シェーダーの {pOSITION0} と {cOLOR0} に対応します。位置と色は一つの頂点バッファーに格納するため、パイプラインにはスロット 0 の入力レイアウトを一つ指定します。C# のフィールド順やパディングを変えた場合は、入力レイアウトも合わせて変更してください。" +tutorial.input.table.headings.byteOffset: "バイトオフセット" tutorial.input.table.headings.cField: "C# フィールド" -tutorial.input.table.headings.format: フォーマット -tutorial.input.table.headings.shaderInput: シェーダー入力 -tutorial.input.table.nextVertex.cField: 次の頂点 -tutorial.input.table.nextVertex.format: "合計 ストライド: 28 バイト" -tutorial.input.table.nextVertex.shaderInput: 次の入力レコード +tutorial.input.table.headings.format: "フォーマット" +tutorial.input.table.headings.shaderInput: "シェーダー入力" +tutorial.input.table.nextVertex.cField: "次の頂点" +tutorial.input.table.nextVertex.format: "合計ストライド:28 バイト" +tutorial.input.table.nextVertex.shaderInput: "次の入力レコード" tutorial.input.table.vertexColor.format: "{float4} (16 バイト)" tutorial.input.table.vertexPosition.format: "{float3} (12 バイト)" -tutorial.input.title: 頂点入力レイアウトを記述する -tutorial.lifecycle.description: "完成したアプリケーションはこのシーケンスを繰り返します:" -tutorial.lifecycle.details: "ウィンドウを閉じると {run} から戻ります。描画された各フレームはすでに GPU 処理の完了を待機しているため、使用されたリソースを安全に破棄できます。{windowRun} 後のクリーンアップは次のようになります:" -tutorial.lifecycle.guidance: "ネイティブウィンドウより先にスワップチェーンを解放し、すべてのリソースを解放した後にコンテキストを解放してください。サブミットされたコマンドバッファーはキューが所有して再利用し、出力テクスチャはスワップチェーンが所有します。このアプリケーションでは、それらのコマンドバッファーと出力テクスチャに個別の {dispose} 呼び出しは不要です。" -tutorial.lifecycle.title: 1 つのフレームのライフサイクルを追跡する -tutorial.pipeline.behavior: "入力レイアウトの後に次を追加します:" -tutorial.pipeline.context: "{cullNone} は、どちらの面の向きも破棄せずに三角形を塗りつぶします。頂点の順序が面の巻き方向を決定するため、カリングを無効にすることで、その順序によって最初の三角形が隠れてしまうのを防ぎます。" -tutorial.pipeline.description: これで頂点データ、入力レイアウト、2 つのシェーダーが揃いました。{graphicsPipeline} はこれらを接続し、GPU が頂点をプリミティブに組み立てて結果をアタッチメントに書き込む方法を指定します。 -tutorial.pipeline.details: "パイプラインは、プログラム可能なシェーダーステージと、三角形の組み立て、面カリング、ブレンディングなどの GPU 操作を制御する固定機能設定を結合します。この三角形には、以下の設定を選択します:" -tutorial.pipeline.guidance: カラーフォーマットは {swapChainDescFormat} から取得します。これはレンダーパスで使用される画像と一致している必要があります。{count1} はピクセルあたり 1 つのサンプルを意味します。 -tutorial.pipeline.item: "{triangleList} は、連続する 3 つの頂点ごとに 1 つの三角形を組み立てます。3 つの頂点を提供して 1 回描画するため、インデックスバッファーは不要です。" -tutorial.pipeline.notes: "{depthNone} は深度テストと書き込みを無効にし、深度アタッチメントのないパスと一致させます。" -tutorial.pipeline.reference: "{opaque} はブレンディングを無効にするため、三角形の内側ではフラグメントシェーダーの色が背景を置き換えます。" -tutorial.pipeline.title: シェーダーと頂点レイアウトを接続する -tutorial.pipeline.usage: シェーダーオブジェクトは、サンプルレンダラーのようにパイプラインを作成した後に破棄できます。パイプライン自体は、これを使用して描画するすべてのフレームで有効に保ってください。クリーンアップで {vertexBufferDispose} の前に {pipelineDispose} を追加します。パイプラインの作成は、描画コールバック前の最後の初期化ステップです。 -tutorial.pipeline.validation: パイプライン記述はアタッチメント構成を宣言するものであり、別の画像を作成するわけではありません。位置と色が 1 つのバッファーにまとめて格納されているため、{inputLayouts} には 1 つのエントリがあります。 -tutorial.presentation.title: GPU をウィンドウに接続する -tutorial.project.context: プロジェクトのビルド設定で {emphasis} ({allowUnsafeBlocks}) を有効にしてください。これは頂点データを GPU に渡す際や、ウィンドウヘルパーのネイティブ呼び出しに使用します。 -tutorial.project.context.emphasis: アンセーフコードの許可 -tutorial.project.description: "プロジェクトを作成し、そのディレクトリに移動します:" -tutorial.project.details: "パッケージをインストールします:" -tutorial.project.guidance: "{zenithNET} は共通のレンダリング API を提供します。3 つのバックエンドパッケージにより、同じプログラムがそのプラットフォームに適した実装を選択できます。{zenithNETCompiler} は、後で作成する小さな GPU プログラムである Slang シェーダーをその実装用にコンパイルします。Silk.NET はウィンドウとイベントループを提供します。" -tutorial.project.title: コンソールプロジェクトを作成する -tutorial.requirements.context: 空のプロジェクトからこのページに沿って進めることができます。ここで使用するレンダリング API とウィンドウ処理 API のリファレンスとして、{link} とその {detail} を参照できます。 -tutorial.requirements.context.detail: 共有ホスト -tutorial.requirements.context.link: Hello Triangle サンプル -tutorial.requirements.description: "{emphasis}、コードエディターまたは IDE、および Zenith.NET バックエンドでサポートされている GPU とドライバーを備えたデスクトップ環境が必要です。C# の基礎知識があれば十分です。グラフィックスの概念は使用する場面で説明します。これは通常の {net10} コンソールプロジェクトです。バックエンドは、Zenith.NET の操作を DirectX 12、Metal、Vulkan などのグラフィックス API の呼び出しに変換します。アプリケーションは起動時にそのうちの 1 つを選択します:" -tutorial.requirements.description.emphasis: .NET 10 SDK -tutorial.requirements.details: Linux では、ここで使用するウィンドウパスに X11 互換のウィンドウセッションが必要です。この三角形を描画するにあたり、オプションのレイトレーシングやメッシュシェーディング機能は不要です。 -tutorial.requirements.guidance: Zenith.NET は、アプリケーションが提供するサーフェスに描画します。Silk.NET.Windowing がデスクトップウィンドウを作成し、そのイベントを処理します。macOS では、プレゼンテーションターゲットは Metal レイヤー ({cAMetalLayerCs}) です。チュートリアルのウィンドウヘルパーがそのレイヤーを自動的に接続します。 -tutorial.requirements.table.headings.graphicsBackend: グラフィックスバックエンド -tutorial.requirements.table.headings.platform: プラットフォーム -tutorial.requirements.table.headings.windowSurface: ウィンドウサーフェス -tutorial.requirements.table.linux.graphicsBackend: Vulkan 1.4 -tutorial.requirements.table.linux.platform: Linux -tutorial.requirements.table.linux.windowSurface: X11 ウィンドウとディスプレイ (XWayland も使用可能) -tutorial.requirements.table.macOS.graphicsBackend: Metal 4 -tutorial.requirements.table.macOS.platform: macOS -tutorial.requirements.table.macOS.windowSurface: ウィンドウに接続された Metal レイヤー -tutorial.requirements.table.windows.graphicsBackend: DirectX 12 -tutorial.requirements.table.windows.platform: Windows -tutorial.requirements.table.windows.windowSurface: Win32 ウィンドウハンドル -tutorial.requirements.title: 始める前に -tutorial.resize.context: "{dotnetRun} を再度実行してください。ウィンドウは均一な暗い背景色になり、リサイズ後も塗りつぶされた状態が維持されるはずです。このコールバックは保持してください。三角形はこの既存のレンダーパス内で描画されます。" -tutorial.resize.description: "スワップチェーンの画像はフレームバッファーのサイズに従う必要があります。{framebufferResize} を使用して、ディスプレイのスケーリングによる変化を含め、ピクセルサイズの変化に対応します。描画コールバックの後、引き続き {windowRun} の前に次を追加します:" -tutorial.resize.details: Silk.NET はウィンドウサイズの変化と {link} を区別します。スワップチェーンはピクセルを格納するため、後者が必要です。最小化されたウィンドウではフレームバッファーのサイズがゼロになることがあります。その場合、両方のコールバックは GPU の処理をスキップします。リサイズ後、レンダーパスはそのビューポートとシザーに新しいアタッチメントサイズを使用します。 -tutorial.resize.details.link: フレームバッファーサイズの変化 -tutorial.resize.guidance: サブミットごとに待機するため、リサイズハンドラーが画像を置き換える際に、以前のフレームがその画像を使用していることはありません。現在の {present} 実装もグラフィックスキューで待機します。このシンプルなループにより、次のフレームが開始する前に 1 つのフレームの処理が確実に完了します。より高度なスケジューリングについては {link} で解説しています。 -tutorial.resize.guidance.link: 同期 -tutorial.resize.title: リサイズに対応する -tutorial.shaders.compilation.context: コンパイルは初期化中に 1 回だけ行われます。{appContextBaseDirectory} は現在の作業ディレクトリに関係なく、実行可能ファイルの横にあるコピーされたシェーダーを見つけます。これらのシェーダーは頂点入力のみを消費するため、定数バッファー、テクスチャ、リソースハンドルをバインドする必要はまだありません。 -tutorial.shaders.compilation.description: "{triangleSlang} のファイルプロパティで、{emphasis} を {detail} に設定します。これにより、シェーダーが実行可能ファイルの横で使用可能になります。" -tutorial.shaders.compilation.description.detail: 新しい場合はコピーする -tutorial.shaders.compilation.description.emphasis: 出力ディレクトリにコピー -tutorial.shaders.compilation.details: "{programCs} に戻ります。頂点アップロードの後、描画コールバックの前にこれらの初期化ステートメントを追加します:" -tutorial.shaders.compilation.guidance: "{zenithCompiler} は要求されたグラフィックス API 用のコードを含むシェーダー記述を返します。{createShader} は対応するバックエンドオブジェクトを作成します。グラフィックス API とエントリポイント名の両方が重要です。{contextGraphicsApi} を使用し、{vSMain} と {fSMain} は Slang ファイルと完全に同じスペルで指定してください。" -tutorial.shaders.compilation.title: 選択したバックエンド用にコンパイルする -tutorial.shaders.context: "{fSInput} は、頂点シェーダーの出力とフラグメントシェーダーの入力を接続します。頂点シェーダーによって書き込まれた場合、{sVPOSITION} はクリップ空間の位置を提供します。これは、GPU が可視画像の内側にあるものを判定するために使用する 4 つの座標です。{cOLOR0} は頂点間で補間する色を伝達します。2 つのステージはその型とセマンティクスで一致している必要があります。" -tutorial.shaders.description: シェーダーは GPU によって実行されるプログラムです。この描画には、頂点を配置する頂点シェーダーと、三角形の内側の色を生成するフラグメントシェーダーが必要です。これらをシェーダー言語である Slang で記述し、同じファイルから 2 つのエントリポイントをコンパイルします。エントリポイントとは、シェーダーステージの実行が開始される関数です。 -tutorial.shaders.details: "次の 2 つの構造体から始めて、{triangleSlang} を作成します:" -tutorial.shaders.fragment.description: "同じファイルにフラグメントエントリポイントを追加します:" -tutorial.shaders.fragment.details: ラスタライズによって、三角形がカバーする画像領域が決定されます。カバーされた領域全体にわたって頂点色が補間され、フラグメントシェーダーによって処理されるデータであるフラグメントが生成されます。{fSMain} は {sVTARGET} を介してこの補間された色を返します。これは最初のカラーアタッチメントを識別します。 -tutorial.shaders.fragment.guidance: 頂点色の補間はアタッチメントのブレンディングとは別個の処理です。ブレンディングは、フラグメントの出力とアタッチメントにすでに格納されている色を結合します。今回の不透明ブレンド状態はその結合を無効にするため、三角形の内側では補間された色が背景を置き換えます。 -tutorial.shaders.fragment.title: フラグメントを着色する -tutorial.shaders.guidance: "{vSInput} は、頂点シェーダーが頂点バッファーから受け取る内容を記述します。セマンティクス {pOSITION0} と {cOLOR0} が入力を識別します。C# のフィールド名だけではそのマッピングは確立されません。" -tutorial.shaders.title: 2 つのシェーダーステージを作成する -tutorial.shaders.vertex.description: "頂点エントリポイントを {triangleSlang} に追加します:" -tutorial.shaders.vertex.details: "GPU は入力頂点ごとにこのエントリポイントを呼び出します。位置に同次座標 {w} を加え、色を引き渡します。頂点ステージの後で位置は w で除算されますが、ここでは x、y、z は変化しません。そのため、上で選んだ位置を正規化デバイス座標として直接理解できます。" -tutorial.shaders.vertex.title: 各頂点を配置する -tutorial.surface.description: "コンテキストは、出力を表示する場所も認識する必要があります。以下を {emphasis} に追加します:" +tutorial.input.title: "頂点入力レイアウト" +tutorial.lifecycle.description: "各フレームは次の順で進みます。" +tutorial.lifecycle.details: "ウィンドウを閉じると {run} が戻り、解放処理へ進みます。各フレームで送信した処理の完了を待っているため、その処理で使用したリソースは解放できます。{windowRun} の後に置く解放処理の全体は次のとおりです。" +tutorial.lifecycle.guidance: "スワップチェーンはネイティブウィンドウを破棄する前に、コンテキストはそのリソースを解放した後に解放します。送信済みコマンドバッファーはキューが回収し、drawable はスワップチェーンが管理するため、どちらにも個別の {dispose} 呼び出しは不要です。" +tutorial.lifecycle.title: "フレームの流れと終了処理" +tutorial.pipeline.behavior: "入力レイアウトの後にパイプラインを作成します。" +tutorial.pipeline.context: "{cullNone} は面のカリングを無効にします。頂点が画面上で時計回りに並んでいても、反時計回りに並んでいても、三角形を描画します。" +tutorial.pipeline.description: "{graphicsPipeline} は、頂点レイアウト、二つのシェーダー、プリミティブの組み立てとアタッチメントへの出力設定をまとめます。" +tutorial.pipeline.details: "頂点とフラグメントの処理はシェーダーが担当します。パイプラインの残りの設定では、プリミティブの組み立て、面のカリング、深度テスト、ブレンドを指定します。" +tutorial.pipeline.guidance: "パイプラインのカラーフォーマットはパスのアタッチメントに合わせ、{swapChainDescFormat} から取得します。{count1} は一ピクセル一サンプルです。" +tutorial.pipeline.item: "{triangleList} は連続する三つの頂点を一組として、三角形を組み立てます。" +tutorial.pipeline.notes: "{depthNone} は深度テストと深度書き込みを無効にします。深度アタッチメントを使わないパスと対応します。" +tutorial.pipeline.reference: "{opaque} はブレンドを無効にします。三角形の内部では、フラグメントシェーダーの色が背景を置き換えます。" +tutorial.pipeline.title: "グラフィックスパイプライン" +tutorial.pipeline.usage: "シェーダーオブジェクトはパイプライン作成後に解放できます。パイプラインは描画中保持し、終了処理で {vertexBufferDispose} の前に {pipelineDispose} を加えます。" +tutorial.presentation.title: "グラフィックスコンテキストと提示" +tutorial.project.context: "プロジェクトのビルド設定で {emphasis}({allowUnsafeBlocks})を有効にします。ウィンドウ補助コードのネイティブ呼び出しと頂点の転送に unsafe コードが必要です。" +tutorial.project.context.emphasis: "アンセーフコードの許可" +tutorial.project.description: ".NET 10 を対象とする、{firstTriangle} という名前の C# コンソールプロジェクトを作成します。" +tutorial.project.details: "プロジェクトに次の NuGet パッケージを追加します。" +tutorial.project.guidance: "{zenithNET} が共通の描画 API を、三つのバックエンドパッケージが各実装を提供します。{zenithNETCompiler} は後で作る Slang シェーダーを対象バックエンド向けにコンパイルします。Silk.NET はウィンドウの作成とイベント処理を担当します。" +tutorial.project.title: "プロジェクトの準備" +tutorial.requirements.context: "{link}とその{detail}が、このチュートリアルの参照実装です。" +tutorial.requirements.context.detail: "共有ホスト" +tutorial.requirements.context.link: "Hello Triangle サンプル" +tutorial.requirements.description: "{emphasis} と C# の基礎知識が必要です。アプリケーションの対象フレームワークは {net10} です。GPU とドライバーは、プラットフォームごとに選ぶ次のバックエンドに対応している必要があります。" +tutorial.requirements.description.emphasis: ".NET 10 SDK" +tutorial.requirements.guidance: "Zenith.NET はアプリケーションから渡されたネイティブサーフェスへ描画します。Silk.NET.Windowing がウィンドウとイベントを管理します。macOS の提示には {cAMetalLayerCs} で表される Metal レイヤーを使い、補助コードがウィンドウへ取り付けます。" +tutorial.requirements.table.headings.graphicsBackend: "グラフィックスバックエンド" +tutorial.requirements.table.headings.platform: "プラットフォーム" +tutorial.requirements.table.linux.graphicsBackend: "Vulkan 1.4" +tutorial.requirements.table.linux.platform: "Linux(X11 または XWayland)" +tutorial.requirements.table.macOS.graphicsBackend: "Metal 4" +tutorial.requirements.table.macOS.platform: "macOS" +tutorial.requirements.table.windows.graphicsBackend: "DirectX 12" +tutorial.requirements.table.windows.platform: "Windows" +tutorial.requirements.title: "前提条件" +tutorial.resize.context: "アプリケーションをもう一度ビルドして実行します。リサイズしても背景がウィンドウ全体を覆うことを確認してください。新しいレンダーパスでは、変更後のアタッチメントの寸法からビューポートとシザーが設定されます。描画コールバックはそのまま残し、後でこのパスに三角形の描画を加えます。" +tutorial.resize.description: "フレームバッファーの寸法が変わったら、スワップチェーンも合わせて変更します。描画コールバックの後、{windowRun} の前に {framebufferResize} のコールバックを登録します。" +tutorial.resize.details: "ウィンドウの論理寸法ではなく、ピクセル単位の{link}を受け取ります。最小化によって幅か高さがゼロになった場合、リサイズコールバックはスワップチェーンを変更しません。描画コールバックも、どちらかの寸法がゼロの間はそのまま戻ります。有効な寸法に戻るまで描画を中断するためです。" +tutorial.resize.details.link: "フレームバッファーサイズの変化" +tutorial.resize.guidance: "描画コールバックは、送信したフレームの完了を待ってから {present} を呼びます。そのため、リサイズコールバックがスワップチェーンの画像を置き換える時点では、以前のフレームによる処理は終わっています。完了とリソースの寿命に関する条件は、{link}で詳しく説明します。" +tutorial.resize.guidance.link: "同期" +tutorial.resize.title: "リサイズ" +tutorial.shaders.compilation.context: "{appContextBaseDirectory} を使うと、コピーしたシェーダーをアプリケーションの出力ディレクトリから読み込みます。別の作業ディレクトリから起動しても、ファイルを探す場所は変わりません。" +tutorial.shaders.compilation.description: "{triangleSlang} のファイルプロパティで {emphasis} を {detail} に設定します。ビルド時にシェーダーが実行ファイルの隣へコピーされます。" +tutorial.shaders.compilation.description.detail: "新しい場合はコピーする" +tutorial.shaders.compilation.description.emphasis: "出力ディレクトリにコピー" +tutorial.shaders.compilation.details: "{programCs} に戻り、頂点のアップロード後、描画コールバック前にシェーダーの初期化を追加します。" +tutorial.shaders.compilation.guidance: "{zenithCompiler} は {contextGraphicsApi} のバックエンド向けにソースをコンパイルします。{createShader} は、コンパイル済みの記述からシェーダーオブジェクトを作成します。エントリーポイント名 {vSMain} と {fSMain} は、Slang ファイルに定義した二つの関数を選択します。" +tutorial.shaders.compilation.title: "シェーダーのコンパイル" +tutorial.shaders.context: "{fSInput} は二つのシェーダーステージをつなぎます。頂点シェーダーはクリップ空間の位置を {sVPOSITION} に書き込み、GPU はその位置から三角形の見える範囲を判断します。{cOLOR0} は頂点色を渡すフィールドです。色は三角形の内部で補間されてから、フラグメントシェーダーに届きます。両ステージで色の型とセマンティクスを一致させる必要があります。" +tutorial.shaders.description: "シェーダーは GPU 上で実行するプログラムです。頂点シェーダーは各頂点の位置を決め、フラグメントシェーダーは画像の覆われた位置の色を決めます。両ステージを一つの Slang ファイルに書き、それぞれにエントリーポイントを定義します。エントリーポイントは、そのステージの実行が始まる関数です。" +tutorial.shaders.details: "{triangleSlang} を作成し、次の入出力構造体を書きます。" +tutorial.shaders.fragment.description: "同じファイルにフラグメントのエントリーポイントを追加します。" +tutorial.shaders.fragment.details: "ラスタライズは三角形が画像を覆う範囲を調べ、その位置にフラグメントを生成します。各フラグメントの色は、三つの頂点色を補間して求めます。{fSMain} がその色を返し、{sVTARGET} が最初のカラーアタッチメントへの出力を指定します。" +tutorial.shaders.fragment.title: "フラグメントシェーダー" +tutorial.shaders.guidance: "{vSInput} は頂点シェーダーの入力です。{pOSITION0} と {cOLOR0} はセマンティクスによって属性を対応付けます。C# のフィールド名だけでは、この対応は決まりません。" +tutorial.shaders.title: "シェーダーステージ" +tutorial.shaders.vertex.description: "{triangleSlang} に頂点のエントリーポイントを追加します。" +tutorial.shaders.vertex.details: "GPU は入力頂点ごとにこの関数を呼びます。同次座標 {w} を追加し、色をそのまま渡します。頂点処理後に位置を w で割りますが、ここでは 1 なので x、y、z は変わらず、正規化デバイス座標として直接解釈できます。" +tutorial.shaders.vertex.title: "頂点シェーダー" +tutorial.surface.description: "ネイティブの提示先を{emphasis}に指定します。" tutorial.surface.description.emphasis: "{windowCenter} の後、{windowRun} の前" -tutorial.surface.details: "{surface} はネイティブプレゼンテーションターゲットとそのピクセルサイズを記述します。フレームバッファーは、ウィンドウに関連付けられたピクセル画像です。{framebufferSize} はそのピクセル単位のサイズを示します。ディスプレイのスケーリングが有効な場合、ウィンドウの論理サイズとは異なることがあります。" -tutorial.surface.guidance: サーフェスは上で選択したバックエンドと一致します。Windows はウィンドウハンドルを提供し、Linux は X11 ディスプレイとウィンドウを提供し、macOS ヘルパーは接続された Metal レイヤーを提供します。これはウィンドウをレンダリングに接続するための唯一のプラットフォーム固有の部分です。 -tutorial.surface.title: ネイティブサーフェスを記述する -tutorial.swapChain.context: "スワップチェーンはコンテキストとネイティブウィンドウの両方を使用します。{programCs} の末尾にある {windowDispose} の行を、次のクリーンアップ順序に置き換えます:" -tutorial.swapChain.description: "サーフェスの記述を使用して、表示される画像を作成します。サーフェスブロックの直後に以下を追加してください:" -tutorial.swapChain.details: "{swapChain} はウィンドウに表示される画像を管理します。各フレームで、{drawable} は画像データの API 型である {texture} として現在の画像を提供します。描画後、{present} は結果の表示を要求し、次の drawable へ進みます。" -tutorial.swapChain.guidance: "{b8G8R8A8UNorm} は、青、緑、赤、アルファの順序で 4 つの 8 ビットカラーチャンネルを格納します。{uNorm} は、0 から 255 の整数値が 0 から 1 の値を表すことを意味します。シェーダーは論理的な RGBA 値を返しますが、この形式によって画像内でのチャンネルの格納方法が決まります。後ほどグラフィックスパイプラインは {swapChainDescFormat} を使用してこのアタッチメントと一致させます。" -tutorial.swapChain.title: スワップチェーンを作成する -tutorial.title: 最初の三角形 -tutorial.troubleshooting.description: "まずコンソールでエラーを確認し、前のチェックポイントを使用して失敗したステージを特定します:" -tutorial.troubleshooting.details: "{link} と {detail} を使用して、頂点データ、入力レイアウト、描画操作を比較してください。そのサンプルではウィンドウ処理とサブミットを共有ホストに配置していますが、このチュートリアルではアプリケーションフローを {programCs} 内に保持しています。インデックス描画、変換、深度テストを学習するには、{context} に進んでください。" -tutorial.troubleshooting.details.context: 回転する立方体 -tutorial.troubleshooting.details.detail: Slang シェーダー -tutorial.troubleshooting.details.link: サンプルレンダラー -tutorial.troubleshooting.table.backend.check: 選択したバックエンドがデバイスおよびインストールされているグラフィックスドライバーでサポートされていることを確認してください。 -tutorial.troubleshooting.table.backend.symptom: バックエンドの作成に失敗する -tutorial.troubleshooting.table.drawing.check: アップロードサイズ、入力レイアウト、パイプラインの選択、およびレンダーパス内の描画コマンドの配置を確認してください。 -tutorial.troubleshooting.table.drawing.symptom: 背景は表示されるが三角形が表示されない -tutorial.troubleshooting.table.headings.check: 確認事項 -tutorial.troubleshooting.table.headings.symptom: 症状 -tutorial.troubleshooting.table.input.check: "28 バイトの ストライド と、0 および 12 の位置/色のオフセットを確認してください。" -tutorial.troubleshooting.table.input.symptom: 頂点の位置や色が破損している -tutorial.troubleshooting.table.shaders.check: コピーされた {triangleSlang}、エントリポイントのスペル、およびコンパイラが報告した診断情報を確認してください。 -tutorial.troubleshooting.table.shaders.symptom: クリア色のステップは機能するが、シェーダーの読み込みに失敗する -tutorial.troubleshooting.table.window.check: .NET プロジェクトがビルドされ、ウィンドウ単体のステップがデスクトップセッションで実行されることを確認してください。Linux では、X11 または XWayland が利用可能であることを確認してください。 -tutorial.troubleshooting.table.window.symptom: ウィンドウが開かない -tutorial.troubleshooting.title: 失敗したステージを確認する -tutorial.window.context: "{usingZenithTutorials} はヘルパーの名前空間をインポートします。各 C# ファイルは通常の using ディレクティブを使用するため、相互運用機能のインポートは両方のファイルで必要です。エイリアス {buffer} は Zenith.NET のバッファー型を指し、{systemBuffer} と区別します。" -tutorial.window.description: "{cocoaHelperCs} を名前空間を維持したままプロジェクトに追加します。そのファイルの先頭、名前空間宣言の前に {interopUsing} を追加してください。このヘルパーは macOS で Metal レイヤーをウィンドウに接続します。他のプラットフォームブランチではこれを呼び出しません。" -tutorial.window.details: "生成された {programCs} を次のコードに置き換えます。明示的な {main} メソッドなしで順番に実行される最上位レベルのステートメントを使用しています。以降のセクションで、この同じファイルにコードを追加する場所を説明します:" -tutorial.window.guidance: "{graphicsAPINone} は、Silk.NET に独自のグラフィックスコンテキストを持たないウィンドウを作成するよう要求します。そのコンテキストは Zenith.NET で作成します。{initialize} はネイティブウィンドウを作成し、そのハンドルを使用可能にします。ハンドルとは、ウィンドウシステムによって提供される識別子です。{center} はウィンドウを中央に配置し、{run} はウィンドウが閉じるまでイベントを処理します。その後、実行はウィンドウを解放する {dispose} に進みます。" -tutorial.window.notes: "{dotnetRun} を実行してください。空のウィンドウが開き、移動、サイズ変更、閉じる操作に応答するはずです。レンダリングコマンドをまだサブミットしていないため、内容はまだ定義されていません。確認したら閉じて次に進んでください。" -tutorial.window.title: ウィンドウを開く -ui.action.copy: コピー -ui.action.navigate: 移動 -ui.action.open: 開く -ui.action.source: ソースを表示 -ui.api.browse: 名前空間と型を参照します。 -ui.api.clearTypeSearch: 型の検索をクリア -ui.api.findType: 型を検索 -ui.api.loadError: 型を読み込めませんでした。このページを再読み込みしてやり直してください。 -ui.api.loadingNamespaces: 名前空間を読み込み中… -ui.api.loadingTypes: 型を読み込み中… -ui.api.matchingTypes: 一致する型 -ui.api.namespace: 名前空間 -ui.api.namespaces: 名前空間 -ui.api.noNamespaceTypes: この名前空間には型がありません。 -ui.api.noTypes: 一致する型はありません。 -ui.api.types: 型 -ui.content.reference: リファレンス -ui.content.source: ソースコード -ui.content.tutorial: チュートリアル -ui.contents.close: 目次を閉じる -ui.contents.open: 目次を開く -ui.contents.title: 目次 -ui.footer.caption: .NET 向けモダン RHI。 -ui.footer.label: フッター -ui.language.label: 言語 -ui.language.unavailable: 未翻訳 -ui.members.clear: メンバー検索をクリア -ui.members.close: メンバー検索を閉じる -ui.members.empty: 一致するメンバーはありません。 -ui.members.open: メンバーへ移動 -ui.members.placeholder: 名前またはシグネチャ… -ui.members.search: メンバーを検索 -ui.members.title: メンバーを検索 -ui.members.undeclared: この型には宣言されたメンバーがありません。 -ui.navigation.api: API -ui.navigation.concepts: 概念 -ui.navigation.home: ホーム -ui.navigation.label: メインナビゲーション -ui.navigation.toggle: ナビゲーションの切り替え -ui.outline.title: このページの内容 -ui.reference.assembly: アセンブリ -ui.reference.classes: クラス -ui.reference.constructors: コンストラクター +tutorial.surface.details: "フレームバッファーは、ウィンドウが表示するピクセル画像です。{surface} はネイティブの提示先と寸法を記述し、{framebufferSize} はピクセル単位のサイズを返します。表示倍率によっては、ウィンドウの論理サイズと異なります。" +tutorial.surface.guidance: "サーフェスにはバックエンドが必要とするネイティブハンドルを渡します。Windows は Win32 ウィンドウ、Linux は X11 のディスプレイとウィンドウ、macOS は取り付けた Metal レイヤーを使います。" +tutorial.surface.title: "ネイティブサーフェス" +tutorial.swapChain.context: "スワップチェーンはコンテキストとウィンドウの両方に依存します。{programCs} 末尾の {windowDispose} を次の解放順序に置き換えます。" +tutorial.swapChain.description: "サーフェス記述の直後にスワップチェーンを作成します。" +tutorial.swapChain.details: "{swapChain} はウィンドウが提示する画像を管理します。{drawable} は現在の画像を、API の画像リソースである {texture} として返します。描画後に {present} が表示を要求し、次の drawable へ進みます。" +tutorial.swapChain.guidance: "{b8G8R8A8UNorm} は青、緑、赤、アルファの順に各 8 ビットを格納します。{uNorm} は整数 0~255 を 0~1 に対応付けます。シェーダー出力は論理的な RGBA のままで、フォーマットは保存表現を定めます。パイプラインは {swapChainDescFormat} でこのアタッチメントに合わせます。" +tutorial.swapChain.title: "スワップチェーン" +tutorial.title: "最初の三角形" +tutorial.troubleshooting.description: "コンソールの診断と三段階の結果を使い、問題のある箇所を特定します。" +tutorial.troubleshooting.details: "{link}と{detail}で頂点データ、入力レイアウト、描画操作を照合できます。サンプルはウィンドウと送信を共通ホストへ分離していますが、このチュートリアルの処理は {programCs} にまとめています。{context}ではインデックス付き描画、変換、深度テストへ進みます。" +tutorial.troubleshooting.details.context: "回転する立方体" +tutorial.troubleshooting.details.detail: "Slang シェーダー" +tutorial.troubleshooting.details.link: "サンプルレンダラー" +tutorial.troubleshooting.table.backend.check: "選択したバックエンドがデバイスおよびインストールされているグラフィックスドライバーでサポートされていることを確認してください。" +tutorial.troubleshooting.table.backend.symptom: "バックエンドの作成に失敗する" +tutorial.troubleshooting.table.drawing.check: "アップロードサイズ、入力レイアウト、パイプラインの選択、およびレンダーパス内の描画コマンドの配置を確認してください。" +tutorial.troubleshooting.table.drawing.symptom: "背景は表示されるが三角形が表示されない" +tutorial.troubleshooting.table.headings.check: "確認事項" +tutorial.troubleshooting.table.headings.symptom: "症状" +tutorial.troubleshooting.table.input.check: "ストライドが 28 バイト、位置と色のオフセットがそれぞれ 0 と 12 バイトであることを確認します。" +tutorial.troubleshooting.table.input.symptom: "頂点の位置や色が破損している" +tutorial.troubleshooting.table.shaders.check: "コピーされた {triangleSlang}、エントリーポイントのスペル、およびコンパイラーが報告した診断情報を確認してください。" +tutorial.troubleshooting.table.shaders.symptom: "背景色は表示されるがシェーダーを読み込めない" +tutorial.troubleshooting.table.window.check: ".NET プロジェクトがビルドされ、ウィンドウ単体のステップがデスクトップセッションで実行されることを確認してください。Linux では、X11 または XWayland が利用可能であることを確認してください。" +tutorial.troubleshooting.table.window.symptom: "ウィンドウが開かない" +tutorial.troubleshooting.title: "問題の切り分け" +tutorial.window.description: "{cocoaHelperCs} をダウンロードしてプロジェクトに追加します。この補助クラスが macOS のウィンドウに Metal レイヤーを取り付けます。" +tutorial.window.details: "自動生成された {programCs} の内容を、次のコードに置き換えます。トップレベルステートメントを使うため、明示的な {main} メソッドを書かずに、上から順に実行できます。続く各節でコードを追加する位置を示します。" +tutorial.window.guidance: "{graphicsAPINone} で、グラフィックスコンテキストの作成を Zenith.NET に任せます。{initialize} はネイティブウィンドウを作り、ウィンドウシステムのハンドルを利用可能にします。{center} で画面中央に置き、{run} で閉じるまでイベントを処理します。その後、{dispose} でウィンドウを解放します。" +tutorial.window.notes: "アプリケーションをビルドして実行し、ウィンドウを開く、移動する、リサイズする、閉じるという操作を確認します。描画コマンドはまだ送信していないため、表示内容は未定義です。次へ進む前にウィンドウを閉じてください。" +tutorial.window.title: "ウィンドウの作成" +ui.action.copy: "コピー" +ui.action.navigate: "移動" +ui.action.open: "開く" +ui.action.source: "ソースを表示" +ui.api.browse: "名前空間と型を参照します。" +ui.api.clearTypeSearch: "型の検索をクリア" +ui.api.findType: "型を検索" +ui.api.loadError: "型を読み込めませんでした。このページを再読み込みしてやり直してください。" +ui.api.loadingNamespaces: "名前空間を読み込み中…" +ui.api.loadingTypes: "型を読み込み中…" +ui.api.matchingTypes: "一致する型" +ui.api.namespace: "名前空間" +ui.api.namespaces: "名前空間" +ui.api.noNamespaceTypes: "この名前空間には型がありません。" +ui.api.noTypes: "一致する型はありません。" +ui.api.types: "型" +ui.content.reference: "リファレンス" +ui.content.source: "ソースコード" +ui.content.tutorial: "チュートリアル" +ui.contents.close: "目次を閉じる" +ui.contents.open: "目次を開く" +ui.contents.title: "目次" +ui.footer.caption: ".NET 向けのモダンな RHI" +ui.footer.label: "フッター" +ui.language.label: "言語" +ui.language.unavailable: "未翻訳" +ui.members.clear: "メンバー検索をクリア" +ui.members.close: "メンバー検索を閉じる" +ui.members.empty: "一致するメンバーはありません。" +ui.members.open: "メンバーへ移動" +ui.members.placeholder: "名前またはシグネチャ…" +ui.members.search: "メンバーを検索" +ui.members.title: "メンバーを検索" +ui.members.undeclared: "この型には宣言されたメンバーがありません。" +ui.navigation.api: "API" +ui.navigation.concepts: "概念" +ui.navigation.home: "ホーム" +ui.navigation.label: "メインナビゲーション" +ui.navigation.toggle: "ナビゲーションの切り替え" +ui.outline.title: "このページの内容" +ui.reference.assembly: "アセンブリ" +ui.reference.classes: "クラス" +ui.reference.constructors: "コンストラクター" ui.reference.declaration: "C# 型宣言" -ui.reference.delegates: デリゲート -ui.reference.derived: 派生型 -ui.reference.enums: 列挙型 -ui.reference.events: イベント -ui.reference.examples: 例 -ui.reference.exceptions: 例外 -ui.reference.extensionMethods: 拡張メソッド -ui.reference.fields: フィールド -ui.reference.implementations: 明示的なインターフェイスの実装 -ui.reference.implements: 実装 -ui.reference.inheritance: 継承 -ui.reference.inheritedMembers: 継承されたメンバー -ui.reference.interfaces: インターフェイス -ui.reference.metadata: 型のメタデータ -ui.reference.methods: メソッド -ui.reference.namespace: 名前空間 +ui.reference.delegates: "デリゲート" +ui.reference.derived: "派生型" +ui.reference.enums: "列挙型" +ui.reference.events: "イベント" +ui.reference.examples: "例" +ui.reference.exceptions: "例外" +ui.reference.extensionMethods: "拡張メソッド" +ui.reference.fields: "フィールド" +ui.reference.implementations: "明示的なインターフェイスの実装" +ui.reference.implements: "実装" +ui.reference.inheritance: "継承" +ui.reference.inheritedMembers: "継承されたメンバー" +ui.reference.interfaces: "インターフェイス" +ui.reference.metadata: "型のメタデータ" +ui.reference.methods: "メソッド" +ui.reference.namespace: "名前空間" ui.reference.open: "{name} のリファレンスを開く" -ui.reference.operators: 演算子 -ui.reference.parameters: パラメーター -ui.reference.properties: プロパティ -ui.reference.related: 関連項目 -ui.reference.relationships: 継承とメタデータ -ui.reference.remarks: 注記 -ui.reference.returns: 戻り値 -ui.reference.structs: 構造体 -ui.reference.typeParameters: 型パラメーター -ui.reference.value: 値 -ui.reference.values: 値 -ui.search.close: 検索を閉じる -ui.search.empty: 「{query}」に一致する結果は見つかりませんでした。 -ui.search.hint: チュートリアル、概念、サンプル、API リファレンスを検索します。 -ui.search.loading: 検索を読み込み中… -ui.search.more: さらに結果を表示 -ui.search.pending: 検索中… -ui.search.placeholder: 何をお探しですか? +ui.reference.operators: "演算子" +ui.reference.parameters: "パラメーター" +ui.reference.properties: "プロパティ" +ui.reference.related: "関連項目" +ui.reference.relationships: "継承とメタデータ" +ui.reference.remarks: "注記" +ui.reference.returns: "戻り値" +ui.reference.structs: "構造体" +ui.reference.typeParameters: "型パラメーター" +ui.reference.value: "値" +ui.reference.values: "値" +ui.search.close: "検索を閉じる" +ui.search.empty: "「{query}」に一致する結果は見つかりませんでした。" +ui.search.hint: "チュートリアル、概念、サンプル、API リファレンスを検索します。" +ui.search.loading: "検索を読み込み中…" +ui.search.more: "さらに結果を表示" +ui.search.pending: "検索中…" +ui.search.placeholder: "何をお探しですか?" ui.search.resultCount: "検索結果: {count} 件" -ui.search.title: ドキュメントを検索 -ui.search.unavailable: 検索は利用できません。以下のページを直接開くことができます。 +ui.search.title: "ドキュメントを検索" +ui.search.unavailable: "検索は利用できません。以下のページを直接開くことができます。" diff --git a/documents/locales/ja-JP/translation.md b/documents/locales/ja-JP/translation.md index 84a2c96c..4cd5a0a4 100644 --- a/documents/locales/ja-JP/translation.md +++ b/documents/locales/ja-JP/translation.md @@ -8,6 +8,16 @@ 翻訳では、この言語の `strings.yml` の値だけを変更します。キーの集合は英語と完全に一致させます。同じ文言に見えるキーや、まだ画面で見ていないキーも含め、独自の追加・削除・改名はしません。原文に問題があれば、該当キーと問題点を保守担当者に伝えてください。英語と共通ページを先に修正し、その後で訳文を更新します。 +## 文体と文脈 + +技術書として正確で落ち着いた、理解しやすい文章にします。操作同士の関係を説明してから、必要な条件や制約を示します。チュートリアルでは具体的な手順と確認できる結果を残します。専門的な文章にするために、受け身や長い文を増やす必要はありません。 + +記事は前後の段落、表、コードと一緒に、読む順序で見直します。リソースキーは保存の区切りであり、翻訳を一文ずつ切り離すための単位ではありません。リンクラベルや強調部分を本文に戻し、助詞と文のつながりを確認してください。 + +見出し、操作ラベル、ホームの短い紹介文とフッター文言には句点を付けません。本文、診断、アクセシビリティの操作説明では通常の句読点を使います。一つの概念には定着した訳語を一貫して使い、一部の用語だけ英語を括弧で併記しないでください。API、ファイル、実際の設定項目の識別子は保持します。 + +文を残すかどうかは、現在の操作、設計上の選択、確認できる結果、正しく使うための条件を説明しているかで判断します。使わない機能の列挙、漠然とした環境上の注意、前提条件の繰り返しは省きます。見出しや装飾で分かれた句も全体を翻訳し、日本語の語順にします。ホームの `{accent}` と `{lineBreak}` は移動でき、装飾や改行で英語の語順を固定しません。文章の削除に伴う原文・共通マークアップ・全言語のキー変更は、保守担当者がまとめて行います。 + ## テキストとプレースホルダー 文または段落全体を、簡潔で自然な「です・ます」調の日本語に翻訳します。前提条件、否定、単位、操作順序、リソースの有効期間に関する制約を維持してください。原文にない技術的な保証、プラットフォーム要件、パッケージのバージョン、リリース情報を追加しません。製品名、パッケージ名、ファイル名、C# と Slang の識別子は、大文字と小文字も含めて変更しません。 diff --git a/documents/locales/ko-KR/strings.yml b/documents/locales/ko-KR/strings.yml index d93714ff..552de82c 100644 --- a/documents/locales/ko-KR/strings.yml +++ b/documents/locales/ko-KR/strings.yml @@ -1,135 +1,134 @@ ### YamlMime:Resources -concepts.execution.context.description: "{graphicsContext}는 하나의 백엔드 장치를 나타내며 그래픽, 컴퓨팅 및 전송 큐를 제공합니다. 동일한 컨텍스트를 통해 워크로드에 대한 버퍼, 텍스처, 셰이더 및 파이프라인을 생성하세요. 다른 컨텍스트에서 생성된 리소스나 핸들은 이 컨텍스트의 명령 버퍼에 단순히 바인딩할 수 없습니다." -concepts.execution.context.details: 플랫폼 및 프레젠테이션 서피스에 적합한 백엔드를 선택하세요. API는 공유되지만 장치 지원 여부는 여전히 중요합니다. {capabilities}는 장치 이름과 {rayTracingSupported} 및 {meshShadingSupported} 플래그를 노출합니다. {link} 및 {detail} 샘플에서처럼 선택적 워크로드를 생성하기 전에 해당 플래그를 확인하세요. 이러한 플래그는 형식, 메모리 또는 플랫폼 제한 사항에 대한 완전한 목록이 아닙니다. +concepts.execution.context.description: "{graphicsContext}는 특정 백엔드를 통해 애플리케이션을 GPU 장치에 연결하고 그래픽스, 컴퓨트, 전송 큐를 제공합니다. 함께 사용하는 리소스는 같은 컨텍스트에 속해야 합니다. 버퍼, 텍스처, 셰이더, 파이프라인과 그 핸들은 서로 다른 컨텍스트 사이에서 바인딩할 수 없습니다." +concepts.execution.context.details: "{capabilities}는 장치 이름과 지원 기능을 알려 줍니다. 해당 기능의 리소스를 만들기 전에 {rayTracingSupported}와 {meshShadingSupported}로 지원 여부를 확인합니다. {link} 및 {detail} 예제는 초기화 과정에서 이 검사를 수행합니다." concepts.execution.context.details.detail: 메시 셰이딩 concepts.execution.context.details.link: 레이 트레이싱 -concepts.execution.context.title: 컨텍스트는 리소스와 큐를 연결 -concepts.execution.description: Zenith.NET 애플리케이션은 GPU 리소스를 생성하고, 이를 사용하는 명령을 기록하며, 해당 명령을 큐에 제출합니다. GPU가 제출된 작업을 실행하는 동안 CPU는 작업을 계속할 수 있습니다. 기록 호출이 반환된 후에도 해당 작업이 완료될 때까지 리소스를 유효하게 유지하세요. -concepts.execution.ownership.description: "여기서 소유권은 해제에 대한 책임을 의미합니다. C# 참조는 관리되는 개체에 대한 도달 가능성을 유지하지만 명시적인 {dispose}가 네이티브 리소스를 파괴하는 것을 막지는 않습니다. 마찬가지로 버퍼를 사용하는 명령을 제출한다고 해서 해당 버퍼의 소유권이 큐로 이전되는 것은 아닙니다." -concepts.execution.ownership.details: "종료 시 새 작업 제출을 중지하고 관련된 모든 큐의 마지막 사용을 기다린 후 애플리케이션의 리소스를 해제한 다음 컨텍스트를 해제하세요. 컨텍스트를 해제하면 자체 큐와 내부 도우미가 해제되며, 모든 애플리케이션 작업을 기다리거나 애플리케이션이 생성한 모든 리소스를 해제하지는 않습니다." -concepts.execution.ownership.guidance: "렌더링 중에도 같은 수명 규칙을 적용하세요. 리소스의 마지막 사용에 대한 완료 값을 보관하여 데이터를 덮어쓰거나 리소스를 교체할 수 있는 시점을 판단하세요. 뷰와 기반 리소스의 수명은 {link}를 참고하세요." +concepts.execution.context.title: "그래픽스 컨텍스트" +concepts.execution.description: "GPU 작업은 CPU에서 준비합니다. 애플리케이션이 리소스를 만들고 이를 사용하는 명령을 기록한 뒤 큐에 제출하면, GPU가 명령을 실행하는 동안 CPU는 다른 작업을 계속할 수 있습니다. 사용 중인 리소스는 GPU 실행이 끝날 때까지 유효하게 유지해야 합니다." +concepts.execution.ownership.description: "소유권은 객체를 해제할 주체를 정하고, GPU 작업의 완료 여부는 해제할 수 있는 시점을 정합니다. C# 참조가 남아 있어도 {dispose}를 호출하면 네이티브 리소스가 해제됩니다. 명령을 제출한다고 해당 리소스의 소유권이 큐로 넘어가지는 않습니다." +concepts.execution.ownership.details: "애플리케이션을 종료할 때는 새 작업 제출을 중단하고, 관련된 모든 큐에서 리소스의 마지막 사용이 끝날 때까지 기다립니다. 그런 다음 애플리케이션 리소스를 해제하고 컨텍스트를 정리합니다. 컨텍스트는 자체 큐와 내부 보조 객체를 해제하므로 애플리케이션 작업이 모두 끝난 뒤 마지막에 정리해야 합니다." +concepts.execution.ownership.guidance: "렌더링 중에는 덮어쓸 데이터나 교체할 리소스를 사용하는 작업의 완료 시점을 추적합니다. 해당 작업이 끝날 때까지 기다린 뒤 저장 공간을 수정하거나 해제합니다. 뷰와 원본 리소스에도 이 수명 관리 원칙을 적용하는 방법은 {link} 문서에서 설명합니다." concepts.execution.ownership.guidance.link: 리소스 관리 concepts.execution.ownership.table.applicationResources.object: 애플리케이션이 생성한 리소스 concepts.execution.ownership.table.applicationResources.ownership: 애플리케이션이 마지막 GPU 사용 후 해제합니다. concepts.execution.ownership.table.commandBuffers.object: 대여한 명령 버퍼 concepts.execution.ownership.table.commandBuffers.ownership: 큐가 관리하고 재활용합니다. -concepts.execution.ownership.table.headings.object: 개체 -concepts.execution.ownership.table.headings.ownership: 누가 해제하는가? +concepts.execution.ownership.table.headings.object: "객체" +concepts.execution.ownership.table.headings.ownership: "해제 책임" concepts.execution.ownership.table.queues.object: 컨텍스트 큐 및 해당 타임라인 concepts.execution.ownership.table.queues.ownership: 컨텍스트와 큐가 관리합니다. concepts.execution.ownership.table.swapChainDrawable.ownership: 스왑 체인이 관리합니다. -concepts.execution.ownership.title: 소유권과 GPU 완료를 구분하여 유지 -concepts.execution.pipelines.description: "그래픽 파이프라인은 셰이더, 정점 입력 레이아웃, 정점을 기본형으로 조립하는 규칙, 어태치먼트 형식과 렌더 상태를 결합합니다. 정점, 인덱스 또는 상수 데이터를 바인딩하고 드로잉 명령을 기록하기 전에 설정하세요. 어태치먼트 형식과 샘플 수는 렌더 패스의 어태치먼트와 일치해야 합니다." -concepts.execution.pipelines.details: 컴퓨팅 파이프라인은 GPU 스레드 그룹을 시작하는 디스패치용 셰이더 진입점을 제공합니다. 디스패치하기 전에 파이프라인과 해당 상수를 설정하세요. 컴퓨팅 디스패치는 그래픽 렌더 패스 외부에 속합니다. 파이프라인 변경은 후속 명령이 입력을 해석하는 방식의 변경을 의미하므로, 선택한 파이프라인에 필요한 데이터를 사용하기 전에 바인딩하세요. -concepts.execution.pipelines.guidance: "{link}는 전체 그래픽 시퀀스를 보여줍니다. {detail}는 디스패치를 기록한 다음 결과를 표시하는 그래픽 패스를 기록합니다." -concepts.execution.pipelines.guidance.detail: 컴퓨팅 샘플 +concepts.execution.ownership.title: "소유권과 수명" +concepts.execution.pipelines.description: "그래픽스 파이프라인은 셰이더, 정점 입력 레이아웃, 프리미티브 조립, 어태치먼트의 포맷, 그리기 상태를 정의합니다. 정점, 인덱스, 상수 데이터를 바인딩하기 전에 파이프라인을 선택합니다. 어태치먼트의 포맷과 샘플 수는 렌더 패스와 일치해야 합니다." +concepts.execution.pipelines.details: "컴퓨트 파이프라인은 디스패치가 실행할 셰이더 진입점을 선택합니다. 그래픽스 렌더 패스 밖에서 파이프라인과 상수를 바인딩한 뒤 디스패치합니다." +concepts.execution.pipelines.guidance: "{link}에서는 그래픽스 명령 순서를, {detail}에서는 계산 결과를 표시하는 패스 앞에 컴퓨트 디스패치를 추가하는 구성을 볼 수 있습니다." +concepts.execution.pipelines.guidance.detail: "컴퓨트 예제" concepts.execution.pipelines.guidance.link: 삼각형의 렌더링 콜백 -concepts.execution.pipelines.title: 파이프라인이 명령의 데이터 해석 방식 결정 -concepts.execution.queues.description: 한 프레임에서 드로잉, 컴퓨팅 및 복사를 결합하는 경우 {graphicsQueue}로 시작하세요. 종속된 작업을 하나의 큐에 유지하면 순서를 파악하기가 더 쉬워집니다. -concepts.execution.queues.details: 큐는 실행을 위한 명령 배치를 수락합니다. 별도의 큐가 반드시 별도의 하드웨어 엔진에 해당하는 것은 아니므로 작업이 동시에 실행되지 않을 수도 있습니다. 워크로드가 중첩 실행의 이점을 얻을 수 있는 경우 다른 큐를 사용하고, 한 큐가 다른 큐의 결과를 소비할 때 명시적 종속성을 추가하세요. -concepts.execution.queues.guidance: 이후 명령이 이전 쓰기에 의존하는 경우, 애플리케이션은 해당 쓰기가 이후 명령에서 사용 가능한지 확인해야 합니다. 두 명령 버퍼를 동일한 큐에 제출한다고 해서 이러한 모든 종속성이 자동으로 설정되는 것은 아닙니다. 명령은 서로 다른 GPU 단계를 사용할 수 있으며, 이후 접근 시 배리어나 텍스처 전환이 필요할 수 있습니다. {link}에서 제출 순서와 리소스 가시성의 차이를 설명합니다. +concepts.execution.pipelines.title: "파이프라인 상태" +concepts.execution.queues.description: "그리기, 계산, 복사를 한 프레임에서 수행한다면 일반적으로 {graphicsQueue}부터 사용합니다. 서로 의존하는 작업을 한 큐에 두면 순서를 관리하기 쉽습니다." +concepts.execution.queues.details: "큐를 나누면 독립적인 작업을 각각 제출할 수 있지만, 각 큐가 반드시 독립된 하드웨어 엔진에 대응하는 것은 아닙니다. 작업을 겹쳐 실행할 때 이점이 있다면 추가 큐를 사용합니다. 한 큐가 다른 큐에서 만든 데이터를 사용한다면 두 제출 사이에 의존성을 명시합니다." +concepts.execution.queues.guidance: "한 큐 안에서도 뒤의 접근이 앞서 쓴 데이터를 볼 수 있도록 배리어나 텍스처 전환이 필요할 수 있습니다. 이러한 메모리 의존성은 제출 순서와 구별됩니다. 구체적인 표현 방법은 {link} 문서에서 설명합니다." concepts.execution.queues.guidance.link: 동기화 -concepts.execution.queues.table.computeQueue.workToRecord: 그래픽 렌더 패스를 제외한 컴퓨팅 디스패치 및 호환 가능한 전송 작업. -concepts.execution.queues.table.graphicsQueue.workToRecord: 렌더 패스 및 드로잉, 그리고 프레임에서 사용되는 컴퓨팅 및 전송 작업. +concepts.execution.queues.table.computeQueue.workToRecord: "그래픽 렌더 패스를 제외한 컴퓨트 디스패치 및 호환 가능한 전송 작업." +concepts.execution.queues.table.graphicsQueue.workToRecord: "렌더 패스, 그리기, 컴퓨트 및 전송 작업." concepts.execution.queues.table.headings.queue: 큐 -concepts.execution.queues.table.headings.workToRecord: 기록할 작업 -concepts.execution.queues.table.transferQueue.workToRecord: 드로잉이나 컴퓨팅 디스패치를 제외한 업로드, 다운로드 및 복사 작업. -concepts.execution.queues.title: 실행할 작업에 맞는 큐 선택 -concepts.execution.recording.context: "큐는 완료를 폴링하고 완료된 명령 버퍼를 재활용합니다. 새로운 각 기록에 대해 {queueCommandBuffer}를 호출하세요. 재활용된 인스턴스가 반환될 수 있습니다. 대여한 명령 버퍼를 직접 해제하거나, 두 번 제출하거나, 제출 후에도 계속 기록하지 마세요. 지정된 명령 버퍼는 한 번에 하나의 스레드에서만 기록하세요. 큐의 내부 잠금은 명령 버퍼에 대한 동시 편집을 보호하지 않습니다." -concepts.execution.recording.description: "{queueCommandBuffer}는 기록이 이미 시작된 {commandBuffer}를 반환합니다. 명령과 해당 종속성을 기록한 다음 {submit}을 한 번 호출합니다. 제출하면 기록이 종료되고 해당 큐의 완료 지점을 식별하는 {timelineValue}가 반환됩니다." -concepts.execution.recording.details: "예를 들어, 프레임을 {commandBuffer}에 기록한 후 삼각형 튜토리얼은 이를 제출하고 다음과 같이 완료를 기다립니다:" -concepts.execution.recording.guidance: "{submit}은 작업을 예약하고, {wait}는 해당 제출이 완료될 때까지 CPU가 계속 진행되지 않도록 유지합니다. 드로잉 기록, 렌더 패스 종료 및 명령 버퍼 제출은 별개의 작업입니다. 드로잉을 기록하거나 패스를 종료하는 작업 모두 GPU를 기다리지 않습니다." -concepts.execution.recording.title: 기록은 명령을 실행하지 않음 +concepts.execution.queues.table.headings.workToRecord: "지원 작업" +concepts.execution.queues.table.transferQueue.workToRecord: "업로드, 다운로드 및 복사 작업. 그리기나 컴퓨트 디스패치는 지원하지 않습니다." +concepts.execution.queues.title: "큐 선택" +concepts.execution.recording.context: "큐는 완료된 명령 버퍼를 회수해 재사용합니다. 명령을 기록할 때마다 {queueCommandBuffer}로 버퍼를 가져오고, 한 번에 한 스레드에서 기록한 뒤 한 번만 제출합니다. 제출 후에는 큐가 버퍼를 관리하므로 수정하거나 다시 제출하거나 해제하지 않습니다." +concepts.execution.recording.description: "{queueCommandBuffer}가 반환하는 {commandBuffer}는 이미 기록을 시작한 상태입니다. 작업과 의존 관계를 기록한 후 {submit}을 한 번 호출합니다. 기록이 종료되고 명령이 제출되며, 해당 큐의 완료 지점을 나타내는 {timelineValue}가 반환됩니다." +concepts.execution.recording.details: "삼각형 튜토리얼은 {commandBuffer}에 프레임을 기록한 뒤 다음과 같이 제출하고 완료를 기다립니다." +concepts.execution.recording.guidance: "기록은 명령 시퀀스를 구성하고, {submit}은 그 시퀀스의 실행을 예약합니다. 이어서 {wait}를 호출하면 해당 제출이 끝날 때까지 CPU 스레드가 대기합니다. 튜토리얼에서는 각 프레임이 끝난 뒤 다음 프레임을 시작하므로 실행 흐름을 쉽게 따라갈 수 있습니다." +concepts.execution.recording.title: "명령 기록과 제출" concepts.execution.title: 실행 모델 -concepts.platforms.description: 애플리케이션이 네이티브 윈도우와 프레임 루프를 소유할지 아니면 UI 렌더링 컨트롤을 사용할지 선택하세요. 이 선택에 따라 출력 텍스처를 얻고, 명령을 제출하며, 결과를 표시하는 주체가 결정됩니다. 출력 텍스처는 현재 프레임의 출력으로 사용되는 텍스처입니다. 오프스크린 그래픽 및 컴퓨팅 작업에는 윈도우나 스왑 체인이 필요하지 않습니다. -concepts.platforms.frame.context: "해당 패스 내에 파이프라인 바인딩과 드로잉 명령을 추가하세요. 반환하기 전에 패스를 종료합니다. 제공된 명령 버퍼를 독립적으로 제출하거나 별도로 표시하지 마세요. 또한 명령 버퍼나 출력 텍스처를 해제하지 마세요. 핸들러가 다른 레이아웃에서 출력 텍스처를 사용하는 경우 컨트롤의 최종 전환을 위해 {colorAttachment}로 되돌립니다." -concepts.platforms.frame.description: 통합 기능은 {iZenithView}를 구현합니다. 애플리케이션은 {graphicsContext}를 제공하고, {updateRequested}에서 장면 데이터를 업데이트하며, {renderEventArgs}를 사용하여 {renderRequested}에서 렌더링을 기록합니다. -concepts.platforms.frame.details: "컨트롤은 각 프레임의 전체 흐름을 관리합니다. 출력 텍스처와 명령 버퍼를 가져오고, 출력 텍스처를 {colorAttachment}로 전환한 뒤 핸들러를 호출합니다. 이후 프레임워크에 필요한 제출과 프레젠테이션 단계를 수행합니다." -concepts.platforms.frame.guidance: "컨텍스트가 할당된 {view}라는 초기화된 {iZenithView}의 경우, 이 핸들러는 완전한 클리어 패스를 기록합니다. {usingZenithNET}이 필요합니다:" -concepts.platforms.frame.notes: 컨트롤은 각 프레임 시작 시 {undefined}에서 전환하므로 애플리케이션은 출력 텍스처의 이전 내용이 보존되는 것에 의존할 수 없습니다. 각 프레임마다 필요한 이미지를 지우거나 렌더링하세요. 지속적인 누적이나 캐시된 렌더링은 애플리케이션 소유의 텍스처에 유지한 다음 뷰를 통해 해당 텍스처를 표시하세요. -concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat}은 통합의 기본 색상 형식을 제공합니다. 어태치먼트 형식, 샘플 수 및 치수를 일치시킬 때 실제 이벤트의 출력 텍스처를 확인하세요." -concepts.platforms.frame.title: UI 컨트롤이 제공하는 프레임에 기록 -concepts.platforms.integration.context: WinForms, WPF 및 Windows WinUI 경로는 Windows가 필요합니다. MAUI 애플리케이션에는 대상 플랫폼의 워크로드가 필요하며 {useZenithView}로 컨트롤 핸들러를 등록해야 합니다. {extensionsCs}를 참조하세요. 프레임워크 지원과 백엔드 지원이 모두 충족되어야 합니다. -concepts.platforms.integration.description: "컨트롤은 이벤트 인터페이스를 공유하지만 모두 동일한 방식으로 표시되지는 않습니다:" -concepts.platforms.integration.details: 비트맵 리드백(bitmap readback)은 UI가 표시하기 전에 렌더링된 픽셀을 CPU 메모리에 복사합니다. 공유 텍스처 상호 운용성은 해당 리드백을 방지하지만 여전히 GPU 복사 및 동기화가 필요할 수 있습니다. 따라서 공유 {renderRequested} 인터페이스가 동일한 프레젠테이션 비용이나 네이티브 상호 운용성 요구 사항을 의미하지는 않습니다. -concepts.platforms.integration.guidance: "애플리케이션 프레임워크에 맞는 패키지를 사용하세요. 예:" +concepts.platforms.description: "화면 표시는 애플리케이션이나 UI 컨트롤이 관리합니다. 이 선택에 따라 프레임의 출력 텍스처를 얻고 명령을 기록·제출하며 결과를 표시할 주체가 정해집니다. 이 출력 텍스처를 drawable이라고 합니다." +concepts.platforms.frame.context: "패스 안에서 파이프라인 바인딩과 그리기 명령을 기록하고, 핸들러가 반환하기 전에 패스를 끝냅니다. 명령 제출과 결과 표시는 컨트롤이 담당합니다. 핸들러는 명령 버퍼를 직접 제출하거나 제공받은 두 객체를 해제해서는 안 됩니다. 출력 텍스처의 레이아웃을 바꿨다면 반환 전에 {colorAttachment}로 복원해 컨트롤이 마지막 전환을 수행할 수 있도록 합니다." +concepts.platforms.frame.description: "컨트롤은 {iZenithView}를 구현합니다. 애플리케이션은 {graphicsContext}를 지정하고 {updateRequested}에서 장면을 갱신하며, {renderRequested}에서 전달받은 {renderEventArgs}로 명령을 기록합니다." +concepts.platforms.frame.details: "매 프레임 컨트롤은 출력 텍스처와 명령 버퍼를 가져오고, 텍스처를 {colorAttachment}로 전환한 뒤 업데이트와 렌더링 핸들러를 호출합니다. 이어서 기록된 작업을 제출하고 프레임워크의 표시 방식으로 이미지를 화면에 표시합니다." +concepts.platforms.frame.guidance: "파일에 {usingZenithNET} 구문을 추가합니다. {view}라는 {iZenithView} 인스턴스가 초기화되어 있고 그래픽스 컨텍스트가 할당되어 있다면, 다음 핸들러를 등록해 출력 텍스처를 지울 수 있습니다." +concepts.platforms.frame.notes: "초기 전환은 {undefined}를 사용하므로 이전 이미지의 내용은 버릴 수 있습니다. 매 프레임 이미지 전체를 그리거나 지웁니다. 누적 결과나 캐시한 렌더링 결과는 애플리케이션이 소유한 텍스처에 보관한 뒤 컨트롤의 출력 텍스처에 그립니다." +concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat}은 이 통합들이 사용하는 기본 색상 형식을 제공합니다." +concepts.platforms.frame.title: "UI 컨트롤에서 렌더링" +concepts.platforms.integration.context: "WinForms, WPF, Windows용 WinUI 통합은 Windows에서 실행됩니다. MAUI는 대상 플랫폼의 워크로드를 설치하고, {extensionsCs}에서처럼 {useZenithView}로 컨트롤 핸들러를 등록합니다." +concepts.platforms.integration.description: "이벤트 인터페이스는 공통이지만 표시 방식은 프레임워크마다 다릅니다." +concepts.platforms.integration.details: "각 구현은 GPU 이미지를 UI에 전달하는 방식이 다릅니다. 비트맵 리드백은 표시 전에 픽셀을 CPU 메모리로 복사합니다. 공유 텍스처 상호 운용은 이 CPU 복사를 피하지만 GPU 복사와 동기화는 여전히 필요할 수 있습니다. 통합을 선택할 때는 공통 {renderRequested} 이벤트뿐 아니라 이 표시 경로도 고려합니다." +concepts.platforms.integration.guidance: "NuGet으로 사용하는 UI 프레임워크의 통합 패키지를 추가합니다. Avalonia에는 {avaloniaPackage}를 사용합니다." concepts.platforms.integration.table.avalonia.integration: Avalonia concepts.platforms.integration.table.avalonia.presentation: 텍스처에 렌더링하고 픽셀을 {writeableBitmap}으로 다운로드합니다. {zenithViewCs} 및 {surfaceCs}를 참조하세요. concepts.platforms.integration.table.headings.integration: 통합 -concepts.platforms.integration.table.headings.presentation: 이미지가 UI에 도달하는 방식 +concepts.platforms.integration.table.headings.presentation: "표시 방식" concepts.platforms.integration.table.maui.integration: .NET MAUI -concepts.platforms.integration.table.maui.presentation: Android, iOS 및 Mac Catalyst에서는 네이티브 서피스를 사용하고 Windows에서는 공유 텍스처 구성을 사용합니다. {link}를 참조하세요. +concepts.platforms.integration.table.maui.presentation: "Android, iOS 및 Mac Catalyst에서는 네이티브 서피스를 사용하고 Windows에서는 공유 텍스처를 이용한 합성 방식을 사용합니다. {link}을 참조하세요." concepts.platforms.integration.table.maui.presentation.link: 플랫폼 구현 concepts.platforms.integration.table.uno.integration: Uno 경로 concepts.platforms.integration.table.uno.presentation: 픽셀을 {writeableBitmap}으로 다운로드합니다. {zenithViewUnoCs}를 참조하세요. concepts.platforms.integration.table.winForms.integration: WinForms concepts.platforms.integration.table.winForms.presentation: 컨트롤의 {hWND}에 대한 Zenith.NET 스왑 체인을 생성합니다. {zenithViewCs}를 참조하세요. concepts.platforms.integration.table.winUI.integration: Windows의 WinUI -concepts.platforms.integration.table.winUI.presentation: 가져온 공유 Direct3D 11 텍스처에 렌더링한 다음 {swapChainPanel}에 연결된 구성 스왑 체인에 복사합니다. {zenithViewWinUICs}를 참조하세요. +concepts.platforms.integration.table.winUI.presentation: "가져온 공유 Direct3D 11 텍스처에 렌더링한 다음 {swapChainPanel}에 연결된 합성용 스왑 체인에 복사합니다. {zenithViewWinUICs}를 참조하세요." concepts.platforms.integration.table.wpf.integration: WPF concepts.platforms.integration.table.wpf.presentation: 공유 Direct3D 11 텍스처를 가져온 다음 Direct3D 상호 운용성을 통해 {d3DImage}로 표시되는 서피스에 복사합니다. {surfaceCs}를 참조하세요. -concepts.platforms.integration.title: 프레임워크뿐만 아니라 프레젠테이션 경로도 선택 -concepts.platforms.lifecycle.context: UI 뷰의 경우 일치하는 렌더링 리소스를 생성할 때 이벤트 출력 텍스처의 {descWidth}, {descHeight}, {descFormat} 및 {descSampleCount}를 사용하세요. 컨트롤이 해당 출력 텍스처의 해상도를 결정합니다. 논리적 치수나 디스플레이 배율이 항상 텍스처 치수와 같다고 가정하지 마세요. -concepts.platforms.lifecycle.description: 네이티브 스왑 체인의 경우 프레임버퍼 치수를 픽셀 단위로 전달하세요. 디스플레이 배율이 활성화된 경우 논리 단위로 표현된 윈도우 크기와 다를 수 있습니다. 크기가 0인 프레임버퍼는 건너뛰고, 픽셀 크기가 변경되면 스왑 체인의 크기를 조정하며, 각 프레임마다 {swapChainDrawable}을 가져옵니다. 출력 텍스처는 스왑 체인이 소유하며 프레젠테이션 또는 크기 조정 후에 변경될 수 있습니다. -concepts.platforms.lifecycle.details: "{swapChainResize}는 기존 서피스의 크기를 변경합니다. {swapChainRefresh}는 네이티브 핸들을 포함하여 서피스 설명을 대체합니다. 두 작업 중 하나를 수행하기 전에 영향을 받는 리소스의 미해결 사용을 완료하세요. 네이티브 프레젠테이션 대상을 해제하기 전에 스왑 체인을 해제하세요." -concepts.platforms.lifecycle.guidance: 윈도우 크기를 따르는 애플리케이션 소유의 깊이 또는 오프스크린 텍스처를 다시 생성하고 해당 핸들이 포함된 상수를 업데이트하세요. 파이프라인은 어태치먼트 형식과 샘플 수가 호환되는 한 크기 변경 후에도 계속 사용할 수 있습니다. {link}는 깊이 텍스처를 교체하면서 파이프라인을 유지합니다. +concepts.platforms.integration.title: "프레임워크와 표시 방식" +concepts.platforms.lifecycle.context: "호환되는 어태치먼트를 만들 때는 렌더 이벤트가 제공한 출력 텍스처의 {descWidth}, {descHeight}, {descFormat}, {descSampleCount}를 사용합니다. 이 텍스처의 크기가 렌더 타깃의 실제 크기입니다. 컨트롤의 레이아웃 크기나 화면 배율로 추정하지 않습니다." +concepts.platforms.lifecycle.description: "스왑 체인은 프레임버퍼의 픽셀 너비와 높이를 사용합니다. 화면 배율이 적용되면 이 크기는 창의 논리적 크기와 다를 수 있습니다. 너비나 높이가 0인 동안에는 렌더링과 스왑 체인 크기 변경을 미룹니다. {swapChainDrawable}은 매 프레임 가져옵니다. 이 텍스처는 스왑 체인이 소유하며 화면 표시나 크기 변경 후 교체될 수 있습니다." +concepts.platforms.lifecycle.details: "프레임버퍼 크기가 바뀌면 GPU가 이전 이미지의 사용을 마칠 때까지 기다린 뒤 {swapChainResize}를 호출합니다. 네이티브 표시 대상을 교체할 때도 사용이 끝난 뒤 새 서피스 설명과 핸들을 {swapChainRefresh}에 전달합니다. 종료할 때는 네이티브 표시 대상을 파괴하기 전에 스왑 체인을 해제합니다." +concepts.platforms.lifecycle.guidance: "애플리케이션이 소유한 깊이 텍스처나 오프스크린 텍스처가 창 크기를 따른다면, 크기가 바뀔 때 다시 만들고 해당 핸들을 담은 상수도 갱신합니다. 어태치먼트 형식과 샘플 수가 계속 일치하면 파이프라인은 재사용할 수 있습니다. {link}는 크기가 바뀌는 텍스처와 재사용하는 파이프라인을 분리하는 예를 보여 줍니다." concepts.platforms.lifecycle.guidance.link: 회전하는 큐브 렌더러 -concepts.platforms.lifecycle.title: 출력 텍스처의 크기와 수명을 호스트와 함께 유지 -concepts.platforms.ownership.description: 애플리케이션은 할당한 컨텍스트와 렌더링을 위해 생성한 리소스를 소유합니다. 컨트롤은 자체 프레젠테이션 리소스를 소유합니다. 뷰의 {graphicsContext} 속성을 변경하면 스케줄러가 컨트롤의 리소스를 다시 생성하지만, 새 컨텍스트를 위해 애플리케이션의 파이프라인, 버퍼 또는 텍스처를 다시 생성하지는 않습니다. -concepts.platforms.ownership.details: "리소스 교체를 뷰의 프레임 수명 주기와 조정하세요. 애플리케이션 리소스 또는 할당된 컨텍스트를 해제하기 전에 뷰의 프레임 활동을 중지하고 미해결 GPU 사용을 완료하세요. 뷰를 제거한다고 해서 컨텍스트 소유권이 컨트롤로 이전되는 것은 아닙니다." -concepts.platforms.ownership.guidance: 공유 {frameSchedulerCs}는 뷰의 UI 디스패처를 통해 프레임 작업을 디스패치합니다. 프레임 핸들러가 프레임 업데이트 및 기록에 집중하도록 유지하세요. 장시간의 CPU 작업은 UI를 지연시킵니다. -concepts.platforms.ownership.title: 애플리케이션 리소스를 컨트롤 소유권 외부에 유지 -concepts.platforms.surface.context: 윈도우 라이브러리나 UI 프레임워크가 운영 체제를 지원한다고 해서 선택한 GPU 백엔드를 해당 환경에서 사용할 수 있다는 보장은 없습니다. 장치 기능, 드라이버 및 네이티브 서피스 지원이 여전히 일치해야 합니다. 해당 워크로드를 생성하기 전에 {contextCapabilities}를 통해 선택적 레이 트레이싱 및 메시 셰이딩을 확인하세요. -concepts.platforms.surface.description: "{link}는 Silk.NET을 사용하여 윈도우를 생성하고 이벤트를 처리합니다. Zenith.NET은 {surface} 설명과 {swapChain}을 통해 해당 윈도우에 연결됩니다. 서피스에는 네이티브 핸들과 치수가 포함됩니다. 설명을 구성한다고 해서 운영 체제 윈도우가 생성되거나 소유되는 것은 아닙니다." -concepts.platforms.surface.description.link: 삼각형 튜토리얼 -concepts.platforms.surface.details: "핸들은 선택한 백엔드와 일치해야 합니다:" -concepts.platforms.surface.guidance: 튜토리얼의 {appCs}는 Windows, macOS 및 X11 선택 항목을 보여줍니다. Linux 호스트는 Xlib 핸들을 제공하므로 Wayland 세션에서 사용하려면 XWayland가 필요합니다. 네이티브 Wayland 애플리케이션은 {surfaceWayland}를 통해 다른 핸들을 제공합니다. +concepts.platforms.lifecycle.title: "스왑 체인의 크기와 수명" +concepts.platforms.ownership.description: "애플리케이션은 할당한 컨텍스트와 자체 렌더링 리소스를 소유하고, 컨트롤은 화면 표시 리소스를 소유합니다. 뷰의 {graphicsContext}가 바뀌면 스케줄러는 새 컨텍스트에 맞게 컨트롤 리소스를 다시 만듭니다. 애플리케이션의 파이프라인, 버퍼, 텍스처도 새 컨텍스트에서 다시 만들어야 합니다." +concepts.platforms.ownership.details: "렌더링 리소스를 교체하기 전에 뷰의 프레임 처리를 중단하고 해당 리소스를 사용하는 GPU 작업이 끝날 때까지 기다립니다. 그런 다음 이전 리소스나 컨텍스트를 해제합니다. 뷰를 제거할 때도 할당한 컨텍스트를 해제할 책임은 애플리케이션에 있습니다." +concepts.platforms.ownership.guidance: "공통 {frameSchedulerCs}는 뷰의 UI 디스패처를 통해 프레임 핸들러를 실행합니다. 핸들러에서는 장면 데이터 갱신과 명령 기록에 집중합니다. 여기서 CPU 작업이 오래 걸리면 인터페이스의 응답도 지연됩니다." +concepts.platforms.ownership.title: "애플리케이션과 컨트롤의 소유권" +concepts.platforms.surface.description: "{link}은 Silk.NET으로 창을 만들고 이벤트를 처리합니다. Zenith.NET은 네이티브 창 핸들과 크기를 {surface} 설명으로 전달받아 {swapChain}을 만듭니다. 운영체제 창의 관리는 애플리케이션이 계속 맡습니다." +concepts.platforms.surface.description.link: "삼각형 튜토리얼" +concepts.platforms.surface.details: "서피스 핸들은 선택한 백엔드와 일치해야 합니다." +concepts.platforms.surface.guidance: "{appCs}의 예제 호스트는 Windows, macOS, X11을 지원합니다. Linux 창에서 Xlib 핸들을 제공하므로 Wayland 세션에서 실행하려면 XWayland가 필요합니다. 네이티브 Wayland 애플리케이션은 {surfaceWayland}로 디스플레이와 서피스 핸들을 전달합니다." concepts.platforms.surface.table.android.backend: Android의 Vulkan. concepts.platforms.surface.table.apple.backend: Apple 플랫폼의 Metal. -concepts.platforms.surface.table.headings.backend: 백엔드 경로 +concepts.platforms.surface.table.headings.backend: "백엔드와 플랫폼" concepts.platforms.surface.table.headings.factory: 서피스 팩토리 concepts.platforms.surface.table.headings.handles: 호스트에서 제공하는 핸들 concepts.platforms.surface.table.wayland.backend: 네이티브 Wayland 호스트를 사용하는 Vulkan. concepts.platforms.surface.table.wayland.handles: Wayland 디스플레이 및 서피스 concepts.platforms.surface.table.win32.backend: Windows의 DirectX 12 또는 Vulkan. concepts.platforms.surface.table.xlib.backend: X11 또는 XWayland를 사용하는 Linux의 Vulkan. -concepts.platforms.surface.table.xlib.handles: X11 디스플레이 및 윈도우 -concepts.platforms.surface.title: 애플리케이션이 프레젠테이션을 소유할 때 네이티브 서피스 제공 +concepts.platforms.surface.table.xlib.handles: "X11 디스플레이 및 창" +concepts.platforms.surface.title: "네이티브 표시 서피스" concepts.platforms.title: 플랫폼 통합 -concepts.resources.allocation.context: "자체 메모리 할당기가 필요한 경우가 아니라면 컨텍스트에서 생성한 리소스부터 사용하세요. 힙을 사용할 때는 해당 리소스를 사용하는 모든 GPU 작업이 완료된 후 배치된 리소스를 먼저 해제하고, 마지막으로 힙 자체를 해제하세요." -concepts.resources.allocation.description: "{heap}은 명시적인 바이트 오프셋에 리소스를 배치할 메모리를 제공합니다. 애플리케이션이 오프셋을 선택하고 사용 중인 영역을 추적합니다." -concepts.resources.allocation.details: "리소스를 배치하기 전에 정확한 버퍼 또는 텍스처 설명을 사용해 {contextGetSizeAndAlignment}를 호출하세요. 반환된 정렬 값의 배수인 오프셋을 선택하고, 반환된 크기만큼 공간을 확보하며, 리소스가 힙의 전체 바이트 범위 안에 있도록 하세요. 사용 중인 할당 영역은 겹치면 안 됩니다. 텍스처 저장 공간에는 백엔드별 패딩과 정렬이 포함될 수 있으므로 픽셀 수에 픽셀당 바이트 수를 곱한 값으로 할당 크기를 계산할 수는 없습니다." -concepts.resources.allocation.guidance: "배치된 버퍼의 상주 특성은 힙의 상주 특성과 일치시켜야 합니다. 여기서 설명하는 일반 GPU 텍스처에는 GPU 전용 힙을 사용하세요. 크기와 정렬은 배치 요구 사항이며, 모든 백엔드에서 임의의 리소스를 임의의 힙에 배치할 수 있다는 보장은 아닙니다." -concepts.resources.allocation.title: 할당 제어가 필요한 경우 힙에 리소스 배치 +concepts.resources.allocation.context: "힙에 배치한 리소스는 수명 내내 그 힙의 저장 공간에 의존합니다. GPU의 마지막 사용이 끝난 뒤 리소스를 먼저 해제하고 힙을 해제합니다." +concepts.resources.allocation.description: "애플리케이션이 메모리 할당을 직접 관리해야 한다면 {heap}을 사용합니다. 힙은 리소스를 지정한 바이트 오프셋에 배치할 저장 공간을 제공합니다. 오프셋을 선택하고 어느 영역이 사용 중인지 추적하는 일은 애플리케이션이 맡습니다." +concepts.resources.allocation.details: "리소스를 만들 때 사용할 버퍼 또는 텍스처 설명으로 {contextGetSizeAndAlignment}를 호출합니다. 반환된 정렬 값의 배수인 오프셋에 반환된 크기만큼 공간을 확보하되, 힙의 범위를 벗어나거나 아직 사용 중인 다른 할당과 겹치지 않도록 합니다. 텍스처에는 백엔드별 패딩이 포함될 수 있으므로 픽셀 수와 픽셀당 바이트 수만으로 할당 크기를 계산할 수 없습니다." +concepts.resources.allocation.guidance: "힙에 배치하는 버퍼의 상주 특성은 힙과 같아야 합니다. 텍스처를 저장할 때는 GPU 전용 힙을 사용합니다." +concepts.resources.allocation.title: "힙에 리소스 배치" concepts.resources.bufferUsages.table.constant.role: 상수 버퍼 바인딩을 통해 읽는 셰이더 매개 변수. concepts.resources.bufferUsages.table.headings.role: "역할" concepts.resources.bufferUsages.table.headings.usage: 용도 -concepts.resources.bufferUsages.table.index.role: 인덱스 드로잉에 사용되는 인덱스. -concepts.resources.bufferUsages.table.indirect.role: "간접 드로잉 또는 디스패치 명령이 읽는 인수." +concepts.resources.bufferUsages.table.index.role: "인덱스 그리기에 사용되는 인덱스." +concepts.resources.bufferUsages.table.indirect.role: "간접 그리기 또는 디스패치 명령이 읽는 인수." concepts.resources.bufferUsages.table.none.role: "버퍼 용도 플래그를 선언하지 않음." concepts.resources.bufferUsages.table.storageReadOnly.role: "읽기 전용 셰이더 바인딩으로 접근하는 버퍼 데이터." concepts.resources.bufferUsages.table.storageReadWrite.role: "읽기 및 쓰기 셰이더 바인딩으로 접근하는 버퍼 데이터." concepts.resources.bufferUsages.table.transferDst.role: "GPU 복사의 대상 저장 공간." concepts.resources.bufferUsages.table.transferSrc.role: "GPU 복사의 원본 데이터." -concepts.resources.bufferUsages.table.vertex.role: 드로잉을 위해 가져오는 정점 속성. +concepts.resources.bufferUsages.table.vertex.role: "그리기에 사용하는 정점 속성." concepts.resources.bufferUsages.title: 버퍼 용도 -concepts.resources.description: "리소스를 사용할 작업에 맞춰 리소스 설명을 선택하세요. 렌더링 대상으로 쓰고, 셰이더에서 샘플링하고, CPU로 읽어 올 텍스처라면 세 가지 용도를 모두 선언하고 작업 사이의 동기화도 처리해야 합니다. 메모리 배치와 리소스 수명은 별도로 결정할 사항입니다." -concepts.resources.memory.context: CPU 접근 가능한 버퍼의 경우 {map}은 CPU에 주소를 제공합니다. GPU가 동일한 바이트에 대한 접근을 중지할 때까지 기다리지 않습니다. {unmap} 역시 작업을 제출하거나 완료를 기다리지 않습니다. CPU 쓰기 가능 데이터를 덮어쓰기 전에 이전 내용이 여전히 필요한 GPU 읽기를 완료하세요. -concepts.resources.memory.description: "{bufferDesc}에는 {residency} 필드가 있습니다. CPU와 GPU가 데이터에 접근하는 방식에 따라 선택하세요:" -concepts.resources.memory.details: 상주 특성은 할당에 대한 의도된 CPU 접근을 설명합니다. 이는 모든 장치가 물리적으로 분리된 CPU 및 GPU 메모리를 갖는다는 것을 의미하지는 않습니다. 삼각형 튜토리얼은 작은 정점 버퍼를 직접 초기화하기 위해 {cpuWriteOnly}를 사용합니다. 대규모 정적 메시는 일회성 업로드를 포함하는 GPU 전용 스토리지의 이점을 얻을 수 있습니다. -concepts.resources.memory.guidance: "{textureDesc}에는 상주 필드가 없습니다. 일반적인 컨텍스트 생성 텍스처는 GPU 스토리지를 사용합니다. 해당 공개 API는 직접 매핑 메서드를 노출하지 않고 CPU 데이터 전송을 위한 업로드 및 다운로드 작업을 제공합니다. 명시적 힙은 아래에 설명된 배치 제어를 제공합니다." -concepts.resources.memory.table.cpuReadOnly.cPUAccess: "GPU 복사가 끝난 후 매핑된 메모리를 읽음." -concepts.resources.memory.table.cpuReadOnly.typicalRole: "GPU가 생성한 리드백 데이터" -concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "이전 GPU 읽기가 끝난 후 매핑된 메모리에 씀." +concepts.resources.description: "리소스 설명은 애플리케이션이 저장 공간을 어떤 용도로 사용할지 정합니다. 예를 들어 렌더 타깃으로 쓰고, 셰이더에서 샘플링하고, CPU로 다시 복사하는 텍스처에는 세 작업의 용도 플래그가 모두 필요합니다. 메모리 배치는 CPU 접근 방식을 결정하고, 동기화와 수명 관리는 데이터에 접근하거나 저장 공간을 해제할 수 있는 시점을 결정합니다." +concepts.resources.memory.context: "CPU에서 접근할 수 있는 버퍼의 경우 {map}은 데이터를 읽거나 쓸 주소를 제공합니다. 매핑과 {unmap}은 GPU 작업을 기다리지 않습니다. 따라서 GPU가 쓴 결과를 읽으려면 쓰기가 끝날 때까지 기다려야 하고, 같은 바이트를 수정하려면 진행 중인 GPU 접근이 끝날 때까지 기다려야 합니다." +concepts.resources.memory.description: "{bufferDesc}의 {residency} 필드는 할당 영역에 대한 CPU 접근 방식을 지정합니다." +concepts.resources.memory.details: "상주 특성은 CPU와 GPU가 물리 메모리를 공유하는 시스템에서도 CPU 접근 요구 사항을 나타냅니다. 삼각형은 작은 정점 버퍼를 직접 초기화하기 위해 {cpuWriteOnly}를 사용합니다. 더 큰 정적 지오메트리에는 GPU 전용 저장 공간을 만들고 데이터를 업로드하는 방식이 적합할 수 있습니다." +concepts.resources.memory.guidance: "컨텍스트에서 직접 만든 텍스처는 GPU 저장 공간을 사용합니다. 따라서 {textureDesc}에는 상주 특성 필드가 없으며, 애플리케이션은 업로드와 다운로드로 텍스처 데이터를 CPU 메모리와 주고받습니다." +concepts.resources.memory.table.cpuReadOnly.cPUAccess: "읽기 전용" +concepts.resources.memory.table.cpuReadOnly.typicalRole: "GPU가 생성하고 CPU가 읽는 데이터" +concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "쓰기 전용" concepts.resources.memory.table.cpuWriteOnly.typicalRole: "CPU가 제공하거나 갱신하는 데이터" -concepts.resources.memory.table.gpuOnly.cPUAccess: "업로드 또는 리드백 버퍼를 통해 바이트를 전송함." +concepts.resources.memory.table.gpuOnly.cPUAccess: "없음" concepts.resources.memory.table.gpuOnly.typicalRole: "정적 지오메트리와 GPU 작업 데이터" -concepts.resources.memory.table.headings.cPUAccess: CPU 접근 -concepts.resources.memory.table.headings.residency: 상주 특성 +concepts.resources.memory.table.headings.cPUAccess: "의도한 CPU 접근" +concepts.resources.memory.table.headings.residency: "상주 방식" concepts.resources.memory.table.headings.typicalRole: 일반적인 역할 -concepts.resources.memory.title: "필요한 CPU 접근 방식에 맞춰 메모리 선택" -concepts.resources.textureUsages.description: "전송 용도 플래그는 GPU 복사의 방향을 나타냅니다. CPU 접근은 이와 별개인 메모리 배치 선택 사항이며 아래에서 설명합니다." -concepts.resources.textureUsages.details: "용도 플래그를 조합하면 여러 역할을 선언할 수 있지만, 작업을 실행하거나 접근 순서를 지정하지는 않습니다. 텍스처에는 여전히 적절한 {link}가 필요하며, 선택한 장치에서 해당 포맷이 요청한 용도를 지원해야 합니다." +concepts.resources.memory.title: "CPU 접근과 메모리 배치" +concepts.resources.textureUsages.description: "전송 플래그는 리소스가 GPU 복사의 원본인지 대상인지를 나타냅니다. CPU가 저장 공간에 직접 접근할 수 있는지는 별도로 메모리 배치를 선택할 때 정합니다." +concepts.resources.textureUsages.details: "용도 플래그는 텍스처가 수행할 수 있는 역할을 선언합니다. 역할을 바꿔 사용할 때는 해당 {link} 요구 사항을 따라야 하며, 선택한 장치가 그 텍스처 형식의 용도를 지원해야 합니다." concepts.resources.textureUsages.details.link: "레이아웃과 동기화" concepts.resources.textureUsages.table.colorAttachment.role: "렌더 패스의 색상 어태치먼트." concepts.resources.textureUsages.table.depthStencilAttachment.role: "렌더 패스의 깊이/스텐실 어태치먼트." @@ -142,225 +141,220 @@ concepts.resources.textureUsages.table.transferDst.role: "GPU 복사의 대상 concepts.resources.textureUsages.table.transferSrc.role: "GPU 복사의 원본 이미지 데이터." concepts.resources.textureUsages.title: 텍스처 용도 concepts.resources.title: 리소스 관리 -concepts.resources.transfers.context: 다운로드는 내부 리드백 스토리지에 GPU 복사를 기록합니다. 라이브러리는 재사용을 위해 완료된 명령 버퍼를 재설정할 때 해당 바이트를 제공된 CPU 대상으로 복사합니다. 제출 값의 {wait}가 반환될 때까지 대상을 할당된 상태로 유지하고 관리 메모리를 고정된 상태로 유지하세요. -concepts.resources.transfers.description: "업로드는 CPU 데이터를 GPU 리소스로 복사하고, 다운로드는 리소스 데이터를 CPU 메모리로 복사합니다. 리소스 자체가 제공하는 메서드는 해당 전송을 완료한 뒤 반환합니다." -concepts.resources.transfers.details: "이러한 대기는 해당 메서드가 제출한 전송만 대상으로 합니다. 다른 큐에서 이미 리소스를 읽거나 쓰고 있던 작업과의 종속성은 찾아내지 않습니다. 리소스의 전송 메서드를 호출하기 전에 종속성을 설정하세요. 매핑된 메모리를 통한 직접 복사도 호출자가 관련 GPU 작업의 완료를 보장해야 합니다." -concepts.resources.transfers.guidance: "복사를 다른 작업과 함께 기록해야 하는 경우 {commandBufferUpload} 또는 {commandBufferDownload}를 사용하세요. 포인터 수명은 서로 다릅니다:" -concepts.resources.transfers.item: "업로드는 호출 중에 CPU 원본 데이터를 내부 업로드 버퍼인 스테이징 메모리로 복사합니다. 원본 포인터는 해당 호출이 진행되는 동안만 유효하면 됩니다." -concepts.resources.transfers.notes: "텍스처의 행 스트라이드는 CPU 데이터의 연속된 두 행 사이의 바이트 거리이며, 슬라이스 스트라이드는 연속된 깊이 슬라이스 사이의 바이트 거리입니다. 이 값은 텍스처 내부의 GPU 메모리 레이아웃이 아닙니다. GPU 완료와 리드백의 차이는 {link}를 참고하세요." +concepts.resources.transfers.context: "다운로드는 먼저 GPU 데이터를 내부 리드백 공간으로 복사합니다. 라이브러리는 완료된 명령 버퍼를 회수할 때 이 데이터를 지정한 CPU 대상으로 복사합니다. 다운로드를 제출해 받은 값에서 {wait}를 호출하면 두 단계가 모두 완료됩니다. 이 호출이 반환할 때까지 대상 메모리를 할당된 상태로 유지하고, 관리형 메모리라면 고정 상태도 유지합니다." +concepts.resources.transfers.description: "업로드는 CPU 데이터를 GPU 리소스로 복사하고, 다운로드는 리소스 데이터를 CPU 메모리로 복사합니다. 버퍼와 텍스처의 메서드는 이 전송을 완료한 뒤 반환합니다." +concepts.resources.transfers.details: "이 메서드들을 호출하기 전에 다른 큐의 충돌하는 접근을 정리해야 합니다. 메서드 내부의 대기는 자체 전송만 대상으로 하며 다른 큐와의 의존성을 설정하지 않습니다. 매핑된 메모리로 직접 복사하는 경로에서는 충돌하는 GPU 접근을 기다리는 일도 전적으로 호출자가 담당합니다." +concepts.resources.transfers.guidance: "전송을 다른 GPU 작업과 함께 제출하려면 {commandBufferUpload} 또는 {commandBufferDownload}로 기록합니다. 업로드 원본과 다운로드 대상은 메모리를 유효하게 유지해야 하는 기간이 서로 다릅니다." +concepts.resources.transfers.item: "업로드를 호출하면 라이브러리가 원본 데이터를 임시 전송 공간인 스테이징 메모리에 복사합니다. 이후 GPU는 이 공간에서 읽으므로 애플리케이션의 원본 포인터는 호출이 반환할 때까지만 필요합니다." +concepts.resources.transfers.notes: "텍스처 전송에서 행 스트라이드는 CPU 데이터의 인접한 행 사이의 바이트 거리이고, 슬라이스 스트라이드는 인접한 깊이 슬라이스 사이의 거리입니다. 이 값으로 CPU에 배치된 데이터와 GPU의 텍스처 저장 공간 사이를 복사할 수 있습니다. GPU 복사 완료와 다운로드 대상에 데이터가 전달되는 시점이 다른 이유는 {link} 문서에서 설명합니다." concepts.resources.transfers.notes.link: 동기화 -concepts.resources.transfers.table.bufferDownload.transfer: "{cpuReadOnly}의 경우 직접 CPU 복사, 그렇지 않으면 전송 큐 다운로드를 제출하고 대기." -concepts.resources.transfers.table.bufferUpload.transfer: "{cpuWriteOnly}의 경우 직접 CPU 복사, 그렇지 않으면 전송 큐 업로드를 제출하고 대기." -concepts.resources.transfers.table.headings.method: 방법 -concepts.resources.transfers.table.headings.transfer: "데이터 전송 방식" +concepts.resources.transfers.table.bufferDownload.transfer: "{cpuReadOnly}이면 매핑된 메모리에서 직접 복사합니다. 그 외에는 전송 큐에 다운로드를 제출하고 완료를 기다립니다." +concepts.resources.transfers.table.bufferUpload.transfer: "{cpuWriteOnly}이면 매핑된 메모리에 직접 복사합니다. 그 외에는 전송 큐에 업로드를 제출하고 완료를 기다립니다." +concepts.resources.transfers.table.headings.method: "메서드" +concepts.resources.transfers.table.headings.transfer: "전송 동작" concepts.resources.transfers.table.textureTransfers.method: "{textureUpload} / {textureDownload}" -concepts.resources.transfers.table.textureTransfers.transfer: "그래픽스 큐를 사용하여 선택한 하위 리소스를 복사용 레이아웃으로 전환하고, 복사 후 요청한 최종 레이아웃으로 전환한 다음 전송 완료를 기다림." -concepts.resources.transfers.title: "즉시 완료하는 전송과 명령에 기록하는 전송 중 선택" -concepts.resources.usages.description: "{bufferUsages} 및 {textureUsages}는 리소스의 의도된 역할을 선언하는 플래그 열거형입니다. 각각 {bufferDescUsages} 및 {textureDescUsages}에 할당됩니다. 플래그 열거형을 사용하면 리소스에 둘 이상의 역할이 있을 때 {value}를 사용하여 여러 멤버를 결합할 수 있습니다." -concepts.resources.usages.title: 리소스를 생성하기 전에 필요한 용도 선언 -concepts.resources.views.description: "{bufferView}는 버퍼 영역과 그 해석을 설명합니다. {textureView}는 호환 가능한 텍스처 형식, 포맷 및 하위 리소스 범위를 선택합니다. 뷰는 기본 스토리지를 공유하며 데이터를 복사하거나 리소스 생성 시 누락된 용도를 추가하지 않습니다. 해당 범위는 셰이더 경계 검사의 이식 가능한 보장이 아닙니다." -concepts.resources.views.details: "기본 뷰에는 리소스 자체의 핸들을 사용하고, 다른 영역이나 호환되는 다른 해석이 필요하면 뷰를 생성하세요. GPU 작업이 뷰와 기본 리소스를 사용할 수 있는 동안 두 객체에 대한 C# 참조를 유지하세요. 리소스 핸들만으로는 어느 객체의 수명도 유지되지 않습니다. 마지막 GPU 사용이 완료된 뒤에만 해제하세요. 둘 중 하나를 교체하면 이전 {link}을 포함하는 상수도 갱신하세요." +concepts.resources.transfers.table.textureTransfers.transfer: "복사와 텍스처 전환을 그래픽스 큐에 제출한 뒤 완료를 기다립니다. 선택한 하위 리소스는 요청한 최종 레이아웃으로 남습니다." +concepts.resources.transfers.title: "즉시 전송과 기록된 전송" +concepts.resources.usages.description: "{bufferUsages}와 {textureUsages}는 리소스 용도를 선언하는 플래그 열거형입니다. 각각 {bufferDescUsages}와 {textureDescUsages}에 지정합니다. 여러 용도가 필요하면 {value}로 해당 멤버를 결합합니다." +concepts.resources.usages.title: "리소스 용도" +concepts.resources.views.description: "{bufferView}는 버퍼의 영역과 그 데이터를 해석하는 방식을 기술합니다. {textureView}는 하위 리소스 범위를 선택하고, 호환되는 텍스처 유형과 포맷을 지정합니다. 둘 다 기존 저장 공간을 참조하며, 생성 시 선언한 용도를 따릅니다. 뷰 범위는 접근 대상을 기술하지만 모든 백엔드에서 동일한 셰이더 범위 검사를 보장하지는 않습니다." +concepts.resources.views.details: "리소스 자체의 핸들은 기본 뷰를 제공합니다. 다른 영역이나 호환되는 다른 해석 방식이 필요하면 별도 뷰를 만듭니다. GPU가 사용을 마칠 때까지 뷰와 원본 리소스를 모두 유지해야 합니다. 핸들만으로는 어느 객체의 수명도 유지되지 않습니다. 둘 중 하나를 교체하면 이전 {link}이 들어 있는 상수도 갱신합니다." concepts.resources.views.details.link: "리소스 핸들" -concepts.resources.views.guidance: "{link}는 크기 조정 시 교체되는 깊이 텍스처를 보여줍니다. {detail}는 쓰기 가능한 출력과 분리되어 유지되는 입력 텍스처를 보여줍니다. 둘 다 리소스 수명이 실제로 이를 사용하는 작업을 따르도록 합니다." -concepts.resources.views.guidance.detail: 컴퓨팅 샘플 -concepts.resources.views.guidance.link: 회전하는 큐브 렌더러 -concepts.resources.views.title: "뷰와 기본 리소스를 함께 사용 가능한 상태로 유지" -concepts.shaders.binding.context: "컴퓨팅 샘플에서 {input}은 {inputTextureSampledHandle}로 채워지고 {output}은 {outputTextureStorageHandle}로 채워집니다. Slang의 형식화된 {descriptorHandle}은 각 리소스에 접근하는 방법을 셰이더에 알려줍니다:" -concepts.shaders.binding.description: "{setConstantBuffer}는 현재 파이프라인의 상수 데이터에 사용할 버퍼와 바이트 오프셋을 바인딩합니다. 기존 GPU 가시적 저장 공간을 바인딩할 뿐 C# 값을 업로드하지는 않습니다. 버퍼를 먼저 채우고, 그 바이트를 덮어쓰기 전에 이전 GPU 읽기 작업이 완료되었는지 확인하세요." -concepts.shaders.binding.details: "상수 버퍼 앞에 파이프라인을 설정하세요. 리소스가 이미 생성되고 업로드된 컴퓨팅 워크로드의 경우 기록 시 다음 순서를 사용합니다:" -concepts.shaders.binding.guidance: 이 조각은 기록 중인 {commandBuffer}, {computePipeline}, {bufferUsagesConstant} 용도로 업로드된 {constantBuffer} 및 워크로드의 스레드 그룹 수를 전제로 합니다. 오프셋 0은 버퍼의 시작을 바인딩합니다. 여러 상수 데이터 레코드가 하나의 버퍼를 공유하는 경우 각 레코드의 시작 오프셋은 백엔드의 바인딩 정렬을 충족해야 합니다. 이 요구 사항은 레코드 내부의 필드 레이아웃과 별개입니다. -concepts.shaders.binding.notes: "{resourceHandle}은 두 개의 32비트 필드를 저장하지만 그 해석은 백엔드에 속합니다. 이를 컨텍스트 간에 전송할 수 있는 범용 설명자 인덱스, 주소 또는 값으로 취급하지 마세요. 핸들은 리소스를 생성하거나 누락된 용도를 추가하거나 동기화를 수행하지 않습니다." -concepts.shaders.binding.reference: "리소스 및 핸들을 얻는 데 사용된 모든 뷰에 대한 참조를 유지하고 셰이더의 마지막 사용이 완료된 후에만 해제하세요. 텍스처나 뷰를 교체할 때 이전 핸들이 포함된 상수를 업데이트하세요. {link}에서 해당 수명 관계를 설명합니다." +concepts.resources.views.title: "뷰와 원본 리소스" +concepts.shaders.binding.context: "컴퓨트 예제는 {input}에 {inputTextureSampledHandle}을, {output}에 {outputTextureStorageHandle}을 지정합니다. Slang의 {descriptorHandle} 형식 인수가 각 리소스의 셰이더 접근 방식을 정합니다." +concepts.shaders.binding.description: "{setConstantBuffer}는 현재 파이프라인이 상수를 읽을 버퍼와 시작 바이트 오프셋을 선택합니다. 셰이더가 사용하기 전에 해당 공간에 매개변수를 업로드합니다. 이전 GPU 작업이 같은 바이트를 아직 읽고 있다면 그 작업이 끝난 뒤 데이터를 갱신합니다." +concepts.shaders.binding.details: "명령 버퍼, 컴퓨트 파이프라인, 데이터가 채워진 상수 버퍼, 스레드 그룹 수를 준비한 뒤 다음 순서로 디스패치를 기록합니다. 상수 버퍼 바인딩은 현재 파이프라인에 적용되므로 파이프라인을 먼저 선택합니다." +concepts.shaders.binding.guidance: "여기서 {commandBuffer}는 {computePipeline}을 사용하는 디스패치를 기록합니다. 셰이더 매개변수는 {constantBuffer}에 저장되어 있습니다. 버퍼에는 {bufferUsagesConstant} 용도가 필요하고, 오프셋 0은 버퍼의 시작을 선택합니다. 여러 상수 레코드가 한 버퍼를 공유한다면 각 레코드의 시작 오프셋도 백엔드의 바인딩 정렬을 따라야 합니다. 이는 레코드 내부의 필드 배치와 별개의 조건입니다." +concepts.shaders.binding.notes: "{resourceHandle}은 32비트 필드 두 개를 포함하며 해석은 백엔드에 따라 다릅니다. 이 값은 리소스를 생성한 컨텍스트에서만 유효합니다." +concepts.shaders.binding.reference: "핸들을 얻은 리소스와 뷰는 셰이더의 마지막 접근이 끝날 때까지 유지합니다. 텍스처나 뷰를 교체하면 이전 핸들을 담은 상수를 갱신합니다. 소유권 규칙은 {link}에서 설명합니다." concepts.shaders.binding.reference.link: 리소스 관리 -concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: 셰이더 형식 {t}의 구조화된 요소를 읽습니다. -concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: 셰이더 형식 {t}의 구조화된 요소를 읽거나 씁니다. +concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: "셰이더 형식 {t}의 구조화 요소 읽기" +concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: "셰이더 형식 {t}의 구조화 요소 읽기 및 쓰기" concepts.shaders.binding.table.headings.access: 의도된 접근 concepts.shaders.binding.table.headings.cHandle: "C# 핸들" concepts.shaders.binding.table.headings.slangFieldType: Slang 필드 형식 -concepts.shaders.binding.table.samplerHandle.access: 텍스처 샘플링 상태를 제공합니다. -concepts.shaders.binding.table.textureSampledHandle.access: 텍스처를 읽습니다. -concepts.shaders.binding.table.textureStorageHandle.access: 스토리지 텍스처를 읽거나 씁니다. -concepts.shaders.binding.title: 상수 버퍼 및 해당 버퍼가 설명하는 리소스 바인딩 -concepts.shaders.compilation.description: "{zenithCompiler}는 명명된 Slang 진입점을 컴파일하고 {shaderDesc}를 반환합니다. 결과가 셰이더를 생성할 백엔드(DirectX 12의 경우 DXIL, Metal의 경우 Metal 라이브러리, Vulkan의 경우 SPIR-V)를 대상으로 하도록 컨텍스트의 {graphicsApi}를 사용하세요." -concepts.shaders.compilation.details: "예를 들어 기존 {context}가 있고 삼각형 셰이더가 실행 파일 옆에 복사된 경우:" -concepts.shaders.compilation.guidance: "{vSMain}은 셰이더 파일의 진입점 이름과 정확히 일치해야 합니다. 파이프라인을 생성하는 동안 셰이더 개체를 유효하게 유지한 다음, {link}에 표시된 대로 파이프라인 생성 후에 해제하세요. 매 프레임마다 다시 컴파일하는 대신 이 초기화를 한 번 수행하세요." +concepts.shaders.binding.table.samplerHandle.access: "텍스처 샘플링 상태" +concepts.shaders.binding.table.textureSampledHandle.access: "텍스처 읽기" +concepts.shaders.binding.table.textureStorageHandle.access: "스토리지 텍스처 읽기 및 쓰기" +concepts.shaders.binding.title: "상수 버퍼와 리소스 핸들" +concepts.shaders.compilation.description: "{zenithCompiler}는 지정한 Slang 진입점을 {shaderDesc}로 컴파일합니다. 컨텍스트의 {graphicsApi}에 따라 DirectX 12용 DXIL, Metal 라이브러리, Vulkan용 SPIR-V를 생성합니다." +concepts.shaders.compilation.details: "{context}라는 그래픽스 컨텍스트를 이미 만든 상태에서, 실행 파일 옆에 복사해 둔 삼각형 셰이더를 다음과 같이 컴파일합니다." +concepts.shaders.compilation.guidance: "진입점 이름 {vSMain}은 셰이더 파일의 선언과 일치해야 합니다. 초기화 중에 셰이더를 컴파일하고 파이프라인을 만든 뒤, 렌더링 중에는 파이프라인을 재사용합니다. 파이프라인 생성이 끝나면 셰이더 객체를 해제할 수 있습니다. {link} 튜토리얼에서 이 순서를 확인할 수 있습니다." concepts.shaders.compilation.guidance.link: 첫 번째 삼각형 -concepts.shaders.compilation.title: 선택한 컨텍스트를 위한 진입점 컴파일 -concepts.shaders.description: "셰이더는 애플리케이션에서 제공하는 데이터를 수신합니다. 정점 속성은 개별 정점을 설명하고, 버퍼는 매개 변수나 배열을 보유하며, 리소스 핸들은 셰이더가 접근할 다른 리소스를 식별합니다. C# 선언과 Slang 선언은 해당 값이 의미하는 바에 대해 일치해야 합니다. 필드 이름을 일치시키는 것만으로는 충분하지 않으며 레이아웃, 리소스 접근 및 바인딩이 모두 일치해야 합니다." -concepts.shaders.dispatch.description: "{dispatch}는 스레드 그룹 수를 받습니다. 컴퓨팅 샘플의 {numthreads} 진입점은 그룹당 16 × 16개의 스레드를 실행합니다. 이미지 치수를 16으로 나누고 올림하여 그룹 수를 계산합니다. 예를 들어 17 × 19 이미지는 2 × 2 그룹이 필요합니다. 마지막 그룹에는 이미지 외부의 스레드가 포함될 수 있으므로 셰이더는 픽셀 좌표를 이미지 크기와 비교하여 검사합니다." -concepts.shaders.dispatch.details: 컴파일러는 진입점의 선언된 그룹 크기를 {shaderDescThreadGroupSize}에 저장하며 {dispatch}에 제공된 픽셀 치수를 그룹 수로 변환하지 않습니다. 완전한 바인딩 및 디스패치 예제에는 셰이더와 함께 {computeShaderRendererCs}를 사용하고 다른 패스가 출력을 사용하기 전에 {link}를 사용하세요. +concepts.shaders.compilation.title: "셰이더 컴파일" +concepts.shaders.description: "C#과 Slang의 선언은 각 값의 위치와 셰이더의 접근 방식이 일치해야 합니다. 정점 입력 레이아웃은 정점 속성을 기술하고, 셰이더의 버퍼 선언은 매개변수와 배열을 기술하며, 리소스 핸들은 셰이더가 사용할 리소스를 가리킵니다." +concepts.shaders.dispatch.description: "{dispatch}는 실행할 스레드 그룹 수를 지정합니다. 컴퓨트 예제는 {numthreads}를 선언하므로 한 그룹은 16 × 16개 스레드로 구성됩니다. 이미지 전체를 처리하려면 너비와 높이를 각각 16으로 나누고 올림합니다. 예를 들어 17 × 19 이미지는 2 × 2개 그룹이 필요합니다. 셰이더는 각 스레드의 좌표를 확인하고 이미지 범위 밖이면 처리를 건너뜁니다." +concepts.shaders.dispatch.details: "선언한 그룹 크기는 {shaderDescThreadGroupSize}에서 확인할 수 있으며, 이 값으로 {dispatch}에 전달할 그룹 수를 계산합니다. 전체 계산은 {computeShaderRendererCs}에 있습니다. 디스패치 이후 결과 이미지에 접근할 때는 {link} 문서의 요구 사항을 따릅니다." concepts.shaders.dispatch.details.link: 동기화 -concepts.shaders.dispatch.title: 픽셀이 아닌 스레드 그룹 디스패치 -concepts.shaders.layout.context: "{link}는 해당 오프셋을 명시적으로 표시합니다. 이 선언에는 범위 내에 {systemRuntimeInteropServices} 및 {zenithNET}이 필요합니다:" -concepts.shaders.layout.context.link: "컴퓨팅 샘플의 C# 상수" -concepts.shaders.layout.description: "정점 입력의 경우 파이프라인의 {inputLayout}은 형식, 오프셋, 스트라이드 및 의미 체계를 설명합니다. 삼각형의 {float3} 위치 뒤에 오는 {float4} 색상은 28바이트를 차지하며 바이트 12에 색상이 있습니다. {inputLayoutAdd}는 이 패킹된 레이아웃을 계산하며 C# 구조체를 검사하지 않습니다. C# 필드에 패딩이 포함된 경우 필드가 패킹되어 있다고 가정하지 말고 일치하는 레이아웃을 제공하세요." -concepts.shaders.layout.details: "상수 버퍼는 셰이더 매개 변수를 보유하는 반면, 구조화된 버퍼는 선언된 형식의 요소 배열을 보유합니다. 둘 다 Slang 선언에 따라 읽힙니다. {inputLayout}을 사용하지 않습니다. 패딩을 포함하여 컴파일된 셰이더 표현에 대한 필드 오프셋과 요소 크기를 확인하세요. 관리되지 않는 C# 형식은 바이트 단위로 복사하기에 적합하지만 그것만으로는 셰이더 형식과 일치함을 입증할 수 없습니다. 특히 정점의 밀접하게 패킹된 {float3} 레이아웃을 모든 셰이더 버퍼에 적용하지 마세요." -concepts.shaders.layout.guidance: 리소스 핸들은 기존 리소스를 참조하는 작은 값입니다. 핸들을 상수 버퍼에 복사한다고 해서 리소스의 내용이 복사되는 것은 아닙니다. -concepts.shaders.layout.notes: "{computeShaderSlang}의 해당 선언은 다음과 같습니다:" -concepts.shaders.layout.reference: "치수는 처음 8바이트를 차지하고 그 뒤에 8바이트 리소스 핸들 2개가 옵니다. C# 샘플은 총 256바이트를 예약합니다. 해당 크기는 샘플이 선택한 스토리지 크기이며 모든 Slang 구조체나 상수 페이로드가 256바이트를 차지해야 한다는 규칙은 아닙니다. 전체 크기를 패딩해도 잘못된 오프셋의 필드가 수정되지는 않습니다." -concepts.shaders.layout.title: 정점 입력과 셰이더 데이터의 서로 다른 레이아웃 규칙 -concepts.shaders.matrices.description: 컴파일러는 각 행의 요소를 함께 저장하는 행 우선(row-major) 행렬 스토리지를 요청합니다. {link}는 오프셋 0, 64 및 128에 세 개의 {matrix4x4} 값을 배치합니다. 해당 {detail}는 모델, 뷰 및 프로젝션 순서로 {mulVectorMatrix}를 사용합니다. +concepts.shaders.dispatch.title: "스레드 그룹" +concepts.shaders.layout.context: "{link}는 이미지 크기와 텍스처 핸들 두 개로 이 구성을 보여 줍니다. 명시적 오프셋으로 각 필드의 시작 위치를 지정합니다. 다음 선언에는 {systemRuntimeInteropServices}와 {zenithNET} 네임스페이스를 사용합니다." +concepts.shaders.layout.context.link: "컴퓨트 예제의 C# 상수" +concepts.shaders.layout.description: "정점 입력에서 {inputLayout}은 각 속성의 형식, 오프셋, 시맨틱과 정점 간 스트라이드를 기술합니다. 삼각형은 {float3} 위치 뒤에 {float4} 색상을 배치합니다. 색상은 바이트 오프셋 12에서 시작하고 정점 하나는 28바이트를 차지합니다. {inputLayoutAdd}는 요소 형식으로 이 조밀한 배치를 계산합니다. C# 구조체에 패딩이 있다면 이를 반영한 오프셋과 스트라이드를 지정해야 합니다." +concepts.shaders.layout.details: "상수 버퍼에는 셰이더 매개변수를, 구조화 버퍼에는 형식이 지정된 요소의 배열을 저장합니다. 이들의 배치는 {inputLayout}이 아니라 Slang 선언을 따릅니다. C#의 필드 오프셋, 요소 크기, 패딩을 컴파일된 셰이더 레이아웃에 맞춥니다. 관리되지 않는 C# 형식은 바이트로 복사할 수 있지만, 그 메모리 배치가 셰이더의 배치와 반드시 일치하는 것은 아닙니다. 정점에서 촘촘히 배치한 {float3}도 셰이더 버퍼에서는 다른 정렬이 필요할 수 있습니다." +concepts.shaders.layout.guidance: "셰이더 매개변수에는 일반 값뿐 아니라 리소스 핸들도 포함할 수 있습니다. 핸들은 이미 존재하는 저장 공간을 가리키므로 상수 버퍼에 핸들을 복사해도 리소스의 내용까지 복사되지는 않습니다." +concepts.shaders.layout.notes: "{computeShaderSlang}의 대응 선언은 다음과 같습니다." +concepts.shaders.layout.reference: "두 크기 값이 처음 8바이트를 차지하고, 그 뒤에 각각 8바이트인 핸들 두 개가 이어집니다. C# 예제는 전체 레코드에 256바이트를 확보합니다. 다른 레코드의 크기는 그 필드와 레이아웃 및 정렬 요구 사항에 맞춰 정합니다." +concepts.shaders.layout.title: "데이터 배치" +concepts.shaders.matrices.description: "컴파일러는 각 행을 연속으로 저장하는 행 우선 행렬 배치를 사용합니다. {link}에서는 {matrix4x4} 세 개를 오프셋 0, 64, 128에 저장합니다. 해당 {detail}는 {mulVectorMatrix}를 모델, 뷰, 투영 순으로 적용합니다." concepts.shaders.matrices.description.detail: 셰이더 concepts.shaders.matrices.description.link: 회전하는 큐브 렌더러 -concepts.shaders.matrices.details: 저장 순서는 행렬 요소가 메모리를 차지하는 방식을 결정하고 곱셈 순서는 변환을 결정합니다. 양쪽의 일관성을 유지하세요. 두 가지 선택을 확인하지 않고 전치(transpose)를 추가하면 다른 불일치를 유발하면서 한 가지 불일치를 숨길 수 있습니다. -concepts.shaders.matrices.title: 행렬 스토리지 및 곱셈의 일관성 유지 +concepts.shaders.matrices.details: "저장 순서는 메모리의 행렬 요소 배치를, 곱셈 순서는 변환을 정합니다. C#과 Slang에서 서로 맞는 규약을 사용해야 합니다." +concepts.shaders.matrices.title: "행렬 규약" concepts.shaders.title: 셰이더 데이터 및 바인딩 -concepts.synchronization.backends.description: DirectX 12 및 Vulkan은 레이아웃 및 접근 정보로 텍스처 전환을 인코딩합니다. Metal은 Zenith.NET의 {transition} 구현에 작업이 없습니다. Metal은 기록된 작업을 렌더 및 컴퓨팅 인코더로 그룹화합니다. 백엔드는 이러한 그룹을 끝낼 때 가시성 배리어를 삽입하여 이후 작업에서 이전 쓰기를 사용할 수 있도록 합니다. 명시적 {barrier} 호출은 동일한 인코더 내에서 연속적인 컴퓨팅 디스패치와 같은 종속성을 처리합니다. -concepts.synchronization.backends.details: 이 차이점은 워크로드를 변경할 때 중요합니다. {link}에서 디스패치 뒤에는 그래픽 렌더 패스가 오며, 이는 Metal에서도 인코더 경계를 생성합니다. 두 개의 종속 컴퓨팅 디스패치는 텍스처의 선언된 레이아웃을 변경하는 것만으로는 해당 경계를 생성하지 않습니다. 공유 API에 필요한 전환을 유지하고 실제 생성 및 소비 명령 간의 종속성을 별도로 식별하세요. -concepts.synchronization.backends.details.link: 컴퓨팅 샘플 -concepts.synchronization.backends.title: 전환이 모든 백엔드에서 동일하지는 않음 -concepts.synchronization.barriers.context: "{barrierStagesAll}은 더 넓은 범위이며 자동 종속성 감지기가 아닙니다. 작업을 실제로 포괄하는 단계를 선택하고 해당 작업을 지원하는 큐에서만 사용하세요." -concepts.synchronization.barriers.description: "두 개의 컴퓨팅 디스패치를 생각해 보세요. 첫 번째는 시뮬레이션 데이터를 쓰고 두 번째는 다음 단계를 수행하기 위해 해당 데이터를 읽습니다. 둘 다 스토리지 버퍼를 사용하므로 변경할 텍스처 레이아웃이 없습니다. 명령 버퍼의 디스패치 사이에 다음을 삽입합니다:" -concepts.synchronization.barriers.details: 첫 번째 인수는 생산 단계를 식별하고 두 번째 인수는 소비 단계를 식별합니다. 배리어는 GPU에 해당 실행 및 메모리 종속성을 설정합니다. 백엔드는 이러한 단계를 실행 및 메모리 접근 규칙으로 변환합니다. 이 배리어는 텍스처의 레이아웃을 변경하지 않으며 장치의 모든 작업을 대기하지도 않습니다. -concepts.synchronization.barriers.guidance: "{link}는 종속 디스패치 간에 이 패턴을 사용합니다. 종속성이 발생하는 곳에 배리어를 배치하세요. 소비자가 이미 기록된 후의 배리어는 해당 소비자를 이전 생산자 뒤에 순서대로 배치할 수 없습니다." +concepts.synchronization.backends.description: "DirectX 12와 Vulkan은 텍스처 전환을 레이아웃 및 접근 변경 명령으로 기록합니다. Metal에서는 Zenith.NET의 {transition} 구현이 이에 해당하는 GPU 작업을 수행하지 않습니다. 대신 Metal 백엔드는 명령을 렌더 인코더와 컴퓨트 인코더로 묶고 인코더가 끝날 때 가시성 배리어를 삽입합니다. 연속된 컴퓨트 디스패치처럼 같은 인코더 안에서 의존하는 작업에는 {barrier}를 명시적으로 호출합니다." +concepts.synchronization.backends.details: "{link}에서는 그래픽스 렌더 패스를 시작하면서 컴퓨트 인코더를 끝내므로 그래픽스 작업이 컴퓨트 결과를 볼 수 있습니다. 연속된 두 컴퓨트 디스패치는 같은 인코더에 남아 있으므로 중간에 텍스처 전환을 기록하더라도 의존성을 위한 배리어가 필요합니다. 여러 백엔드에서 사용할 명령 시퀀스는 이처럼 텍스처 레이아웃과 접근 의존성을 함께 고려해야 합니다." +concepts.synchronization.backends.details.link: "컴퓨트 예제" +concepts.synchronization.backends.title: "백엔드별 동작" +concepts.synchronization.barriers.context: "관련 접근을 포함하고 큐에서 지원하는 단계를 선택합니다. {barrierStagesAll}은 지원되는 모든 단계를 포함합니다. 의존성이 일부 단계에만 관련된다면 해당 단계만 선택합니다." +concepts.synchronization.barriers.description: "같은 명령 버퍼에 두 컴퓨트 디스패치를 기록한다고 가정합니다. 첫 번째는 시뮬레이션 데이터를 쓰고 두 번째는 이를 읽습니다. 두 번째가 완료된 쓰기를 볼 수 있도록 디스패치 사이에 배리어를 둡니다. 스토리지 버퍼라면 텍스처 레이아웃을 전환하지 않고 다음과 같이 접근 순서를 정할 수 있습니다." +concepts.synchronization.barriers.details: "첫 번째 인수는 데이터를 만든 단계를, 두 번째는 데이터를 사용할 단계를 지정합니다. 두 인수는 디스패치 사이에 필요한 실행 순서와 메모리 가시성을 기술합니다." +concepts.synchronization.barriers.guidance: "{link}은 시뮬레이션 단계 사이에 이 패턴을 적용합니다. 각 배리어는 데이터를 만드는 디스패치 뒤, 이를 사용하는 디스패치 앞에 놓입니다." concepts.synchronization.barriers.guidance.link: FluidTank 시뮬레이션 -concepts.synchronization.barriers.title: 배리어로 종속 명령 순서 지정 -concepts.synchronization.dependencies.description: 각 공유 리소스에 대해 먼저 접근하는 작업, 그 뒤를 잇는 작업, 둘 중 쓰기 접근이 있는지 식별합니다. 동일한 데이터를 두 번 읽는 것은 내용을 보호하기 위한 순서 지정이 필요하지 않지만, 레이아웃 변경이나 프레젠테이션으로 인해 다른 요구 사항이 적용될 수 있습니다. 쓰기 후 읽기, 읽기 후 덮어쓰기 또는 두 번의 쓰기에는 종속성이 필요할 수 있습니다. -concepts.synchronization.dependencies.details: "그런 다음 해당 작업이 실행되는 위치에 대한 메커니즘을 선택합니다:" -concepts.synchronization.dependencies.guidance: 이러한 메커니즘은 관련되어 있지만 상호 교환할 수 없습니다. 명령을 순서대로 제출한다고 해서 모든 메모리 종속성이 대체되는 것은 아닙니다. 큐 대기는 새 텍스처 레이아웃을 선언하지 않으며 명령 배리어는 호출하는 CPU 스레드에서 대기하지 않습니다. +concepts.synchronization.barriers.title: "파이프라인 배리어" +concepts.synchronization.dependencies.description: "각 리소스에서 같은 데이터를 다루는 접근을 확인합니다. 어느 한쪽이라도 쓰기라면 필요한 순서를 지켜야 합니다. 읽기끼리는 충돌하지 않지만 텍스처 레이아웃과 프레젠테이션 요구 사항은 여전히 적용됩니다. CPU가 데이터를 갱신하거나 리소스를 해제할 때도 GPU가 해당 저장 공간을 다 쓸 때까지 기다려야 합니다." +concepts.synchronization.dependencies.details: "작업이 실행되는 위치에 따라 적절한 수단을 선택합니다." +concepts.synchronization.dependencies.guidance: "한 작업에 여러 동기화 수단이 필요할 수 있습니다. 예를 들어 다른 큐에서 만든 텍스처를 사용하려면 제출 간 의존성과 다음 용도에 맞는 레이아웃이 모두 필요합니다. CPU가 직접 데이터에 접근하거나 메모리를 해제해야 하는 경우가 아니라면 이 두 작업 때문에 CPU를 대기시킬 필요는 없습니다." concepts.synchronization.dependencies.table.cpuAccess.mechanism: 해당 완료 값에 대해 {wait}를 호출합니다. -concepts.synchronization.dependencies.table.cpuAccess.situation: CPU가 데이터에 접근하거나 해제하기 전에 대기해야 하는 경우 -concepts.synchronization.dependencies.table.crossQueue.mechanism: 소비하는 명령 버퍼의 {submit}에 해당 {timelineValue}를 전달합니다. -concepts.synchronization.dependencies.table.crossQueue.situation: 다른 큐의 제출이 데이터를 생성하는 경우 +concepts.synchronization.dependencies.table.cpuAccess.situation: "CPU 접근이나 리소스 해제에 GPU 완료가 필요" +concepts.synchronization.dependencies.table.crossQueue.mechanism: "생산자의 {timelineValue}를 소비자의 {submit}에 전달합니다." +concepts.synchronization.dependencies.table.crossQueue.situation: "한 큐에서 다른 큐가 만든 데이터를 사용" concepts.synchronization.dependencies.table.headings.mechanism: 메커니즘 concepts.synchronization.dependencies.table.headings.situation: 상황 -concepts.synchronization.dependencies.table.layoutChange.mechanism: 이전 및 다음 레이아웃이 포함된 {commandBufferTransition}. +concepts.synchronization.dependencies.table.layoutChange.mechanism: "이전·다음 레이아웃을 지정한 {commandBufferTransition}." concepts.synchronization.dependencies.table.layoutChange.situation: 텍스처 하위 리소스 사용 방식 변경 -concepts.synchronization.dependencies.table.pipelineStages.mechanism: 생산 및 소비 단계를 포함하는 {commandBufferBarrier}. +concepts.synchronization.dependencies.table.pipelineStages.mechanism: "생성 단계와 소비 단계를 지정한 {commandBufferBarrier}." concepts.synchronization.dependencies.table.pipelineStages.situation: 명령 스트림의 종속 GPU 단계 -concepts.synchronization.dependencies.title: 생산자와 소비자로 시작 -concepts.synchronization.description: "이전 명령이 쓴 데이터를 읽는 명령은 쓰기가 완료되어 그 결과를 읽을 수 있어야 합니다. 쓰는 쪽은 생산자이고 읽는 쪽은 소비자입니다. CPU도 공유 데이터를 읽거나 덮어쓰거나 해제하기 전에 완료 지점이 필요합니다. Zenith.NET은 이러한 종속성에 맞춰 배리어, 텍스처 전환과 타임라인을 제공합니다." -concepts.synchronization.layouts.context: "{undefined}는 이전 내용을 보존할 필요가 없음을 의미합니다. 새 이미지나 완전히 지워질 어태치먼트에 적합합니다. 내용을 로드, 샘플링 또는 누적할 이미지의 레이아웃 추적을 피하기 위한 방법이 아닙니다." -concepts.synchronization.layouts.description: "용도 플래그는 텍스처가 지원하는 역할을 설명합니다. {textureLayout}은 작업을 위해 특정 하위 리소스에 접근하는 방식을 설명합니다. 하위 리소스는 선택된 밉 레벨과 배열 레이어입니다. 레이아웃을 변경하면 해당 접근이 준비되지만 텍스처가 다른 픽셀 형식으로 변환되지는 않습니다. 예를 들어 컴퓨팅 샘플은 {storage} 레이아웃으로 출력 텍스처를 작성한 다음 그래픽 패스에서 이를 샘플링합니다. 이러한 사용 사이에 다음을 기록합니다:" -concepts.synchronization.layouts.details: 이 조각은 {outputTexture}가 {sampledStorage} 용도로 생성되었고 선택된 하위 리소스가 {storage} 레이아웃에 있다고 가정합니다. {default}는 밉 레벨 0과 배열 레이어 0을 선택합니다. 이 작업은 텍스처의 모든 밉 또는 레이어를 전환하지는 않습니다. -concepts.synchronization.layouts.guidance: 애플리케이션은 이전 레이아웃을 제공합니다. {transition}은 애플리케이션에 표시되는 레이아웃 추적기를 유지 관리하지 않으며 이전 명령에서 해당 값을 유추하지도 않습니다. 리소스가 렌더링 단계 간에 전달되는 곳마다 레이아웃을 추적하세요. -concepts.synchronization.layouts.title: 각 텍스처 하위 리소스의 레이아웃 추적 -concepts.synchronization.readback.description: "{isCompleted}는 GPU 타임라인이 값에 도달했는지만 쿼리합니다. 명령 버퍼를 회수하거나 스테이징된 다운로드를 애플리케이션의 대상 포인터에 복사하지는 않습니다." -concepts.synchronization.readback.details: "{commandBufferDownload}는 먼저 내부 리드백 저장 공간으로의 복사를 기록합니다. 완료된 명령 버퍼를 재사용하도록 재설정할 때 CPU가 데이터를 제공된 포인터로 복사합니다. 해당 다운로드 제출 값의 {wait}가 반환될 때까지 대상 메모리를 유효하게 유지하고 관리 메모리를 고정하세요. 데이터 읽기나 메모리 해제는 그 이후에 해야 합니다. 다른 큐의 후속 제출을 기다리는 것만으로는 다운로드를 관리하는 큐가 폴링되지 않습니다." -concepts.synchronization.readback.guidance: 이것이 {isCompleted}를 폴링하고 비동기 다운로드 대상을 즉시 읽는 것만으로는 충분하지 않은 이유입니다. {link}에서 직접 복사 및 스테이징 전송 경로를 다룹니다. +concepts.synchronization.dependencies.title: "접근 의존 관계" +concepts.synchronization.description: "동기화는 공유 데이터에 접근하는 순서를 정하고, 뒤의 작업이 필요한 결과를 볼 수 있게 합니다. 쓰기에서 읽기로 이어지는 의존성에서 쓰는 작업을 생산자, 읽는 작업을 소비자라고 합니다. 배리어와 텍스처 전환은 GPU 접근을 조율하며, 타임라인은 제출 간 의존성을 연결하고 CPU가 GPU 완료를 기다릴 수 있게 합니다." +concepts.synchronization.layouts.context: "새 이미지나 전체를 지울 어태치먼트처럼 기존 내용을 버려도 되는 경우 이전 레이아웃에 {undefined}를 사용합니다. 로드, 샘플링, 누적에 기존 내용이 필요하다면 직전 접근의 레이아웃을 지정합니다." +concepts.synchronization.layouts.description: "용도 플래그는 텍스처에 허용된 역할을 선언합니다. {textureLayout}은 밉 레벨과 배열 레이어로 식별한 하위 리소스를 명령 시퀀스의 특정 지점에서 어떻게 접근하는지 나타냅니다. 접근 방식이 바뀌면 전환을 기록합니다. 예를 들어 컴퓨트 예제는 출력 텍스처를 {storage} 레이아웃에서 쓴 뒤 그래픽스 패스에서 샘플링할 수 있도록 준비합니다." +concepts.synchronization.layouts.details: "여기서는 {outputTexture}를 {sampledStorage} 용도로 만들었고 선택한 하위 리소스는 {storage} 상태입니다. {default}는 mip 레벨 0과 배열 레이어 0을 선택합니다. 다른 레벨이나 레이어에는 영향을 주지 않습니다." +concepts.synchronization.layouts.guidance: "{transition}에는 하위 리소스의 직전 사용 레이아웃을 전달합니다. 애플리케이션은 명령을 기록하고 렌더링 단계 사이에 텍스처를 전달하면서 이 상태를 추적합니다." +concepts.synchronization.layouts.title: "텍스처 레이아웃" +concepts.synchronization.readback.description: "{isCompleted}는 GPU 완료 여부를 알려 줍니다. 기록된 다운로드에는 내부 리드백 공간의 결과를 애플리케이션의 대상 메모리로 복사하는 단계가 하나 더 있습니다." +concepts.synchronization.readback.details: "{commandBufferDownload}는 내부 리드백 공간으로의 GPU 복사를 기록합니다. 제출이 끝나면 라이브러리는 완료된 명령 버퍼를 회수하면서 CPU 복사를 수행합니다. 다운로드를 제출해 받은 값에서 {wait}를 호출하면 GPU 완료를 기다리고 해당 큐의 완료된 버퍼도 처리하므로 두 단계가 모두 끝납니다. 호출이 반환할 때까지 대상 메모리의 할당을 유지하고, 관리형 메모리라면 고정 상태도 유지합니다." +concepts.synchronization.readback.guidance: "{isCompleted}만 조회해서는 마지막 CPU 복사가 수행되지 않습니다. 다른 큐를 기다리는 것 역시 다운로드 큐의 완료된 버퍼를 회수하지 않습니다. 업로드와 다운로드가 직접 메모리 접근이나 스테이징 공간을 사용하는 조건은 {link} 문서에서 설명합니다." concepts.synchronization.readback.guidance.link: 리소스 관리 -concepts.synchronization.readback.title: GPU 완료와 다운로드된 CPU 데이터는 별개의 단계임 -concepts.synchronization.reuse.description: "첫 번째 렌더러의 경우 각 프레임 직후에 대기하는 것이 간단합니다. 작업을 중첩하려면 미해결 프레임에 별도의 가변 데이터를 제공하고 각 프레임의 최종 사용 완료 값을 유지하세요. 상수 버퍼를 업데이트하거나 텍스처를 교체하거나 파이프라인을 해제하기 전에 영향을 받는 리소스에 대한 모든 미해결 접근을 완료하세요." -concepts.synchronization.reuse.details: "크기 조정 또는 종료 시 이전 작업을 기다리기 전에 새 사용을 중지하세요. {swapChainResize}, 리소스 해제 및 컨텍스트 해제는 애플리케이션 작업에 대한 일반적인 대기 역할을 하지 않습니다. 이전 각 프레임이 이미 제출을 완료했으므로 삼각형 튜토리얼은 콜백 간에 안전하게 크기를 조정할 수 있습니다." -concepts.synchronization.reuse.guidance: 현재 {swapChainPresent}도 프레젠테이션 작업 후 그래픽 큐에서 신호를 보내고 대기합니다. 따라서 삼각형의 명시적 제출 대기를 제거한다고 해서 그 자체로 중첩 프레젠테이션 루프가 설정되지는 않습니다. 또한 그래픽 큐 대기는 다른 큐에서 여전히 실행 중인 독립적인 작업에 대해서는 아무것도 보장하지 않습니다. -concepts.synchronization.reuse.title: 최종 접근 후에만 데이터 재사용 -concepts.synchronization.timelines.context: "CPU가 이러한 리소스를 읽거나 덮어쓰거나 해제하기 전에 최종 사용을 기다리세요:" -concepts.synchronization.timelines.description: 타임라인은 증가하는 값을 사용하여 큐의 완료를 추적합니다. {submit}은 해당 타임라인과 제출과 관련된 값을 포함하는 {timelineValue}를 반환합니다. 서로 다른 타임라인의 완료 값은 숫자 {value} 필드만으로는 비교할 수 없습니다. -concepts.synchronization.timelines.details: "{producer}와 {consumer}가 동일한 컨텍스트의 두 큐에서 이미 기록된 명령 버퍼라고 가정합니다. 생산자는 소비자가 사용하는 데이터를 씁니다. 다음과 같이 제출하세요:" -concepts.synchronization.timelines.guidance: 생성된 값을 전달하면 소비 큐가 GPU에서 이를 기다립니다. CPU는 여기서 {producedWait}를 호출하지 않습니다. {consumed}가 완료될 때까지 공유 리소스를 유효하게 유지하고 소비자가 요구하는 텍스처 레이아웃 변경 사항을 기록하세요. -concepts.synchronization.timelines.notes: "{wait}는 해당 타임라인 값을 기다린 다음 소유 큐에서 완료된 제출을 확인합니다. 완료된 명령 버퍼는 재사용을 위해 재설정되고 스테이징된 다운로드는 제공된 CPU 대상에 복사됩니다. {queueTimelineSignal}은 해당 큐에 이미 제출된 작업 후에 완료 지점을 큐에 추가할 수도 있습니다. {signal}을 호출한다고 해서 GPU가 이미 해당 지점에 도달했음을 의미하지는 않습니다." -concepts.synchronization.timelines.title: 완료 및 큐 전달에 타임라인 사용 +concepts.synchronization.readback.title: "리드백 완료" +concepts.synchronization.reuse.description: "삼각형은 각 프레임이 끝난 뒤 데이터를 재사용합니다. 프레임을 겹쳐 실행하려면 진행 중인 프레임마다 별도의 수정 가능한 저장 공간을 두고 언제 다시 사용할 수 있는지 추적합니다. 데이터를 변경하기 전에는 해당 바이트에 아직 접근하는 GPU 작업을 기다리고, 리소스를 해제하기 전에는 그 리소스의 모든 사용이 끝날 때까지 기다립니다." +concepts.synchronization.reuse.details: "크기 변경과 종료에도 같은 원칙이 적용됩니다. 새 사용을 막고 기존 사용이 끝날 때까지 기다린 뒤 리소스를 교체하거나 해제합니다. {swapChainResize}를 호출하거나 리소스 또는 컨텍스트를 해제하기 전에 이 순서를 지켜야 합니다. 삼각형은 매 프레임 기다리므로 콜백 호출 사이에서 크기를 바꿀 수 있습니다." +concepts.synchronization.reuse.guidance: "{swapChainPresent}는 이미지를 표시한 뒤 그래픽스 큐에 신호를 보내고 완료를 기다립니다. 따라서 명시적인 제출 대기를 제거해도 삼각형은 화면 표시 단계에서 여전히 기다립니다. 다른 큐에 독립적으로 제출한 작업은 별도로 완료를 추적해야 합니다." +concepts.synchronization.reuse.title: "리소스 재사용" +concepts.synchronization.timelines.context: "소비자가 끝난 뒤 CPU에서 결과를 읽거나 공유 데이터를 덮어쓰거나 리소스를 해제하려면 해당 제출을 기다립니다." +concepts.synchronization.timelines.description: "타임라인은 증가하는 값으로 큐의 완료를 나타냅니다. {submit}은 타임라인과 제출 값을 담은 {timelineValue}를 반환합니다. 서로 다른 타임라인의 숫자 {value}를 직접 비교할 수는 없습니다." +concepts.synchronization.timelines.details: "같은 컨텍스트의 두 큐에서 기록한 {producer}와 {consumer}가 있고, 소비자가 생산자가 쓴 데이터를 사용한다고 하겠습니다. 다음 의존 관계로 제출합니다." +concepts.synchronization.timelines.guidance: "소비자 큐는 전달받은 완료 값에 도달할 때까지 기다린 뒤 명령을 실행합니다. CPU는 {producedWait}를 호출하지 않고 계속 진행할 수 있습니다. {consumed}가 완료될 때까지 공유 리소스를 유지하고, 소비자의 접근에 필요한 텍스처 전환을 기록합니다." +concepts.synchronization.timelines.notes: "{queueTimelineSignal}이 반환한 값도 {wait}로 기다리거나 다른 큐의 의존성에 사용할 수 있습니다. {signal}은 이미 제출된 작업 뒤에 완료 지점을 넣으며, GPU는 그 작업을 끝낸 뒤 해당 지점에 도달합니다." +concepts.synchronization.timelines.title: "타임라인과 큐 간 의존 관계" concepts.synchronization.title: 동기화 home.actions.reference: API 탐색 home.actions.tutorial: 삼각형으로 시작하기 -home.entries.description: 첫 번째 프레임. 핵심 예제. API에 대한 자세한 정보. -home.entries.label: 문서 탐색 +home.entries.description: "튜토리얼, 예제, API 참조" +home.entries.label: "문서 구성" home.entries.reference.action: API 탐색 home.entries.reference.category: 참조 -home.entries.reference.description: 애플리케이션의 기반이 되는 형식, 시그니처 및 멤버를 확인하세요. +home.entries.reference.description: "API 형식, 멤버, 선언 찾아보기" home.entries.reference.title: API 참조 home.entries.samples.action: 예제 탐색 home.entries.samples.category: 예제 -home.entries.samples.description: 소스 코드를 통해 핵심 렌더링 및 컴퓨팅 기법을 살펴보세요. +home.entries.samples.description: "직접 실행하며 살펴보는 그래픽스와 컴퓨트 예제" home.entries.samples.title: 예제 -home.entries.title: 빌드를 시작하세요. +home.entries.title: "문서" home.entries.tutorial.action: 튜토리얼 시작 home.entries.tutorial.category: 튜토리얼 -home.entries.tutorial.description: 설정부터 첫 번째 프레임까지 완전한 렌더링 애플리케이션을 구축하세요. +home.entries.tutorial.description: "빈 프로젝트에서 첫 삼각형을 그리기까지" home.entries.tutorial.title: 첫 번째 삼각형 -home.introduction.accent: "C#으로 구축." -home.introduction.description: 단일 .NET API를 통해 리소스를 생성하고, 명령을 기록하며, 그래픽 또는 컴퓨팅 작업을 제출하세요. -home.introduction.title: 나만의 렌더러를 구축하세요. -home.meta.description: "DirectX, Metal 및 Vulkan 전반에서 그래픽 및 컴퓨팅을 위한 일관된 C# API를 제공합니다." -home.scene.description: 회전하는 지오메트리 연구입니다. 드래그하거나 화살표 키를 사용하여 보기를 조정하세요. +home.introduction.accent: "크로스 플랫폼 그래픽스" +home.introduction.description: "Zenith.NET은 DirectX, Metal, Vulkan의 그래픽스와 컴퓨트 기능을 하나의 API로 제공합니다" +home.introduction.title: ".NET으로 만드는{lineBreak}{accent}" +home.meta.description: "DirectX, Metal, Vulkan의 공통 API로 개발하는 .NET 크로스 플랫폼 그래픽스·컴퓨트 애플리케이션" +home.scene.description: "회전하는 도형을 조작할 수 있습니다. 드래그하거나 방향키를 눌러 시점을 바꾸세요." home.scene.label: 지오메트리 표시 home.scene.surface: 서피스 home.scene.wireframe: 와이어프레임 -home.title: .NET을 위한 모던 RHI -learning.concepts.description: 렌더 패스를 결합하기 전에 명령, 리소스, 셰이더 데이터 및 동기화가 어떻게 맞물려 동작하는지 이해하세요. -learning.concepts.execution.description: GPU 작업을 기록하고 제출하며, 해당 리소스를 유효하게 유지하세요. -learning.concepts.platforms.description: 네이티브 윈도우 또는 UI 렌더링 컨트롤을 연결하세요. -learning.concepts.resources.description: 리소스 용도, 메모리 배치 및 뷰를 선택하세요. -learning.concepts.shaders.description: "C# 레이아웃과 리소스 핸들을 Slang과 일치시키세요." -learning.concepts.synchronization.description: 종속적인 접근 순서를 지정하고 작업 완료 시점을 파악하세요. +home.title: ".NET을 위한 현대적인 RHI" +learning.concepts.description: "리소스 용도를 선택하고 셰이더 데이터를 기술하며 GPU 실행을 조율하는 방법" +learning.concepts.execution.description: "명령 기록과 제출, 리소스 수명" +learning.concepts.platforms.description: "네이티브 화면 표시와 UI 렌더링 컨트롤" +learning.concepts.resources.description: "리소스 용도, 메모리 배치, 뷰" +learning.concepts.shaders.description: "C#과 Slang의 데이터 배치 및 바인딩 규약" +learning.concepts.synchronization.description: "의존 관계, 가시성, 완료" learning.concepts.title: 핵심 개념 -learning.description: 완전한 삼각형 튜토리얼로 시작하세요. 그런 다음 핵심 예제와 개념 가이드를 활용하여 더 큰 렌더러의 기반이 되는 리소스, 데이터 및 종속성을 이해하세요. +learning.description: "삼각형 튜토리얼로 첫 애플리케이션을 만들어 보세요. 이후 리소스 관리, 셰이더 데이터, 동기화 개념을 필요한 순서대로 읽거나 구현하려는 기법의 예제를 살펴볼 수 있습니다." learning.entries.samples.action: 예제 탐색 -learning.entries.samples.description: "지오메트리, 컴퓨팅, 레이 쿼리 및 메시 셰이딩에 대한 C# 및 Slang 예제를 찾아보세요." +learning.entries.samples.description: "지오메트리, 컴퓨트, 레이 쿼리, 메시 셰이딩의 C# 및 Slang 구현" learning.entries.tutorial.action: 튜토리얼 열기 -learning.entries.tutorial.description: 콘솔 애플리케이션을 생성하고, 윈도우를 열며, 삼각형을 그립니다. -learning.meta.description: Zenith.NET을 시작하고 해당 프로그래밍 모델을 살펴보세요. +learning.entries.tutorial.description: "창을 열고 삼각형을 그리는 콘솔 애플리케이션" +learning.meta.description: "Zenith.NET 프로그래밍 모델을 위한 튜토리얼과 개념 설명" learning.title: 학습 -reference.description: 리소스 형식, 명령 시그니처 및 플랫폼 통합을 조회하세요. -reference.entries.commands.description: 그래픽, 컴퓨팅 및 전송 명령을 기록하세요. -reference.entries.commands.label: 작업 기록 -reference.entries.context.description: 선택한 백엔드를 위한 GPU 리소스를 생성하세요. +reference.description: "리소스, 명령, 플랫폼 통합 참조" +reference.entries.commands.description: "그래픽스, 컴퓨트, 전송 명령" +reference.entries.commands.label: "명령 기록" +reference.entries.context.description: "선택한 백엔드의 GPU 리소스 생성" reference.entries.context.label: 여기서 시작 -reference.meta.description: Zenith.NET의 형식과 멤버를 살펴보세요. -reference.navigation.core: 핵심 API를 탐색하세요. +reference.meta.description: "Zenith.NET 네임스페이스, 형식, 멤버" +reference.navigation.core: "핵심 API 참조" reference.title: API 참조 -samples.computeShader.description: 컴퓨팅 디스패치로 이미지를 그레이스케일로 변환하고 결과 텍스처를 표시합니다. 샘플링된 입력 텍스처 및 쓰기 가능한 출력 텍스처를 위한 리소스 핸들, 올림 처리된 스레드 그룹 수, 셰이더 내 경계 검사를 보여줍니다. 포함된 {assetsTexturesShokoPng} 에셋을 유지하세요. 렌더러는 이를 한 번 처리하고 후속 프레임에서 결과를 표시합니다. +samples.computeShader.description: "이 예제는 {assetsTexturesShokoPng}를 읽고 컴퓨트 디스패치에서 회색조로 변환한 뒤 결과 텍스처를 표시합니다. 변환은 한 번만 실행하고 이후 프레임은 같은 결과를 표시합니다. 렌더러는 샘플링용 텍스처와 쓰기 가능한 텍스처를 바인딩하고, 스레드 그룹 수를 올림해 이미지 전체를 처리하며, 셰이더에서 이미지 범위를 확인하는 방법을 보여 줍니다." samples.computeShader.details: "{computeShaderRendererCs} · {computeShaderSlang}" -samples.computeShader.title: 컴퓨팅 셰이더 -samples.cube.description: 상수 버퍼의 모델, 뷰, 프로젝션 행렬, 인덱스 드로잉 및 깊이 테스트를 추가합니다. 크기 조정 시 깊이 텍스처가 다시 생성됩니다. 클립 공간 지오메트리에서 변환된 객체로 전환할 때 사용하세요. 렌더러는 {d32FloatS8UInt} 깊이/스텐실 어태치먼트를 사용합니다. +samples.computeShader.title: "컴퓨트 셰이더" +samples.cube.description: "큐브는 인덱스 그리기, 상수 버퍼의 모델·뷰·투영 행렬, 깊이 테스트를 추가합니다. {d32FloatS8UInt} 깊이·스텐실 텍스처는 크기를 바꿀 때 다시 생성합니다." samples.cube.details: "{spinningCubeRendererCs} · {spinningCubeSlang}" samples.cube.title: 회전하는 큐브 -samples.description: "연구하고자 하는 기능에 맞춘 예제를 선택하세요. 각 예제는 C# 렌더러와 해당 Slang 셰이더로 연결됩니다. 빈 프로젝트부터 전체 애플리케이션에 대한 설명을 원하시면 {link}부터 시작하세요." +samples.description: "각 예제는 C# 렌더러와 Slang 셰이더를 함께 제공하며 한 가지 기법을 다룹니다. 애플리케이션 구성부터 렌더링까지의 전체 과정은 {link}에서 설명합니다." samples.description.link: 첫 번째 삼각형 -samples.execution.description: "{link}에는 하나의 데스크톱 애플리케이션 내에 6개의 독립적인 렌더러가 포함되어 있습니다. .NET 10 SDK와 아래에 설명된 지원되는 데스크톱 백엔드를 사용하세요. 애플리케이션을 빌드 및 실행한 다음 콘솔 메뉴에서 예제를 선택하세요." +samples.execution.description: "{link} 프로젝트를 실행하고 콘솔 메뉴에서 예제를 선택합니다." samples.execution.description.link: ZenithTutorials -samples.execution.details: 호스트는 Windows에서 DirectX 12, macOS에서 Metal, Linux에서 Vulkan을 선택합니다. 선택한 백엔드에서 지원하는 장치, 드라이버 및 셰이더 컴파일러 환경을 사용하세요. Linux 윈도우 경로는 X11 또는 XWayland가 필요합니다. {link}는 패키지 종속성을 선언하고 런타임에 필요한 셰이더 및 텍스처 에셋을 복사합니다. -samples.execution.details.link: 프로젝트 파일 -samples.execution.guidance: 예제들은 윈도우 처리 및 프레젠테이션 코드를 공유합니다. 연구하려는 기능에 따라 각 예제를 독립적으로 선택할 수 있습니다. -samples.execution.title: 튜토리얼 예제 실행하기 -samples.host.description: "{appCs}는 컨텍스트, 윈도우 및 스왑 체인을 생성합니다. 명령 버퍼를 가져오고, 선택한 렌더러를 호출하며, 프레임을 제출하고 표시합니다. {iRendererCs}는 렌더러의 업데이트, 렌더링, 크기 조정 및 해제 메서드를 정의합니다." -samples.host.details: 컴퓨팅 및 레이 트레이싱은 오프스크린 텍스처를 생성합니다. {texturePresenterCs} 및 {presentTextureSlang}은 해당 텍스처를 윈도우의 현재 프레임의 출력 텍스처에 그립니다. 호스트는 여전히 제출 및 스왑 체인 프레젠테이션을 소유합니다. -samples.host.title: 공유 호스트 및 프레젠테이션 -samples.indirectDrawing.description: 인덱스화된 간접 인수 버퍼와 구조화된 버퍼의 인스턴스별 데이터를 사용하여 큐브의 여러 복사본을 그립니다. CPU가 드로잉 인수를 제공하고 변환을 업데이트합니다. GPU 생성 인수를 추가하기 전에 간접 인수 레이아웃과 인스턴스 데이터에 대한 셰이더 접근을 이해하는 데 사용하세요. +samples.execution.title: "예제 실행" +samples.host.description: "{appCs}는 컨텍스트, 창, 스왑 체인을 초기화합니다. 매 프레임 명령 버퍼를 얻고 선택한 렌더러를 호출한 다음 명령을 제출하고 결과를 표시합니다. {iRendererCs}는 갱신, 렌더링, 크기 변경, 해제 작업을 정의합니다." +samples.host.details: "컴퓨트 렌더러와 레이 트레이싱 렌더러는 오프스크린 텍스처를 만듭니다. {texturePresenterCs}와 {presentTextureSlang}이 이 텍스처를 현재 출력 텍스처에 그리면, 공통 호스트가 명령을 제출하고 프레임을 화면에 표시합니다." +samples.host.title: "호스트와 화면 표시" +samples.indirectDrawing.description: "간접 그리기는 인덱스 그리기 인수 버퍼와 인스턴스별 구조화 데이터 버퍼로 여러 큐브를 그립니다. CPU가 인수를 제공하고 변환을 갱신합니다." samples.indirectDrawing.details: "{indirectDrawingRendererCs} · {indirectDrawingSlang}" -samples.indirectDrawing.title: 간접 드로잉 -samples.meshShading.description: 태스크 셰이더를 사용하여 구 인스턴스를 컬링하고 지오메트리를 내보내는 메시 셰이더로 인덱스를 전달합니다. 렌더러는 파이프라인을 생성하기 전에 {contextCapabilitiesMeshShadingSupported}를 확인합니다. 태스크 및 메시 단계를 통해 리소스 핸들과 페이로드 데이터를 추적하는 데 사용하세요. +samples.indirectDrawing.title: "간접 그리기" +samples.meshShading.description: "태스크 셰이더가 구 인스턴스를 컬링하고 남은 인덱스를 메시 셰이더에 전달하면 메시 셰이더가 지오메트리를 생성합니다. 파이프라인 생성 전에 {contextCapabilitiesMeshShadingSupported}를 확인합니다." samples.meshShading.details: "{meshShadingRendererCs} · {meshShadingSlang}" samples.meshShading.title: 메시 셰이딩 -samples.rayTracing.description: 지면과 절차적 구체를 위한 하위 및 상위 가속 구조를 구축한 다음 컴퓨팅 셰이더에서 인라인 레이 쿼리를 추적합니다. 렌더러는 워크로드를 구성하기 전에 {contextCapabilitiesRayTracingSupported}를 확인합니다. 가속 구조 입력 및 셰이더 측 광선 순회에 이 예제를 사용하세요. +samples.rayTracing.description: "바닥과 절차적 구의 하위·상위 가속 구조를 만들고 컴퓨트 셰이더에서 인라인 레이 쿼리를 수행합니다. 초기화 전에 {contextCapabilitiesRayTracingSupported}를 확인합니다." samples.rayTracing.details: "{rayTracingRendererCs} · {rayTracingSlang}" samples.rayTracing.title: 레이 트레이싱 samples.title: 예제 -samples.triangle.description: 정점 버퍼와 일치하는 입력 레이아웃을 생성한 다음 그래픽스 파이프라인을 통해 세 개의 정점을 그립니다. 리소스 생성과 렌더 패스 내의 명령을 연결하는 데 사용하세요. +samples.triangle.description: "정점 버퍼와 대응하는 입력 레이아웃을 연결하고 그래픽스 파이프라인으로 정점 세 개를 그립니다." samples.triangle.details: "{helloTriangleRendererCs} · {helloTriangleSlang} · {link}" samples.triangle.details.link: 전체 튜토리얼 samples.triangle.title: Hello Triangle -samples.workloads.description: "메인 저장소의 {link}에는 여러 기능을 결합한 애플리케이션이 포함되어 있습니다. 해당 프로젝트는 라이브러리 소스 코드를 참조합니다. Zenith.NET 체크아웃에서 원하는 프로젝트를 실행하세요. 예:" +samples.workloads.description: "주 저장소의 {link}에는 라이브러리 소스를 참조하는 더 큰 규모의 애플리케이션이 있습니다." samples.workloads.description.link: Experiments 디렉터리 -samples.workloads.details: 윈도우 기반 실험은 Windows, macOS 및 Linux/X11에 대해 동일한 호스트 선택을 사용합니다. Avalonia, WinForms, WPF, WinUI/Uno 또는 MAUI 내에서의 드로잉, 컨트롤 프레임 수명 주기 및 구현 링크에 대해서는 {link}를 참조하세요. +samples.workloads.details: "창을 사용하는 실험은 동일한 Windows, macOS, Linux/X11 표시 경로를 사용합니다. Avalonia, WinForms, WPF, WinUI/Uno, MAUI 컨트롤의 프레임 흐름과 구현 소스는 {link}에서 설명합니다." samples.workloads.details.link: 플랫폼 통합 samples.workloads.table.cornellBox.example: "{link}" samples.workloads.table.cornellBox.example.link: CornellBox -samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: 패스 트레이싱, 디노이징, 톤 매핑, 업스케일링 및 ImGui 컨트롤을 보여줍니다. 레이 트레이싱 지원과 데스크톱 백엔드용 셰이더 컴파일러 환경이 필요합니다. +samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: "패스 트레이싱, 디노이징, 톤 매핑, 업스케일링, ImGui 컨트롤을 다룹니다. 레이 트레이싱 지원이 필요합니다." samples.workloads.table.fluidTank.example: "{link}" samples.workloads.table.fluidTank.example.link: FluidTank -samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: 컴퓨팅 유체 시뮬레이션, 시뮬레이션 단계 간 종속성 및 다중 패스 표면 렌더링을 보여줍니다. 데스크톱 백엔드 및 셰이더 컴파일러 환경이 필요합니다. +samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: "컴퓨트 유체 시뮬레이션, 시뮬레이션 단계 사이의 의존 관계, 다중 패스 표면 렌더링을 다룹니다." samples.workloads.table.headings.example: 예제 -samples.workloads.table.headings.whatItDemonstratesAndRequires: 시연 내용 및 요구 사항 +samples.workloads.table.headings.whatItDemonstratesAndRequires: "기법과 요구 사항" samples.workloads.table.inkCanvas.example: "{link}" samples.workloads.table.inkCanvas.example.link: InkCanvas -samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: 네이티브 윈도우에서의 Skia 드로잉 및 입력 처리를 보여줍니다. 대상 플랫폼용 백엔드 및 네이티브 Skia 라이브러리가 필요합니다. +samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: "네이티브 창에서의 Skia 그리기 및 입력 처리를 보여줍니다. 대상 플랫폼용 백엔드 및 네이티브 Skia 라이브러리가 필요합니다." samples.workloads.table.platformDetection.example: "{link}" samples.workloads.table.platformDetection.example.link: PlatformDetection -samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: 각 백엔드에 대한 컨텍스트 생성을 시도하고 장치 기능을 보고합니다. 컨텍스트 생성이 실패하면 지원되지 않는 것으로 보고되며, 이 결과는 드라이버 또는 런타임 종속성 누락을 나타낼 수도 있습니다. -samples.workloads.title: 더 큰 규모의 워크로드 살펴보기 -tutorial.context.description: 이제 윈도우를 열 수 있지만 윈도우에 렌더링할 GPU 개체는 아직 생성하지 않았습니다. {graphicsContext}는 선택한 그래픽 백엔드 및 해당 명령 큐에 대한 액세스를 제공합니다. -tutorial.context.details: "이 블록을 {emphasis}에 삽입합니다:" +samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: "각 백엔드의 컨텍스트 생성을 시도하고 장치 기능을 보고합니다. 생성에 실패하면 지원되지 않는 것으로 표시하지만, 원인은 장치나 드라이버 또는 누락된 런타임 의존성일 수 있습니다." +samples.workloads.title: "복합 렌더링 애플리케이션" +tutorial.context.description: "{graphicsContext}는 백엔드를 통해 애플리케이션을 GPU에 연결하고 렌더링 리소스를 만드는 메서드를 제공합니다." +tutorial.context.details: "컨텍스트 초기화를 {emphasis}에 추가합니다." tutorial.context.details.emphasis: using 지시문 뒤, {iWindowWindow} 앞 -tutorial.context.guidance: 분기는 Windows에서는 DirectX 12, macOS에서는 Metal, Linux에서는 Vulkan을 선택합니다. 이어지는 렌더링 코드는 공유 Zenith.NET API를 사용합니다. 개발 중에 유효성 검사를 요청하고 {validationMessage}를 통해 보고된 메시지를 출력합니다. 진단은 백엔드 및 컴퓨터에서 사용 가능한 유효성 검사 구성 요소에 따라 다릅니다. -tutorial.context.title: 그래픽스 컨텍스트 생성 -tutorial.description: 윈도우를 열고 부드러운 그라데이션이 있는 삼각형을 그리는 .NET 콘솔 애플리케이션을 빌드합니다. 정점 데이터, 셰이더 및 파이프라인 상태가 함께 작동하는 방식을 배우고, 이미지를 생성하는 명령을 기록하고 제출합니다. -tutorial.details: 섹션을 순서대로 진행하세요. 먼저 빈 윈도우를 연 다음 배경색을 표시하고 마지막으로 삼각형을 그립니다. 각 체크포인트는 다음 단계를 추가하기 전에 애플리케이션의 한 부분을 확인합니다. 초기화는 한 번 실행되며, 렌더링 콜백은 호출될 때마다 새 프레임을 기록합니다. -tutorial.draw.context: "{draw}에 대한 인수는 다음과 같습니다:" -tutorial.draw.description: "{windowRender} 콜백에서 {beginRenderPass}와 {endRenderPass} 사이의 {addTheTriangleDrawCommandsHereLater}를 다음 세 가지 명령으로 바꿉니다:" -tutorial.draw.details: "{setPipeline}은 방금 생성한 셰이더와 상태를 선택합니다. 정점 데이터를 바인딩하기 전에 설정하세요. 백엔드는 파이프라인의 입력 레이아웃을 사용하여 바인딩을 해석합니다." -tutorial.draw.guidance: "{setVertexBufferVertexBuffer}는 바이트 오프셋 0부터 시작하는 버퍼를 입력 슬롯 0에 바인딩합니다. 해당 슬롯은 {inputLayouts}의 단일 항목에 해당합니다. 데이터를 다시 복사하거나 업로드하지는 않습니다." -tutorial.draw.notes: 이 시점에서는 명령이 여전히 기록되기만 한 상태입니다. 렌더링 콜백 끝에 이미 있는 {submitWait} 및 {present} 호출이 작업을 실행하고 결과를 표시합니다. 삼각형이 이미지의 일부만 가리기 때문에 클리어 작업은 여전히 필요합니다. 배경 역시 각 프레임마다 정의된 색상을 받아야 합니다. +tutorial.context.guidance: "각 분기에서 플랫폼에 맞는 백엔드를 선택하고 검증을 요청합니다. {validationMessage} 메시지는 콘솔에 출력합니다." +tutorial.context.imports: "{programCs} 맨 위에 다음 using 지시문을 추가합니다." +tutorial.context.title: "그래픽스 컨텍스트" +tutorial.description: "이 튜토리얼에서는 빈 .NET 콘솔 프로젝트에서 시작해 창을 열고 색상이 있는 삼각형을 그리는 애플리케이션을 만듭니다." +tutorial.details: "튜토리얼에는 세 번의 확인 단계가 있습니다. 먼저 빈 창을 열고, 단색 배경을 표시한 다음, 색상이 있는 삼각형을 그립니다. 각 단계에서 애플리케이션을 실행해 결과를 확인한 뒤 다음 부분을 추가합니다." +tutorial.draw.context: "{draw}의 인수는 다음과 같습니다." +tutorial.draw.description: "{windowRender} 콜백의 {addTheTriangleDrawCommandsHereLater}를 다음 명령으로 바꿉니다. 위치는 {beginRenderPass}와 {endRenderPass} 사이입니다." +tutorial.draw.details: "{setPipeline}은 셰이더와 렌더링 상태를 선택합니다. 정점 바인딩은 파이프라인의 입력 레이아웃으로 해석되므로, 그 전에 호출해야 합니다." +tutorial.draw.guidance: "{setVertexBufferVertexBuffer}는 업로드한 정점 데이터를 바이트 오프셋 0부터 입력 슬롯 0에 바인딩합니다. 이 슬롯은 {inputLayouts}의 유일한 항목과 대응합니다." +tutorial.draw.notes: "이 호출들은 그리기 명령을 기록합니다. 기존의 {submitWait}가 명령을 제출하고 GPU 완료를 기다리면, {present}가 완성된 이미지의 표시를 요청합니다. 삼각형 바깥 영역에도 배경색이 정해지도록 패스 시작 부분의 지우기 작업을 유지합니다." tutorial.draw.table.firstInstance.meaning: 인스턴스 번호 매기기를 0부터 시작합니다. tutorial.draw.table.firstVertex.meaning: 버퍼의 첫 번째 정점부터 시작합니다. tutorial.draw.table.headings.argument: 인수 @@ -368,45 +362,47 @@ tutorial.draw.table.headings.description: 값 tutorial.draw.table.headings.meaning: 의미 tutorial.draw.table.instanceCount.meaning: 삼각형 한 개를 그립니다. tutorial.draw.table.vertexCount.meaning: 세 개의 정점을 읽습니다. -tutorial.draw.title: 패스 내부에서 삼각형 그리기 -tutorial.execution.description: "{firstTriangle} 디렉터리에서 빌드하고 실행합니다:" -tutorial.execution.details: 윈도우에는 어두운 배경에 위쪽 모서리는 빨간색, 오른쪽 아래 모서리는 녹색, 왼쪽 아래 모서리는 파란색인 삼각형이 표시되어야 합니다. 내부는 해당 색상 간의 부드러운 그라데이션을 보여야 합니다. -tutorial.execution.guidance: 윈도우 크기를 조정해 보세요. 크기 조정 콜백은 프레임버퍼 치수를 업데이트하고 스왑 체인의 크기를 조정합니다. 렌더 패스는 해당 이미지와 일치하는 뷰포트를 설정합니다. 정점 위치가 정규화된 좌표로 유지되기 때문에 삼각형은 윈도우 너비와 높이의 동일한 비율을 유지합니다. 종횡비를 변경하면 모양이 늘어날 수 있습니다. 개체의 종횡비를 유지하려면 투영 또는 뷰포트 정책이 필요하며, 이는 이 첫 번째 드로잉의 범위를 벗어납니다. -tutorial.execution.title: 실행, 크기 조정 및 닫기 -tutorial.frame.commands.context: "{endRenderPass} 후 두 번째 전환은 프레젠테이션을 위해 이미지를 준비합니다. {submit}은 기록을 완료하고 명령 버퍼를 제출하며, {wait}는 GPU가 해당 제출을 완료할 때까지 기다립니다. 그런 다음 {present}는 렌더링된 이미지의 표시를 요청합니다." -tutorial.frame.commands.description: 렌더 패스는 동일한 어태치먼트를 사용하는 드로잉 작업을 그룹화합니다. 여기서 색상 어태치먼트는 스왑 체인의 출력 텍스처, 즉 드로잉을 수신하는 이미지입니다. {colorAttachmentClear}는 지정된 RGBA 색상으로 지우고 패스가 끝날 때 결과를 유지하도록 지시하는 설명을 생성합니다. {beginRenderPass}는 해당 지침을 기록하며, GPU는 명령이 제출된 후 지우기를 수행합니다. -tutorial.frame.commands.details: 대괄호에는 단일 색상 어태치먼트가 포함되어 있습니다. {null} 인수는 깊이 및 스텐실 테스트를 위한 깊이 값과 스텐실 마스크를 저장할 깊이/스텐실 어태치먼트가 없음을 의미합니다. -tutorial.frame.commands.guidance: "{beginRenderPass}는 어태치먼트를 덮는 뷰포트와 시저를 설정합니다. 뷰포트는 렌더링된 좌표를 픽셀에 매핑하고 시저는 쓸 수 있는 픽셀을 제한합니다. 이러한 기본값은 출력 텍스처 전체를 포괄하며, 이는 이 삼각형에 필요한 설정입니다." -tutorial.frame.commands.title: 클리어, 제출 및 프레젠테이션 -tutorial.frame.description: 먼저 이미지를 단일 배경색으로 채웁니다. 이 작업을 클리어(clear)라고 합니다. 해당 색상이 윈도우에 나타나면 서피스, 명령 제출 및 프레젠테이션 경로가 함께 작동하고 있는 것입니다. 이 체크포인트를 사용하면 지오메트리와 셰이더를 추가하기 전에 프레임 루프를 확인할 수 있습니다. -tutorial.frame.details: "렌더링 콜백은 프레임을 그릴 때 Silk.NET이 호출하는 코드입니다. 이 콜백은 이벤트의 경과 시간 인수가 필요하지 않으므로 {value}로 지정됩니다. {emphasis}에 등록합니다:" +tutorial.draw.title: "그리기 명령" +tutorial.execution.description: "{firstTriangle} 프로젝트를 빌드하고 실행합니다." +tutorial.execution.details: "어두운 배경 위에 위쪽은 빨강, 오른쪽 아래는 초록, 왼쪽 아래는 파랑인 삼각형이 나타나야 합니다. 내부 색상은 정점 색상을 보간한 결과로, 부드럽게 이어집니다." +tutorial.execution.guidance: "창 크기를 바꾸면 이미지의 픽셀 크기가 달라지지만 정점 좌표는 그대로입니다. 뷰포트는 이 좌표를 새로운 너비와 높이에 맞추므로 창의 가로세로 비율이 바뀌면 삼각형도 늘어나거나 줄어듭니다." +tutorial.execution.title: "애플리케이션 실행" +tutorial.frame.commands.context: "{endRenderPass} 뒤의 두 번째 전환은 출력 텍스처를 화면에 표시할 수 있도록 준비합니다. {submit}은 기록을 끝내고 명령 버퍼를 제출하며, {wait}는 해당 제출이 완료될 때까지 CPU 스레드를 대기시킵니다. 이어서 {present}가 렌더링한 이미지의 표시를 요청합니다." +tutorial.frame.commands.description: "렌더 패스는 같은 어태치먼트에 쓰는 그리기 작업을 묶습니다. 이 패스에서는 스왑 체인의 출력 텍스처가 색상 결과를 받습니다. {colorAttachmentClear}는 해당 어태치먼트를 RGBA 색상으로 초기화하고 패스가 끝난 뒤에도 내용을 보존하도록 지정합니다. {beginRenderPass}는 이 설정으로 패스를 시작하는 명령을 기록합니다." +tutorial.frame.commands.details: "컬렉션에는 색상 어태치먼트 하나가 있습니다. {null}은 이 패스에 깊이·스텐실 어태치먼트가 없다는 뜻입니다." +tutorial.frame.commands.guidance: "{beginRenderPass}는 어태치먼트 전체를 덮도록 뷰포트와 시저를 설정합니다. 뷰포트는 렌더링 좌표를 픽셀 위치로 바꾸고 시저는 쓸 수 있는 영역을 제한합니다." +tutorial.frame.commands.title: "지우기, 제출, 표시" +tutorial.frame.description: "먼저 창을 하나의 배경색으로 채웁니다. 이 작업을 지우기라고 합니다. 배경색이 보이면 서피스, 명령 제출, 표시 과정이 연결된 것입니다. 이제 삼각형의 정점과 셰이더를 추가할 수 있습니다." +tutorial.frame.details: "Silk.NET은 프레임을 그릴 시점에 콜백을 호출합니다. 이 예제는 경과 시간 인수를 쓰지 않으므로 매개변수 이름을 {value}로 둡니다. 콜백을 {emphasis}에 등록합니다." tutorial.frame.details.emphasis: "{windowRun} 앞" -tutorial.frame.target.description: "{graphicsQueueCommandBuffer}는 기록이 이미 시작된 명령 버퍼를 가져옵니다. 기록은 GPU에 대한 작업을 설명하는 것이며 해당 작업을 즉시 실행하지는 않습니다." -tutorial.frame.target.details: 첫 번째 {transition}은 색상 어태치먼트 접근을 위해 출력 텍스처를 준비합니다. {default}는 밉 레벨 0과 배열 레이어 0을 선택합니다. 전체 이미지를 지우고 이전 내용을 버릴 것이므로 이전 레이아웃으로 {undefined}를 사용합니다. 기존 내용을 보존해야 하는 패스는 대신 실제 이전 레이아웃을 사용해야 합니다. -tutorial.frame.target.guidance: 각 프레임마다 스왑 체인의 현재 출력 텍스처를 사용하세요. 프레젠테이션으로 인해 사용 가능한 이미지가 변경될 수 있으므로 이전 프레임에서 저장된 텍스처는 영구적인 윈도우 렌더 타깃이 아닙니다. -tutorial.frame.target.title: 출력 텍스처 준비 -tutorial.frame.title: 배경색 표시 -tutorial.geometry.data.description: 이 배열을 {emphasis}에 추가합니다. 다음 리소스 생성 단계도 표시된 순서대로 해당 콜백 앞에 배치됩니다. +tutorial.frame.target.description: "{graphicsQueueCommandBuffer}는 기록할 준비가 된 명령 버퍼를 반환합니다. 기록은 GPU 작업을 정의하는 단계이며 실행은 제출 후 시작됩니다." +tutorial.frame.target.details: "텍스처 레이아웃은 작업에 필요한 접근 방식을 나타냅니다. 첫 번째 {transition} 호출은 출력 텍스처를 색상 어태치먼트로 사용할 수 있도록 준비합니다. 여기서 {default}는 출력 텍스처의 기본 이미지인 밉 레벨 0과 배열 레이어 0을 선택합니다. 이 패스는 이미지 전체를 지우므로 {undefined}를 지정해 이전 내용을 버릴 수 있습니다." +tutorial.frame.target.guidance: "화면에 표시한 뒤에는 다른 이미지로 넘어갈 수 있으므로 매 프레임 현재 출력 텍스처를 가져옵니다." +tutorial.frame.target.title: "출력 텍스처 준비" +tutorial.frame.title: "첫 프레임" +tutorial.geometry.data.description: "정점 배열을 {emphasis}에 추가합니다. 이후 리소스 초기화도 설명한 순서대로 이 콜백 앞에 둡니다." tutorial.geometry.data.description.emphasis: "{windowRender} 앞" -tutorial.geometry.data.details: 각 배열 항목은 {vertex}를 생성합니다. 두 개의 내부 {new} 표현식은 해당 {vector3} 위치와 {vector4} 색상을 생성합니다. 정점은 위쪽, 오른쪽 아래, 왼쪽 아래 모서리를 설명합니다. 정점 셰이더는 네 번째 위치 좌표인 {w}를 제공합니다. w가 1이면 x와 y는 정규화된 장치 좌표를 직접 설명합니다. -1과 +1은 이미지 가장자리이고 0은 중심입니다. 이러한 좌표는 윈도우의 픽셀 크기에 의존하지 않습니다. -tutorial.geometry.data.guidance: 각 색상에는 빨강, 초록, 파랑 및 알파 구성 요소가 포함되어 있습니다. 알파는 세 모서리 모두에서 1입니다. 세 위치 모두 z = 0이므로 동일한 평면에 배치됩니다. 이러한 위치는 렌더링하려는 좌표를 이미 설명하고 있으므로 카메라나 변환 행렬이 필요하지 않습니다. 이 단일 평면 삼각형의 경우 블렌딩 및 깊이 테스트도 비활성화하고 깊이 버퍼를 생략합니다. -tutorial.geometry.data.title: 모서리 선택 -tutorial.geometry.description: 정점은 그리는 데 사용되는 데이터와 함께 제공되는 점입니다. 우리의 삼각형에는 각 모서리마다 하나씩 세 개의 정점이 있습니다. 각각에는 위치와 색상이 포함되어 있습니다. GPU는 색상을 보간하여 삼각형 전체에 걸쳐 중간 값을 계산합니다. -tutorial.geometry.format.description: "이 선언을 {emphasis}에 추가합니다:" +tutorial.geometry.data.details: "각 항목은 {vertex}를 생성하고, 안쪽의 두 {new} 표현식은 {vector3} 위치와 {vector4} 색상을 제공합니다. 위치는 위, 오른쪽 아래, 왼쪽 아래 꼭짓점입니다. 정점 셰이더는 네 번째 좌표를 {w}로 설정합니다. w가 1이므로 x와 y는 정규화 장치 좌표이기도 하며, -1과 +1은 이미지 경계, 0은 중앙을 뜻합니다. 이 해석은 픽셀 크기와 무관합니다." +tutorial.geometry.data.guidance: "각 색상은 빨강, 초록, 파랑, 알파 성분을 가지며 알파는 1입니다. 세 정점 모두 z = 0인 같은 평면에 있습니다." +tutorial.geometry.data.title: "정점 위치와 색상" +tutorial.geometry.description: "세 정점은 각각 위치와 색상을 가집니다. GPU는 위치로 삼각형 모양을 정하고 정점 색상을 보간해 내부의 색상을 계산합니다." +tutorial.geometry.format.description: "정점 선언을 {emphasis}에 추가합니다." tutorial.geometry.format.description.emphasis: "{programCs} 끝부분, 정리 문 뒤" -tutorial.geometry.format.details: "{file}은 이 형식을 {programCs}로 제한하며, 생성자는 위치 및 색상 필드를 초기화합니다. {layoutKindSequential}은 필드를 선언 순서대로 유지합니다. {position}에는 32비트 부동소수점 3개가 포함되고 {color}에는 4개가 포함됩니다. 이 구조체에서 위치는 바이트 0에서 시작하고 색상은 바이트 12에서 시작하며 완전한 정점은 28바이트를 차지합니다. 그래픽스 파이프라인에 동일한 레이아웃을 설명할 것입니다." -tutorial.geometry.format.title: 정점 정의 -tutorial.geometry.title: GPU에 정점 세 개 제공 -tutorial.geometry.upload.context: "{fixed}는 주소가 사용되는 동안 가비지 수집기가 배열을 이동하지 못하도록 방지합니다. 이 CPU 쓰기 가능 버퍼의 경우 {upload}는 반환하기 전에 메모리를 매핑, 복사 및 매핑 해제하므로 나중에 배열을 고정된 상태로 유지할 필요가 없습니다. 버퍼는 렌더링 내내 유지되어야 하며 정점이 변경되지 않으므로 업로드는 한 번만 수행하면 됩니다." -tutorial.geometry.upload.description: "관리되는 배열은 CPU 데이터입니다. {buffer}는 GPU가 정점을 읽을 수 있는 스토리지를 제공합니다. 배열 뒤에 다음을 추가합니다:" -tutorial.geometry.upload.details: "총 크기는 {sizeofVertexVerticesLength}입니다. 정점당 28바이트, 3개의 정점, 총 84바이트입니다. {bufferUsagesVertex}는 정점 입력 접근을 허용합니다. {cpuWriteOnly}를 사용하면 CPU가 이 작은 버퍼를 직접 초기화할 수 있습니다. 설명자의 스트라이드는 요소 크기를 기록합니다. 아래에서 생성할 입력 레이아웃은 개별 속성을 읽는 방법을 정점 가져오기에 알려줍니다." -tutorial.geometry.upload.guidance: 버퍼를 생성해도 채워지지는 않습니다. {upload}는 대상 바이트 오프셋 0부터 시작하여 해당 할당에 배열을 복사합니다. 소스 설명은 포인터와 복사할 바이트 수를 제공합니다. -tutorial.geometry.upload.notes: "{programCs} 하단의 정리에서 {swapChainDispose} 바로 앞에 {vertexBufferDispose}를 추가하세요. 더 큰 정적 지오메트리의 경우 {link}에서 GPU 전용 메모리와 전송 업로드를 대신 선택해야 하는 시점을 설명합니다." +tutorial.geometry.format.details: "{file}은 형식의 사용 범위를 {programCs}로 제한하고, {layoutKindSequential}은 필드를 선언 순서대로 배치합니다. {position}은 32비트 부동소수점 값 세 개로 구성되며 바이트 오프셋 0에서 시작합니다. {color}는 네 개로 구성되며 바이트 오프셋 12에서 시작합니다. 따라서 정점 하나는 28바이트입니다. GPU가 각 필드를 올바르게 읽을 수 있도록 입력 레이아웃에 이 배치를 기술합니다." +tutorial.geometry.format.imports: "벡터 형식과 구조체 레이아웃 특성을 사용하도록 {programCs} 맨 위에 다음 using 지시문을 추가합니다." +tutorial.geometry.format.title: "정점 표현" +tutorial.geometry.title: "정점 데이터" +tutorial.geometry.upload.context: "{fixed}는 배열의 주소를 사용하는 동안 가비지 수집기가 배열을 옮기지 못하게 고정합니다. 이 버퍼는 CPU 쓰기가 가능하므로 {upload}는 메모리를 매핑하고 바이트를 복사한 뒤 매핑을 해제하고 반환합니다. 배열은 이 호출이 끝날 때까지만 고정하면 됩니다. 정점은 초기화 중에 한 번 업로드하고, 버퍼는 렌더링이 끝날 때까지 유지합니다." +tutorial.geometry.upload.description: "GPU가 그리기 중에 읽을 수 있도록 정점 데이터를 {buffer}에 저장합니다. 배열 바로 뒤에 버퍼 할당과 업로드 코드를 추가합니다." +tutorial.geometry.upload.details: "할당 크기는 {sizeofVertexVerticesLength}로, 28바이트 정점 세 개인 84바이트입니다. {bufferUsagesVertex}는 정점 입력 접근을 선언하고 {cpuWriteOnly}는 CPU 직접 초기화를 허용합니다. 설명의 스트라이드는 요소 크기이며, 뒤에서 정의할 입력 레이아웃이 각 속성을 읽는 방법을 정합니다." +tutorial.geometry.upload.guidance: "할당만으로 버퍼 내용이 초기화되지는 않습니다. {upload}는 데이터 설명의 원본 포인터와 바이트 수를 사용해 배열을 목적지 오프셋 0에 복사합니다." +tutorial.geometry.upload.imports: "Zenith.NET 버퍼 형식을 {systemBuffer}와 구분하기 위해 {programCs}의 using 지시문에 {bufferAlias} 구문을 추가합니다." +tutorial.geometry.upload.notes: "{programCs} 끝의 해제 코드에서 {swapChainDispose} 바로 앞에 {vertexBufferDispose}를 추가합니다. 큰 정적 지오메트리를 위한 GPU 전용 저장과 전송은 {link}에서 설명합니다." tutorial.geometry.upload.notes.link: 리소스 관리 -tutorial.geometry.upload.title: 버퍼 할당 및 배열 업로드 -tutorial.input.description: "정점 바이트와 셰이더가 준비되었습니다. 다음으로 GPU가 각 정점을 읽는 방법을 설명합니다. 속성은 위치나 색상과 같은 단일 값입니다. 입력 레이아웃은 각 속성에 형식과 바이트 오프셋을 제공합니다. 스트라이드는 한 정점에서 다음 정점까지의 바이트 단위 거리를 제공합니다. 셰이더 생성 후 이 초기화 블록을 추가합니다:" -tutorial.input.details: "{inputLayoutAdd}는 현재 스트라이드에 요소를 추가하고 해당 스트라이드를 요소 크기만큼 늘립니다. C# 구조체를 검사하지는 않습니다. 여기서는 CPU 메모리와 셰이더 입력 간에 다음과 같은 일치 관계를 생성합니다:" -tutorial.input.guidance: "이 설명을 업데이트하지 않고 C# 필드 순서나 패딩을 변경하면 GPU가 잘못된 바이트를 읽게 됩니다. 기본 {semanticIndex}는 0이며 {pOSITION0} 및 {cOLOR0}과 일치합니다. 두 요소 모두 동일한 버퍼에 속하므로 파이프라인에는 하나의 입력 레이아웃이 포함되며 해당 버퍼를 슬롯 0에 바인딩합니다." +tutorial.geometry.upload.title: "버퍼 할당과 업로드" +tutorial.input.description: "GPU는 위치와 색상 같은 정점 속성이 어디에 있는지 알아야 합니다. 입력 레이아웃은 각 속성의 포맷과 바이트 오프셋을 지정합니다. 스트라이드는 다음 정점까지의 바이트 거리입니다. 셰이더를 생성한 뒤 다음 코드를 추가합니다." +tutorial.input.details: "{inputLayoutAdd}는 각 속성을 이전 속성 바로 뒤에 배치하고 그 크기를 정점 간 스트라이드에 더합니다. 오프셋은 C# 구조체를 조사하는 대신 여기서 지정한 형식으로 계산합니다. 두 필드의 배치는 다음과 같습니다." +tutorial.input.guidance: "{semanticIndex}의 기본값은 0이며 셰이더의 {pOSITION0}, {cOLOR0}과 일치합니다. 위치와 색상이 하나의 정점 버퍼에 함께 저장되므로 파이프라인은 슬롯 0에 입력 레이아웃 하나를 사용합니다. C# 구조체의 필드 순서나 패딩을 바꾸면 입력 레이아웃도 맞춰 수정합니다." tutorial.input.table.headings.byteOffset: 바이트 오프셋 tutorial.input.table.headings.cField: "C# 필드" tutorial.input.table.headings.format: 형식 @@ -416,110 +412,102 @@ tutorial.input.table.nextVertex.format: "총 스트라이드: 28바이트" tutorial.input.table.nextVertex.shaderInput: 다음 입력 레코드 tutorial.input.table.vertexColor.format: "{float4} (16바이트)" tutorial.input.table.vertexPosition.format: "{float3} (12바이트)" -tutorial.input.title: 정점 입력 레이아웃 설명 -tutorial.lifecycle.description: "완성된 애플리케이션은 이 시퀀스를 반복합니다:" -tutorial.lifecycle.details: "윈도우를 닫으면 {run}에서 반환됩니다. 렌더링된 각 프레임은 이미 GPU 작업이 완료될 때까지 기다렸으므로 이제 사용된 리소스를 안전하게 해제할 수 있습니다. {windowRun} 이후의 정리는 다음과 같아야 합니다:" -tutorial.lifecycle.guidance: "네이티브 윈도우보다 먼저 스왑 체인을 해제하고, 모든 리소스를 해제한 후 컨텍스트를 해제하세요. 제출된 명령 버퍼는 큐가 소유하고 재활용하며, 출력 텍스처는 스왑 체인이 소유합니다. 따라서 이 애플리케이션에서는 해당 명령 버퍼와 출력 텍스처에 별도의 {dispose} 호출이 필요하지 않습니다." -tutorial.lifecycle.title: 단일 프레임의 수명 주기 추적 -tutorial.pipeline.behavior: "입력 레이아웃 뒤에 다음을 추가합니다:" -tutorial.pipeline.context: "{cullNone}은 면의 방향을 버리지 않고 삼각형을 채웁니다. 정점의 순서에 따라 면의 감기 방향이 결정되므로 컬링을 비활성화하면 해당 순서로 인해 첫 번째 삼각형이 숨겨지는 것을 방지할 수 있습니다." -tutorial.pipeline.description: 이제 정점 데이터, 입력 레이아웃 및 두 개의 셰이더가 준비되었습니다. {graphicsPipeline}은 이들을 연결하고 GPU가 정점을 기본형(primitive)으로 조립하고 결과를 어태치먼트에 쓰는 방법을 지정합니다. -tutorial.pipeline.details: "파이프라인은 프로그래밍 가능한 셰이더 단계와 삼각형 조립, 면 컬링, 블렌딩과 같은 GPU 작업을 제어하는 고정 기능 설정을 결합합니다. 이 삼각형의 경우 다음 설정을 선택합니다:" -tutorial.pipeline.guidance: 색상 형식은 {swapChainDescFormat}에서 가져옵니다. 렌더 패스에서 사용하는 이미지와 일치해야 합니다. {count1}은 픽셀당 하나의 샘플을 의미합니다. -tutorial.pipeline.item: "{triangleList}는 연속된 세 개의 정점 그룹을 하나의 삼각형으로 조립합니다. 세 개의 정점을 제공하고 한 번 그리므로 인덱스 버퍼가 필요하지 않습니다." -tutorial.pipeline.notes: "{depthNone}은 깊이 테스트 및 쓰기를 비활성화하여 깊이 어태치먼트가 없는 패스와 일치시킵니다." -tutorial.pipeline.reference: "{opaque}는 블렌딩을 비활성화하므로 조각 셰이더의 색상이 삼각형 내부의 배경을 대체합니다." -tutorial.pipeline.title: 셰이더 및 정점 레이아웃 연결 -tutorial.pipeline.usage: "샘플 렌더러에서와 같이 파이프라인을 생성한 후 셰이더 개체를 해제할 수 있습니다. 파이프라인 자체는 이를 사용하여 그리는 모든 프레임 동안 유지하세요. 정리에서 {vertexBufferDispose} 앞에 {pipelineDispose}를 추가합니다. 파이프라인 생성은 렌더링 콜백 전 마지막 초기화 단계입니다." -tutorial.pipeline.validation: 파이프라인 설명은 어태치먼트 구성을 선언하며 다른 이미지를 생성하지 않습니다. 위치와 색상이 하나의 버퍼에 함께 저장되므로 {inputLayouts}에는 하나의 항목이 있습니다. -tutorial.presentation.title: GPU를 윈도우에 연결 -tutorial.project.context: 프로젝트의 빌드 설정에서 {emphasis}({allowUnsafeBlocks})를 사용하도록 설정하세요. 정점 데이터를 GPU에 전달하고 윈도우 도우미의 네이티브 호출에 이를 사용합니다. +tutorial.input.title: "정점 입력 레이아웃" +tutorial.lifecycle.description: "각 프레임은 다음 순서를 따릅니다." +tutorial.lifecycle.details: "창을 닫으면 {run}이 반환하고 정리 코드가 이어서 실행됩니다. 각 프레임에서 제출한 작업이 끝날 때까지 이미 기다렸으므로 명령에 사용한 리소스를 해제할 수 있습니다. {windowRun} 뒤에 들어갈 전체 정리 코드는 다음과 같습니다." +tutorial.lifecycle.guidance: "네이티브 창을 파괴하기 전에 스왑 체인을 해제하고, 컨텍스트는 그 리소스들을 해제한 뒤 정리합니다. 제출한 명령 버퍼는 큐가 재사용하고 출력 텍스처는 스왑 체인이 관리하므로 각각 {dispose}를 호출할 필요가 없습니다." +tutorial.lifecycle.title: "프레임 흐름과 해제" +tutorial.pipeline.behavior: "입력 레이아웃 다음에 파이프라인을 생성합니다." +tutorial.pipeline.context: "{cullNone}은 면 컬링을 끕니다. 따라서 정점이 시계 방향으로 보이든 반시계 방향으로 보이든 삼각형을 그립니다." +tutorial.pipeline.description: "{graphicsPipeline}은 정점 레이아웃, 두 셰이더, 프리미티브 조립과 어태치먼트 출력 설정을 하나로 묶습니다." +tutorial.pipeline.details: "셰이더는 정점과 프래그먼트를 처리합니다. 나머지 파이프라인 설정은 프리미티브 조립, 면 컬링, 깊이 테스트, 색상 블렌딩을 제어합니다." +tutorial.pipeline.guidance: "파이프라인의 색상 포맷은 렌더 패스의 어태치먼트와 같아야 하므로 {swapChainDescFormat}에서 가져옵니다. {count1}은 픽셀당 샘플 하나를 지정합니다." +tutorial.pipeline.item: "{triangleList}는 연속된 정점 세 개를 한 삼각형으로 조립합니다." +tutorial.pipeline.notes: "{depthNone}은 깊이 테스트와 쓰기를 끕니다. 깊이 어태치먼트가 없는 패스와 일치하는 설정입니다." +tutorial.pipeline.reference: "{opaque}는 블렌딩을 끕니다. 따라서 프래그먼트 셰이더 출력이 삼각형 내부의 배경색을 대체합니다." +tutorial.pipeline.title: "그래픽스 파이프라인" +tutorial.pipeline.usage: "셰이더 객체는 파이프라인을 생성한 뒤 해제할 수 있습니다. 파이프라인은 렌더링 동안 유지하고, 해제 코드에서 {vertexBufferDispose} 앞에 {pipelineDispose}를 추가합니다." +tutorial.presentation.title: "그래픽스 컨텍스트와 표시" +tutorial.project.context: "프로젝트 빌드 설정에서 {emphasis}({allowUnsafeBlocks})를 켭니다. 창 보조 코드의 네이티브 호출과 정점 업로드에는 unsafe 코드가 필요합니다." tutorial.project.context.emphasis: 안전하지 않은 코드 허용 -tutorial.project.description: "프로젝트를 생성하고 해당 디렉터리로 이동합니다:" -tutorial.project.details: "패키지를 설치합니다:" -tutorial.project.guidance: "{zenithNET}은 공유 렌더링 API를 제공합니다. 세 가지 백엔드 패키지를 통해 동일한 프로그램이 해당 플랫폼에 적합한 구현을 선택할 수 있습니다. {zenithNETCompiler}는 나중에 작성할 작은 GPU 프로그램인 Slang 셰이더를 해당 구현을 위해 컴파일합니다. Silk.NET은 윈도우와 이벤트 루프를 제공합니다." -tutorial.project.title: 콘솔 프로젝트 생성 -tutorial.requirements.context: 빈 프로젝트에서 이 페이지를 따라갈 수 있습니다. {link} 및 해당 {detail}는 여기서 사용되는 렌더링 및 윈도우 API에 대한 참조로 제공됩니다. +tutorial.project.description: ".NET 10을 대상으로 하는 {firstTriangle} C# 콘솔 프로젝트를 만듭니다." +tutorial.project.details: "다음 NuGet 패키지를 프로젝트에 추가합니다." +tutorial.project.guidance: "{zenithNET}은 공통 렌더링 API를, 백엔드 패키지 세 개는 플랫폼 구현을 제공합니다. {zenithNETCompiler}는 뒤에서 작성할 Slang 셰이더를 선택한 백엔드에 맞게 컴파일합니다. Silk.NET은 창 생성과 이벤트 처리를 담당합니다." +tutorial.project.title: "프로젝트 준비" +tutorial.requirements.context: "{link}와 해당 {detail}에서 이 튜토리얼의 참조 구현을 확인할 수 있습니다." tutorial.requirements.context.detail: 공유 호스트 -tutorial.requirements.context.link: Hello Triangle 샘플 -tutorial.requirements.description: "{emphasis}, 코드 편집기 또는 IDE, Zenith.NET 백엔드에서 지원하는 GPU 및 드라이버가 장착된 데스크톱 환경이 필요합니다. C#에 대한 기본적인 이해만 있으면 충분하며, 그래픽 개념은 사용될 때마다 설명됩니다. 이것은 일반적인 {net10} 콘솔 프로젝트입니다. 백엔드는 Zenith.NET 작업을 DirectX 12, Metal 또는 Vulkan과 같은 그래픽 API 호출로 변환합니다. 애플리케이션은 시작 시 그중 하나를 선택합니다:" +tutorial.requirements.context.link: "Hello Triangle 예제" +tutorial.requirements.description: "{emphasis}와 기본 C# 지식이 필요합니다. 애플리케이션의 대상 프레임워크는 {net10}입니다. GPU와 드라이버는 사용 중인 플랫폼에 맞춰 선택한 다음 백엔드를 지원해야 합니다." tutorial.requirements.description.emphasis: .NET 10 SDK -tutorial.requirements.details: Linux는 여기서 사용되는 윈도우 경로에 대해 X11 호환 윈도우 세션이 필요합니다. 이 삼각형을 그리는 데 선택적 레이 트레이싱 및 메시 셰이딩 기능은 필요하지 않습니다. -tutorial.requirements.guidance: Zenith.NET은 애플리케이션에서 제공하는 서피스에 렌더링합니다. Silk.NET.Windowing이 데스크톱 윈도우를 생성하고 해당 이벤트를 처리합니다. macOS에서 프레젠테이션 대상은 Metal 레이어({cAMetalLayerCs})입니다. 튜토리얼의 윈도우 도우미가 해당 레이어를 연결해 줍니다. +tutorial.requirements.guidance: "Zenith.NET은 애플리케이션이 제공하는 네이티브 서피스에 렌더링합니다. Silk.NET.Windowing은 창을 만들고 이벤트를 처리합니다. macOS에서는 {cAMetalLayerCs}로 표현되는 Metal 레이어로 표시하며, 창 보조 코드가 이 레이어를 창에 연결합니다." tutorial.requirements.table.headings.graphicsBackend: 그래픽 백엔드 tutorial.requirements.table.headings.platform: 플랫폼 -tutorial.requirements.table.headings.windowSurface: 윈도우 서피스 tutorial.requirements.table.linux.graphicsBackend: Vulkan 1.4 -tutorial.requirements.table.linux.platform: Linux -tutorial.requirements.table.linux.windowSurface: X11 윈도우 및 디스플레이 (XWayland도 적합) +tutorial.requirements.table.linux.platform: "Linux(X11 또는 XWayland)" tutorial.requirements.table.macOS.graphicsBackend: Metal 4 tutorial.requirements.table.macOS.platform: macOS -tutorial.requirements.table.macOS.windowSurface: 윈도우에 연결된 Metal 레이어 tutorial.requirements.table.windows.graphicsBackend: DirectX 12 tutorial.requirements.table.windows.platform: Windows -tutorial.requirements.table.windows.windowSurface: Win32 윈도우 핸들 -tutorial.requirements.title: 시작하기 전에 -tutorial.resize.context: "{dotnetRun}을 다시 실행합니다. 이제 윈도우에는 크기를 조정한 후에도 계속 채워지는 균일한 어두운 배경이 있어야 합니다. 이 콜백을 유지하세요. 삼각형은 기존 렌더 패스 내에 그려집니다." -tutorial.resize.description: "스왑 체인의 이미지는 프레임버퍼 치수를 따라야 합니다. 디스플레이 배율로 인한 변경 사항을 포함하여 픽셀 크기 변경에 응답하려면 {framebufferResize}를 사용하세요. 렌더링 콜백 뒤, 여전히 {windowRun} 앞에 다음을 추가합니다:" -tutorial.resize.details: Silk.NET은 윈도우 크기 변경과 {link}를 구분합니다. 스왑 체인은 픽셀을 저장하므로 후자가 필요합니다. 최소화된 윈도우는 크기가 0인 프레임버퍼를 가질 수 있습니다. 두 콜백 모두 해당 경우 GPU 작업을 건너뜁니다. 크기 조정 후 렌더 패스는 뷰포트 및 시저에 새 어태치먼트 치수를 사용합니다. +tutorial.requirements.title: "준비 사항" +tutorial.resize.context: "애플리케이션을 다시 빌드하고 실행합니다. 창 크기를 바꿔도 배경이 창 전체를 채워야 합니다. 새 렌더 패스를 시작할 때마다 변경된 어태치먼트 크기로 뷰포트와 시저가 설정되기 때문입니다. 렌더링 콜백은 그대로 둡니다. 이후 이 패스 안에서 삼각형을 그립니다." +tutorial.resize.description: "프레임버퍼 크기가 바뀌면 스왑 체인도 그에 맞춰야 합니다. 렌더링 콜백 뒤, {windowRun} 앞에 {framebufferResize} 콜백을 등록합니다." +tutorial.resize.details: "창의 논리적 크기 대신 픽셀 단위의 {link}을 처리합니다. 창을 최소화하면서 너비나 높이가 0이 되면 크기 변경 콜백은 스왑 체인을 그대로 둡니다. 렌더링 콜백도 어느 한쪽이 0인 동안에는 바로 반환하므로, 프레임버퍼가 다시 유효한 크기가 될 때까지 렌더링이 중단됩니다." tutorial.resize.details.link: 프레임버퍼 크기 변경 -tutorial.resize.guidance: 제출할 때마다 기다리므로 크기 조정 핸들러가 이미지를 바꿀 때 이전 프레임이 여전히 해당 이미지를 사용하고 있지 않습니다. 현재 {present} 구현도 그래픽 큐에서 대기합니다. 이 간단한 루프는 다음 프레임이 시작되기 전에 한 프레임의 작업이 완료된 상태를 유지합니다. {link}에서 고급 일정 관리를 다룹니다. +tutorial.resize.guidance: "렌더링 콜백은 제출한 프레임이 끝날 때까지 기다린 뒤 {present}를 호출합니다. 따라서 크기 변경 콜백은 이전 프레임의 작업을 방해하지 않고 스왑 체인 이미지를 교체할 수 있습니다. 작업 완료와 리소스 수명의 관계는 {link} 문서에서 자세히 설명합니다." tutorial.resize.guidance.link: 동기화 -tutorial.resize.title: 크기 조정에 대응 -tutorial.shaders.compilation.context: 컴파일은 초기화 중에 한 번 수행됩니다. {appContextBaseDirectory}는 현재 작업 디렉터리와 관계없이 실행 파일 옆에 복사된 셰이더를 찾습니다. 이러한 셰이더는 정점 입력만 사용하므로 바인딩할 상수 버퍼, 텍스처 또는 리소스 핸들이 아직 없습니다. -tutorial.shaders.compilation.description: "{triangleSlang}의 파일 속성에서 {emphasis}를 {detail}로 설정합니다. 이렇게 하면 실행 파일 옆에서 셰이더를 사용할 수 있습니다." +tutorial.resize.title: "크기 변경" +tutorial.shaders.compilation.context: "{appContextBaseDirectory}를 사용하면 애플리케이션 출력 디렉터리에 복사한 셰이더를 불러옵니다. 다른 작업 디렉터리에서 애플리케이션을 실행하더라도 셰이더를 찾는 위치는 바뀌지 않습니다." +tutorial.shaders.compilation.description: "{triangleSlang}의 파일 속성에서 {emphasis}를 {detail}로 설정합니다. 빌드하면 셰이더가 실행 파일 옆으로 복사됩니다." tutorial.shaders.compilation.description.detail: 변경된 내용만 복사 tutorial.shaders.compilation.description.emphasis: 출력 디렉터리에 복사 -tutorial.shaders.compilation.details: "{programCs}로 돌아갑니다. 정점 업로드 후, 렌더링 콜백 앞에 다음 초기화 문을 추가합니다:" -tutorial.shaders.compilation.guidance: "{zenithCompiler}는 요청된 그래픽 API용 코드가 포함된 셰이더 설명을 반환합니다. {createShader}는 해당 백엔드 개체를 생성합니다. 그래픽 API와 진입점 이름이 모두 중요합니다. {contextGraphicsApi}를 사용하고 {vSMain} 및 {fSMain}을 Slang 파일과 정확히 동일한 철자로 작성하세요." -tutorial.shaders.compilation.title: 선택한 백엔드용으로 컴파일 -tutorial.shaders.context: "{fSInput}은 정점 셰이더의 출력을 조각 셰이더의 입력에 연결합니다. 정점 셰이더가 쓰는 {sVPOSITION}은 클립 공간 위치를 제공하며, GPU는 이 네 좌표로 가시 영역 안에 있는 내용을 판단합니다. {cOLOR0}은 정점 사이에서 보간할 색상을 전달합니다. 두 단계에서 사용하는 형식과 시맨틱이 일치해야 합니다." -tutorial.shaders.description: 셰이더는 GPU가 실행하는 프로그램입니다. 이 드로잉에는 정점을 배치하기 위한 정점 셰이더와 삼각형 내부의 색상을 생성하기 위한 조각 셰이더가 필요합니다. 우리는 셰이더 언어인 Slang으로 이를 작성하고 동일한 파일에서 두 개의 진입점을 컴파일할 것입니다. 진입점은 셰이더 단계가 실행되기 시작하는 함수입니다. -tutorial.shaders.details: "이 두 구조체로 시작하여 {triangleSlang}을 생성합니다:" -tutorial.shaders.fragment.description: "동일한 파일에 조각 진입점을 추가합니다:" -tutorial.shaders.fragment.details: 래스터화는 삼각형이 포함하는 이미지 위치를 결정합니다. 덮인 영역 전체에 걸쳐 정점 색상이 보간되어 조각 셰이더가 처리하는 데이터인 조각(fragment)을 생성합니다. {fSMain}은 첫 번째 색상 어태치먼트를 식별하는 {sVTARGET}을 통해 이 보간된 색상을 반환합니다. -tutorial.shaders.fragment.guidance: 정점 색상 보간은 어태치먼트 블렌딩과 별개입니다. 블렌딩은 조각의 출력과 어태치먼트에 이미 저장된 색상을 결합합니다. 불투명 블렌드 상태는 해당 결합을 비활성화하므로 보간된 색상이 삼각형 내부의 배경을 대체합니다. -tutorial.shaders.fragment.title: 조각 색상 지정 -tutorial.shaders.guidance: "{vSInput}은 정점 셰이더가 정점 버퍼로부터 수신하는 내용을 설명합니다. 의미 체계 {pOSITION0} 및 {cOLOR0}이 입력을 식별합니다. C# 필드 이름만으로는 해당 매핑이 설정되지 않습니다." -tutorial.shaders.title: 두 셰이더 단계 작성 -tutorial.shaders.vertex.description: "정점 진입점을 {triangleSlang}에 추가합니다:" -tutorial.shaders.vertex.details: GPU는 각 입력 정점에 대해 이 진입점을 호출합니다. 위치에 동차 좌표 {w}를 추가하고 색상을 전달합니다. 정점 단계 후에 위치는 w로 나누어집니다. 여기서는 해당 나눗셈으로 x, y, z가 변경되지 않은 상태로 유지됩니다. 이것이 위에서 선택한 위치를 정규화된 장치 좌표로 직접 이해할 수 있는 이유입니다. -tutorial.shaders.vertex.title: 각 정점 위치 지정 -tutorial.surface.description: "컨텍스트는 출력을 표시할 위치도 알아야 합니다. {emphasis}에 다음을 추가합니다:" +tutorial.shaders.compilation.details: "{programCs}로 돌아와 정점 업로드 뒤, 렌더 콜백 앞에 셰이더 초기화를 추가합니다." +tutorial.shaders.compilation.guidance: "{zenithCompiler}는 {contextGraphicsApi}에 맞게 소스를 컴파일하고, {createShader}는 컴파일 결과의 설명으로 셰이더 객체를 만듭니다. 진입점 이름 {vSMain}과 {fSMain}은 Slang 파일에 정의한 두 함수를 선택합니다." +tutorial.shaders.compilation.title: "셰이더 컴파일" +tutorial.shaders.context: "{fSInput}은 두 셰이더 단계를 연결합니다. 정점 셰이더는 {sVPOSITION}에 클립 공간 위치를 기록하며, GPU는 이 위치를 이용해 삼각형에서 보이는 부분을 결정합니다. {cOLOR0} 필드는 정점 색상을 전달합니다. 이 색상은 삼각형 내부에서 보간된 뒤 프래그먼트 셰이더에 전달되므로 두 단계의 필드 형식과 시맨틱이 일치해야 합니다." +tutorial.shaders.description: "셰이더는 GPU에서 실행하는 프로그램입니다. 정점 셰이더는 각 정점의 위치를 정하고, 프래그먼트 셰이더는 이미지에서 도형이 덮는 각 위치의 색상을 정합니다. 두 단계를 하나의 Slang 파일에 작성하되, 실행을 시작하는 함수인 진입점은 단계별로 따로 둡니다." +tutorial.shaders.details: "{triangleSlang}을 만들고 다음 입력·출력 구조체를 작성합니다." +tutorial.shaders.fragment.description: "같은 파일에 프래그먼트 진입점을 추가합니다." +tutorial.shaders.fragment.details: "래스터화는 삼각형이 이미지의 어느 위치를 덮는지 결정하고 해당 위치에 프래그먼트를 생성합니다. 각 프래그먼트는 세 정점의 색상으로부터 보간된 색상을 받습니다. {fSMain}은 이 색상을 반환하고, {sVTARGET}은 결과를 첫 번째 색상 어태치먼트로 보냅니다." +tutorial.shaders.fragment.title: "프래그먼트 셰이더" +tutorial.shaders.guidance: "{vSInput}은 정점 셰이더의 입력을 정의합니다. {pOSITION0}과 {cOLOR0}이 시맨틱으로 속성을 식별하며, C# 필드 이름만으로는 이 대응 관계가 정해지지 않습니다." +tutorial.shaders.title: "셰이더 단계" +tutorial.shaders.vertex.description: "{triangleSlang}에 정점 진입점을 추가합니다." +tutorial.shaders.vertex.details: "GPU는 입력 정점마다 이 함수를 실행합니다. 함수는 네 번째 동차 좌표를 {w}로 설정하고 색상을 그대로 전달합니다. 정점 처리 후 위치를 w로 나누는데, 여기서는 1이므로 x, y, z가 그대로 유지되어 정규화 장치 좌표로 해석됩니다." +tutorial.shaders.vertex.title: "정점 셰이더" +tutorial.surface.description: "네이티브 표시 대상을 {emphasis}에 지정합니다." tutorial.surface.description.emphasis: "{windowCenter} 뒤, {windowRun} 앞" -tutorial.surface.details: "{surface}는 네이티브 프레젠테이션 대상 및 픽셀 크기를 설명합니다. 프레임버퍼는 윈도우와 연결된 픽셀 이미지입니다. {framebufferSize}는 픽셀 단위 크기를 제공합니다. 디스플레이 배율이 활성화된 경우 윈도우의 논리적 크기와 다를 수 있습니다." -tutorial.surface.guidance: 서피스는 위에서 선택한 백엔드와 일치합니다. Windows는 윈도우 핸들을 제공하고, Linux는 X11 디스플레이 및 윈도우를 제공하며, macOS 도우미는 연결된 Metal 레이어를 제공합니다. 이것이 윈도우를 렌더링에 연결하는 유일한 플랫폼별 부분입니다. -tutorial.surface.title: 네이티브 서피스 설명 -tutorial.swapChain.context: "스왑 체인은 컨텍스트와 네이티브 윈도우를 모두 사용합니다. {programCs} 하단의 {windowDispose} 줄을 다음 정리 순서로 바꿉니다:" -tutorial.swapChain.description: "서피스 설명을 사용하여 표시될 이미지를 생성합니다. 서피스 블록 바로 뒤에 다음을 추가합니다:" -tutorial.swapChain.details: "{swapChain}은 윈도우에 표시되는 이미지를 관리합니다. 각 프레임에서 {drawable}은 현재 이미지를 이미지 데이터용 API 형식인 {texture}로 제공합니다. 드로잉 후 {present}는 결과 표시를 요청하고 다음 drawable로 이동합니다." -tutorial.swapChain.guidance: "{b8G8R8A8UNorm}은 파란색, 녹색, 빨간색 및 알파 순서로 4개의 8비트 색상 채널을 저장합니다. {uNorm}은 0부터 255까지의 정수 값이 0부터 1까지의 값을 나타냄을 의미합니다. 셰이더는 여전히 논리적 RGBA 값을 반환하지만, 이 형식은 해당 채널이 이미지에 저장되는 방식을 결정합니다. 나중에 그래픽스 파이프라인은 {swapChainDescFormat}을 사용하여 이 어태치먼트와 일치시킵니다." -tutorial.swapChain.title: 스왑 체인 생성 +tutorial.surface.details: "프레임버퍼는 창에 표시할 픽셀 이미지입니다. {surface}는 네이티브 표시 대상과 크기를 설명하고 {framebufferSize}는 픽셀 단위 크기를 제공합니다. 화면 배율에 따라 창의 논리 크기와 다를 수 있습니다." +tutorial.surface.guidance: "서피스는 백엔드가 요구하는 네이티브 핸들을 제공합니다. Windows에서는 Win32 창, Linux에서는 X11 디스플레이와 창, macOS에서는 연결한 Metal 레이어를 사용합니다." +tutorial.surface.title: "네이티브 서피스" +tutorial.swapChain.context: "스왑 체인은 컨텍스트와 창 모두에 의존합니다. {programCs} 끝의 {windowDispose}를 다음 해제 순서로 바꿉니다." +tutorial.swapChain.description: "서피스 설명 바로 다음에 스왑 체인을 생성합니다." +tutorial.swapChain.details: "{swapChain}은 창에 표시할 이미지를 관리합니다. {drawable}은 현재 이미지를 API의 이미지 리소스인 {texture}로 제공합니다. 렌더링 후 {present}가 이미지 표시를 요청하고 다음 출력 텍스처로 넘어갑니다." +tutorial.swapChain.guidance: "{b8G8R8A8UNorm}은 파랑, 초록, 빨강, 알파 순서로 8비트 채널 네 개를 저장합니다. {uNorm}은 정수 0–255를 0–1에 대응시킵니다. 셰이더 출력은 논리적인 RGBA 값이며, 포맷은 메모리에 저장하는 방식을 정합니다. 파이프라인의 색상 포맷은 {swapChainDescFormat}을 사용해 어태치먼트와 맞춥니다." +tutorial.swapChain.title: "스왑 체인" tutorial.title: 첫 번째 삼각형 -tutorial.troubleshooting.description: "먼저 콘솔에서 오류를 읽은 다음 이전 체크포인트를 사용하여 실패한 단계를 식별하세요:" -tutorial.troubleshooting.details: "{link} 및 {detail}를 사용하여 정점 데이터, 입력 레이아웃 및 드로잉 작업을 비교하세요. 해당 샘플은 윈도우 처리 및 제출을 공유 호스트에 배치하지만, 이 튜토리얼은 애플리케이션 흐름을 {programCs}에 유지합니다. 인덱스 드로잉, 변환 및 깊이 테스트를 배우려면 {context}로 계속 진행하세요." +tutorial.troubleshooting.description: "콘솔 진단과 세 단계의 결과를 이용해 문제가 생긴 지점을 찾습니다." +tutorial.troubleshooting.details: "{link}와 {detail}에서 정점 데이터, 입력 레이아웃, 그리기를 확인할 수 있습니다. 예제는 창과 제출을 공통 호스트로 분리하지만, 이 튜토리얼은 전체 흐름을 {programCs}에 둡니다. {context}에서는 인덱스 그리기, 변환, 깊이 테스트를 소개합니다." tutorial.troubleshooting.details.context: 회전하는 큐브 tutorial.troubleshooting.details.detail: Slang 셰이더 -tutorial.troubleshooting.details.link: 샘플 렌더러 +tutorial.troubleshooting.details.link: "예제 렌더러" tutorial.troubleshooting.table.backend.check: 선택한 백엔드가 장치 및 설치된 그래픽 드라이버에서 지원되는지 확인합니다. tutorial.troubleshooting.table.backend.symptom: 백엔드 생성 실패 -tutorial.troubleshooting.table.drawing.check: 업로드 크기, 입력 레이아웃, 파이프라인 선택 및 렌더 패스 내부의 드로잉 명령 배치를 확인합니다. +tutorial.troubleshooting.table.drawing.check: "업로드 크기, 입력 레이아웃, 파이프라인 선택 및 렌더 패스 내부의 그리기 명령 배치를 확인합니다." tutorial.troubleshooting.table.drawing.symptom: 배경은 나타나지만 삼각형은 나타나지 않음 tutorial.troubleshooting.table.headings.check: 확인 사항 tutorial.troubleshooting.table.headings.symptom: 증상 -tutorial.troubleshooting.table.input.check: "28바이트 스트라이드와 0 및 12의 위치/색상 오프셋을 확인합니다." +tutorial.troubleshooting.table.input.check: "스트라이드가 28바이트이고 위치와 색상의 오프셋이 각각 0과 12바이트인지 확인합니다." tutorial.troubleshooting.table.input.symptom: 정점 위치 또는 색상이 손상됨 tutorial.troubleshooting.table.shaders.check: 복사된 {triangleSlang}, 진입점 철자 및 컴파일러에서 보고된 진단을 확인합니다. -tutorial.troubleshooting.table.shaders.symptom: 클리어 색상 단계는 작동하지만 셰이더 로드에 실패함 -tutorial.troubleshooting.table.window.check: .NET 프로젝트가 빌드되고 윈도우 전용 단계가 데스크톱 세션에서 실행되는지 확인합니다. Linux의 경우 X11 또는 XWayland를 사용할 수 있는지 확인합니다. -tutorial.troubleshooting.table.window.symptom: 윈도우가 열리지 않음 -tutorial.troubleshooting.title: 실패한 단계 확인 -tutorial.window.context: "{usingZenithTutorials}는 도우미의 네임스페이스를 가져옵니다. 각 C# 파일은 고유한 일반 using 지시문을 사용하므로 상호 운용성 가져오기는 두 파일 모두에 필요합니다. 별칭 {buffer}는 Zenith.NET 버퍼 형식을 나타내며 {systemBuffer}와 구별합니다." -tutorial.window.description: "{cocoaHelperCs}를 네임스페이스를 유지한 상태로 프로젝트에 추가합니다. 해당 파일의 맨 위, 네임스페이스 선언 앞에 {interopUsing}을 추가합니다. 도우미는 macOS에서 윈도우에 Metal 레이어를 연결하며, 다른 플랫폼 분기에서는 이를 호출하지 않습니다." -tutorial.window.details: "생성된 {programCs}를 다음 코드로 교체합니다. 명시적인 {main} 메서드 없이 순서대로 실행되는 최상위 문을 사용합니다. 이후 섹션에서 이 동일한 파일에 코드를 추가할 위치를 안내합니다:" -tutorial.window.guidance: "{graphicsAPINone}은 Silk.NET에 자체 그래픽스 컨텍스트가 없는 윈도우를 생성하도록 요청합니다. 해당 컨텍스트는 Zenith.NET으로 생성합니다. {initialize}는 네이티브 윈도우를 생성하고 핸들을 사용할 수 있게 합니다. 핸들은 윈도우 시스템에서 제공하는 식별자입니다. {center}는 윈도우를 화면 중앙에 배치하고, {run}은 윈도우가 닫힐 때까지 이벤트를 처리합니다. 그런 다음 실행은 윈도우를 해제하는 {dispose}로 계속됩니다." -tutorial.window.notes: "{dotnetRun}을 실행합니다. 빈 윈도우가 열리고 이동, 크기 조정 및 닫기에 응답해야 합니다. 렌더링 명령을 아직 제출하지 않았으므로 해당 내용은 아직 정의되지 않았습니다. 계속하기 전에 닫으세요." -tutorial.window.title: 윈도우 열기 +tutorial.troubleshooting.table.shaders.symptom: "배경색은 표시되지만 셰이더를 불러오지 못함" +tutorial.troubleshooting.table.window.check: ".NET 프로젝트가 빌드되고 창 전용 단계가 데스크톱 세션에서 실행되는지 확인합니다. Linux의 경우 X11 또는 XWayland를 사용할 수 있는지 확인합니다." +tutorial.troubleshooting.table.window.symptom: "창이 열리지 않음" +tutorial.troubleshooting.title: "문제 진단" +tutorial.window.description: "{cocoaHelperCs}를 다운로드해 프로젝트에 추가합니다. 이 보조 클래스는 macOS 창에 Metal 레이어를 연결합니다." +tutorial.window.details: "자동 생성된 {programCs} 내용을 다음 코드로 바꿉니다. 최상위 문을 사용하므로 {main} 메서드를 직접 작성하지 않아도 위에서 아래로 실행됩니다. 이후 각 절에서 새 코드를 넣을 위치를 안내합니다." +tutorial.window.guidance: "{graphicsAPINone}은 그래픽스 컨텍스트 생성을 Zenith.NET에 맡깁니다. {initialize}는 네이티브 창을 만들고 창 시스템 핸들을 사용할 수 있게 합니다. {center}는 창을 화면 가운데 놓습니다. {run}이 창을 닫을 때까지 이벤트를 처리한 뒤 {dispose}가 실행되어 창을 해제합니다." +tutorial.window.notes: "애플리케이션을 빌드하고 실행합니다. 창을 열고 닫을 수 있는지, 이동하거나 크기를 바꿀 수 있는지 확인합니다. 아직 렌더링 명령을 제출하지 않아 창 내부의 내용은 정의되지 않았습니다. 다음 단계로 넘어가기 전에 창을 닫습니다." +tutorial.window.title: "창 생성" ui.action.copy: 복사 ui.action.navigate: 탐색 ui.action.open: 열기 @@ -542,7 +530,7 @@ ui.content.tutorial: 튜토리얼 ui.contents.close: 목차 닫기 ui.contents.open: 목차 열기 ui.contents.title: 목차 -ui.footer.caption: .NET을 위한 모던 RHI. +ui.footer.caption: ".NET을 위한 현대적인 RHI" ui.footer.label: 바닥글 ui.language.label: 언어 ui.language.unavailable: 번역되지 않음 diff --git a/documents/locales/ko-KR/translation.md b/documents/locales/ko-KR/translation.md index 4ac951a0..9bdb1a42 100644 --- a/documents/locales/ko-KR/translation.md +++ b/documents/locales/ko-KR/translation.md @@ -8,6 +8,16 @@ 번역 시에는 이 언어의 `strings.yml` 값만 수정합니다. 키 집합은 영문과 정확히 같아야 합니다. 문구가 같아 보이거나 아직 화면에서 보지 못한 키도 임의로 추가, 삭제하거나 이름을 바꾸지 않습니다. 원문에 문제가 있으면 해당 키와 문제를 유지 관리자에게 알립니다. 영문과 공유 페이지를 먼저 수정한 다음 번역에 반영합니다. +## 문체와 문맥 + +기술 교재에 맞게 정확하고 차분하며 이해하기 쉬운 문장으로 씁니다. 작업 사이의 관계를 먼저 설명하고 조건과 제약을 이어서 제시합니다. 튜토리얼은 구체적인 절차와 확인 가능한 결과를 유지합니다. 학술적 정확성을 위해 수동태나 긴 문장을 늘릴 필요는 없습니다. + +기사는 앞뒤 문단, 표, 코드와 함께 읽는 순서대로 검토합니다. 리소스 키는 저장 경계일 뿐 독립된 번역 단위가 아닙니다. 링크와 강조 구절을 완성된 문장에 넣고 조사와 문장 연결을 확인합니다. + +제목, UI 레이블, 홈페이지의 짧은 소개와 바닥글 문구에는 마침표를 붙이지 않습니다. 본문, 진단, 접근성 안내는 정상적인 문장 부호를 유지합니다. 개념마다 통용되는 용어 하나를 일관되게 쓰고 일부 용어에만 영어를 괄호로 덧붙이지 않습니다. API, 파일, 실제 설정 항목의 식별자는 유지합니다. + +문장을 남길지는 현재 작업, 설계 선택, 확인 가능한 결과, 올바른 사용 조건을 설명하는지로 판단합니다. 사용하지 않는 기능 목록, 막연한 환경 주의사항, 반복된 전제는 덜어 냅니다. 제목과 스타일로 나뉜 구절도 하나로 번역해 한국어 어순을 따릅니다. 홈페이지 제목의 `{accent}`와 `{lineBreak}`는 옮길 수 있으며 강조와 줄바꿈이 영어 어순을 강제해서는 안 됩니다. 문단을 삭제할 때는 유지 관리자가 영어 원문, 공통 바인딩, 모든 언어의 키를 함께 정리합니다. + ## 텍스트와 자리 표시자 문장이나 문단 전체를 명확하고 자연스러운 한국어로 번역합니다. 전제 조건, 부정 표현, 단위, 작업 순서 및 수명 제약을 유지합니다. 원문에 없는 기술적 보장, 플랫폼 요구 사항, 패키지 버전 또는 릴리스 설명을 추가하지 않습니다. 제품명, 패키지명, 파일명과 C# 및 Slang 식별자는 대소문자까지 그대로 유지합니다. diff --git a/documents/locales/pt-BR/strings.yml b/documents/locales/pt-BR/strings.yml index 9309f2f9..93ac29ae 100644 --- a/documents/locales/pt-BR/strings.yml +++ b/documents/locales/pt-BR/strings.yml @@ -1,604 +1,592 @@ ### YamlMime:Resources -concepts.execution.context.description: Um {graphicsContext} representa um dispositivo de backend e fornece suas filas de gráficos, computação e transferência. Crie os buffers, texturas, shaders e pipelines para uma carga de trabalho por meio do mesmo contexto. Um recurso ou handle criado por outro contexto não pode ser simplesmente vinculado aos buffers de comandos deste. -concepts.execution.context.details: Escolha o backend para a plataforma e a superfície de apresentação. A API permanece compartilhada, mas o suporte ao dispositivo ainda é importante. {capabilities} expõe o nome do dispositivo e os sinalizadores {rayTracingSupported} e {meshShadingSupported}. Verifique o sinalizador correspondente antes de criar uma carga de trabalho opcional, como fazem os exemplos {link} e {detail}. Esses sinalizadores não são uma lista completa de restrições de formato, memória ou plataforma. -concepts.execution.context.details.detail: sombreamento de malhas -concepts.execution.context.details.link: traçado de raios -concepts.execution.context.title: O contexto conecta recursos e filas -concepts.execution.description: Uma aplicação Zenith.NET cria recursos de GPU, grava comandos que os utilizam e envia esses comandos para uma fila. A CPU pode continuar enquanto a GPU executa o envio. Mantenha os recursos válidos até que esse trabalho seja concluído, mesmo após as chamadas de gravação terem retornado. -concepts.execution.ownership.description: "Aqui, propriedade significa responsabilidade de descarte. Uma referência C# mantém um objeto gerenciado acessível; ela não impede que um {dispose} explícito destrua o recurso nativo. Da mesma forma, enviar um comando que usa um buffer não transfere a propriedade desse buffer para a fila." -concepts.execution.ownership.details: No desligamento, pare de enviar novos trabalhos, aguarde os últimos usos em cada fila envolvida, libere os recursos da aplicação e, em seguida, descarte o contexto. O descarte do contexto libera suas próprias filas e auxiliares internos; ele não espera todo o trabalho da aplicação nem descarta todos os recursos criados por ela. -concepts.execution.ownership.guidance: Aplique as mesmas regras de tempo de vida durante a renderização. Guarde o valor de conclusão do último uso de um recurso para saber quando seus bytes podem ser sobrescritos ou quando o recurso pode ser substituído. Consulte {link} para visualizações e tempos de vida de recursos de suporte. -concepts.execution.ownership.guidance.link: Gerenciamento de recursos -concepts.execution.ownership.table.applicationResources.object: Recursos criados pela aplicação -concepts.execution.ownership.table.applicationResources.ownership: A aplicação os descarta após seu último uso na GPU. -concepts.execution.ownership.table.commandBuffers.object: Buffers de comandos emprestados -concepts.execution.ownership.table.commandBuffers.ownership: A fila os gerencia e recicla. -concepts.execution.ownership.table.headings.object: Objeto -concepts.execution.ownership.table.headings.ownership: Quem o libera? -concepts.execution.ownership.table.queues.object: Filas do contexto e suas linhas do tempo -concepts.execution.ownership.table.queues.ownership: O contexto e as filas os gerenciam. -concepts.execution.ownership.table.swapChainDrawable.ownership: A cadeia de troca o gerencia. -concepts.execution.ownership.title: Manter a propriedade separada da conclusão na GPU -concepts.execution.pipelines.description: Uma pipeline gráfica combina shaders, o layout de entrada de vértices, a regra para montar vértices em primitivas, formatos de anexo e estado de renderização. Defina-a antes de vincular dados de vértices, índices ou constantes e emitir comandos de desenho. Seus formatos de anexo e contagem de amostras devem corresponder aos anexos da passagem de renderização. -concepts.execution.pipelines.details: Uma pipeline de computação fornece o ponto de entrada do shader para um dispatch, que inicializa grupos de threads de GPU. Defina-a e defina suas constantes antes do dispatch. Dispatches de computação pertencem ao exterior das passagens de renderização gráfica. Mudar a pipeline é uma mudança em como os comandos subsequentes interpretam suas entradas; vincule os dados necessários para a pipeline selecionada antes de usá-la. -concepts.execution.pipelines.guidance: O {link} mostra a sequência gráfica completa. O {detail} grava um dispatch seguido por uma passagem gráfica que exibe o resultado. -concepts.execution.pipelines.guidance.detail: exemplo de computação -concepts.execution.pipelines.guidance.link: callback de renderização do triângulo -concepts.execution.pipelines.title: Uma pipeline determina como os comandos interpretam os dados -concepts.execution.queues.description: Comece com {graphicsQueue} quando um quadro combinar desenho, computação e cópias. Manter o trabalho dependente em uma única fila torna sua ordenação mais fácil de acompanhar. -concepts.execution.queues.details: Uma fila aceita lotes de comandos para execução. Filas separadas não correspondem necessariamente a mecanismos de hardware separados, portanto seus trabalhos podem não ser executados simultaneamente. Use outra fila quando a carga de trabalho puder se beneficiar da sobreposição e adicione uma dependência explícita quando uma fila consumir os resultados de outra fila. -concepts.execution.queues.guidance: Quando comandos posteriores dependem de gravações anteriores, a aplicação também deve garantir que essas gravações estejam disponíveis para os comandos posteriores. Enviar ambos os buffers de comandos para a mesma fila não estabelece automaticamente todas as dependências desse tipo. Comandos podem usar diferentes estágios de GPU, e acessos posteriores podem precisar de uma barreira ou transição de textura. {link} explica a distinção entre ordem de envio e visibilidade de recursos. -concepts.execution.queues.guidance.link: Sincronização -concepts.execution.queues.table.computeQueue.workToRecord: Dispatches de computação e trabalho de transferência compatível, sem passagens de renderização gráfica. -concepts.execution.queues.table.graphicsQueue.workToRecord: Passagens de renderização e desenho, além de operações de computação e transferência usadas pelo quadro. -concepts.execution.queues.table.headings.queue: Fila -concepts.execution.queues.table.headings.workToRecord: Trabalho a gravar -concepts.execution.queues.table.transferQueue.workToRecord: Trabalho de envio, download e cópia, sem desenho ou dispatches de computação. -concepts.execution.queues.title: Escolher uma fila para o trabalho que ela executará -concepts.execution.recording.context: A fila faz a sondagem de conclusão e recicla buffers de comandos finalizados. Chame {queueCommandBuffer} para cada nova gravação; ele pode retornar uma instância reciclada. Não descarte um buffer de comandos emprestado, não o envie duas vezes nem continue gravando nele após o envio. Grave um determinado buffer de comandos a partir de uma única thread por vez; o bloqueio interno da fila não protege contra edições simultâneas em um buffer de comandos. -concepts.execution.recording.description: "{queueCommandBuffer} retorna um {commandBuffer} com a gravação já iniciada. Grave os comandos e suas dependências, depois chame {submit} uma vez. O envio encerra a gravação e retorna um {timelineValue} identificando um ponto de conclusão nessa fila." -concepts.execution.recording.details: "Por exemplo, após gravar um quadro em {commandBuffer}, o triângulo o envia e aguarda a conclusão com:" -concepts.execution.recording.guidance: "{submit} agenda o trabalho; {wait} impede que a CPU continue até que esse envio seja concluído. Gravar um desenho, encerrar uma passagem de renderização e enviar um buffer de comandos são operações separadas. Nem gravar o desenho nem encerrar a passagem aguardam a GPU." -concepts.execution.recording.title: A gravação não executa comandos -concepts.execution.title: Modelo de execução -concepts.platforms.description: Escolha se sua aplicação possui a janela nativa e o loop de quadros ou se utiliza um controle de renderização de interface. Essa escolha determina quem obtém a textura de saída, envia comandos e apresenta o resultado. A textura de saída é a textura usada como saída do quadro atual. Tarefas gráficas e de computação fora da tela não precisam de janela ou cadeia de troca. -concepts.platforms.frame.context: Adicione suas vinculações de pipeline e comandos de desenho dentro dessa passagem. Encerre a passagem antes de retornar. Não envie o buffer de comandos fornecido nem apresente de forma independente, e não descarte o buffer de comandos ou a textura de saída. Se o seu manipulador usar a textura de saída em outro layout, retorne-a para {colorAttachment} para a transição final do controle. -concepts.platforms.frame.description: As integrações implementam {iZenithView}. A aplicação fornece seu {graphicsContext}, atualiza dados de cena em {updateRequested} e grava a renderização em {renderRequested} usando {renderEventArgs}. -concepts.platforms.frame.details: "O controle gerencia o ciclo completo de cada quadro. Ele obtém a textura de saída e o buffer de comandos, faz a transição da textura para {colorAttachment}, chama os manipuladores e executa o envio e a apresentação exigidos pelo framework." -concepts.platforms.frame.guidance: "Para uma {iZenithView} inicializada chamada {view}, com um contexto atribuído, este manipulador grava uma passagem de limpeza completa. Requer {usingZenithNET}:" -concepts.platforms.frame.notes: Os controles transitam de {undefined} no início de cada quadro, portanto as aplicações não podem confiar na preservação do conteúdo anterior da textura de saída. Limpe ou renderize a imagem necessária a cada quadro. Mantenha acumulação persistente ou renderização em cache em uma textura de propriedade da aplicação e, em seguida, exiba essa textura por meio da visualização. -concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat} fornece o formato de cor padrão das integrações. Verifique a textura de saída real do evento ao fazer a correspondência de formatos de anexos, contagens de amostras e dimensões." -concepts.platforms.frame.title: Gravar no quadro fornecido por um controle de interface -concepts.platforms.integration.context: WinForms, WPF e o caminho WinUI do Windows exigem Windows. Aplicações MAUI precisam da carga de trabalho de sua plataforma de destino e devem registrar o manipulador de controle com {useZenithView}; consulte {extensionsCs}. O suporte ao framework e o suporte ao backend devem ser atendidos. -concepts.platforms.integration.description: "Os controles compartilham a interface de eventos, mas nem todos apresentam da mesma maneira:" -concepts.platforms.integration.details: A leitura de bitmap (bitmap readback) copia os pixels renderizados para a memória da CPU antes que a interface os exiba. A interoperabilidade por textura compartilhada evita essa leitura, mas ainda pode exigir cópias e sincronização na GPU. A interface compartilhada {renderRequested}, portanto, não implica custos de apresentação idênticos ou requisitos de interoperabilidade nativa idênticos. -concepts.platforms.integration.guidance: "Use o pacote para o framework da aplicação; por exemplo:" -concepts.platforms.integration.table.avalonia.integration: Avalonia -concepts.platforms.integration.table.avalonia.presentation: Renderiza em uma textura e faz download dos pixels em um {writeableBitmap}. Consulte {zenithViewCs} e {surfaceCs}. -concepts.platforms.integration.table.headings.integration: Integração -concepts.platforms.integration.table.headings.presentation: Como sua imagem chega à interface -concepts.platforms.integration.table.maui.integration: .NET MAUI -concepts.platforms.integration.table.maui.presentation: Usa superfícies nativas no Android, iOS e Mac Catalyst, e composição de textura compartilhada no Windows. Consulte as {link}. -concepts.platforms.integration.table.maui.presentation.link: implementações de plataforma -concepts.platforms.integration.table.uno.integration: Caminho Uno -concepts.platforms.integration.table.uno.presentation: Faz download dos pixels em um {writeableBitmap}. Consulte {zenithViewUnoCs}. -concepts.platforms.integration.table.winForms.integration: WinForms -concepts.platforms.integration.table.winForms.presentation: Cria uma cadeia de troca do Zenith.NET para o {hWND} do controle. Consulte {zenithViewCs}. -concepts.platforms.integration.table.winUI.integration: WinUI no Windows -concepts.platforms.integration.table.winUI.presentation: Renderiza em uma textura Direct3D 11 compartilhada importada e depois copia para uma cadeia de troca de composição conectada a {swapChainPanel}. Consulte {zenithViewWinUICs}. -concepts.platforms.integration.table.wpf.integration: WPF -concepts.platforms.integration.table.wpf.presentation: Importa uma textura Direct3D 11 compartilhada e depois copia por meio da interoperabilidade Direct3D para uma superfície exibida por {d3DImage}. Consulte {surfaceCs}. -concepts.platforms.integration.title: Escolher o caminho de apresentação bem como o framework -concepts.platforms.lifecycle.context: Para uma visualização de interface, use {descWidth}, {descHeight}, {descFormat} e {descSampleCount} da textura de saída do evento ao criar recursos de renderização correspondentes. O controle determina a resolução dessa textura de saída; não presuma que suas dimensões lógicas ou escala de tela sejam sempre iguais às dimensões da textura. -concepts.platforms.lifecycle.description: Para uma cadeia de troca nativa, passe as dimensões do framebuffer em pixels. Os tamanhos de janela expressos em unidades lógicas podem ser diferentes quando o dimensionamento de tela está ativado. Ignore framebuffers de tamanho zero, redimensione a cadeia de troca quando o tamanho em pixels mudar e obtenha {swapChainDrawable} para cada quadro. A textura de saída pertence à cadeia de troca e pode mudar após a apresentação ou o redimensionamento. -concepts.platforms.lifecycle.details: "{swapChainResize} altera as dimensões da superfície existente. {swapChainRefresh} substitui a descrição da superfície, incluindo seus handles nativos. Antes de qualquer operação, conclua os usos pendentes dos recursos afetados. Descarte a cadeia de troca antes de destruir seu destino de apresentação nativo." -concepts.platforms.lifecycle.guidance: Recrie texturas de profundidade ou fora da tela de propriedade da aplicação cujo tamanho segue a janela e atualize constantes contendo seus handles. Uma pipeline pode permanecer em uso durante uma mudança de tamanho quando seus formatos de anexos e contagem de amostras permanecerem compatíveis. O {link} mantém sua pipeline enquanto substitui sua textura de profundidade. -concepts.platforms.lifecycle.guidance.link: renderizador de cubo giratório -concepts.platforms.lifecycle.title: Manter o tamanho e o tempo de vida da textura de saída com seu host -concepts.platforms.ownership.description: A aplicação é proprietária do contexto que atribui e dos recursos que cria para renderização. O controle é proprietário de seus próprios recursos de apresentação. Alterar a propriedade {graphicsContext} da visualização faz com que o agendador recrie os recursos do controle; isso não recria as pipelines, buffers ou texturas da aplicação para o novo contexto. -concepts.platforms.ownership.details: Coordene a substituição de recursos com o ciclo de vida do quadro da visualização. Interrompa a atividade de quadros da visualização e conclua os usos pendentes da GPU antes de descartar recursos da aplicação ou o contexto atribuído. Remover uma visualização não transfere a propriedade do contexto para o controle. -concepts.platforms.ownership.guidance: O {frameSchedulerCs} compartilhado distribui o trabalho de quadros por meio do despachante de interface da visualização. Mantenha os manipuladores de quadro focados na atualização e gravação do quadro; trabalho prolongado da CPU ali também atrasa a interface. -concepts.platforms.ownership.title: Manter os recursos da aplicação fora da propriedade do controle -concepts.platforms.surface.context: Uma biblioteca de janelas ou framework de interface suportar um sistema operacional não garante que o backend de GPU selecionado esteja disponível nele. Recursos de dispositivo, drivers e suporte a superfícies nativas ainda devem corresponder. Verifique o traçado de raios e o sombreamento de malhas opcionais por meio de {contextCapabilities} antes de criar essas cargas de trabalho. -concepts.platforms.surface.description: O {link} usa o Silk.NET para criar uma janela e processar eventos. O Zenith.NET se conecta a essa janela por meio de uma descrição de {surface} e uma {swapChain}. Uma superfície contém handles e dimensões nativas; construir a descrição não cria nem possui a janela do sistema operacional. -concepts.platforms.surface.description.link: triângulo -concepts.platforms.surface.details: "O handle deve corresponder ao backend selecionado:" -concepts.platforms.surface.guidance: O arquivo {appCs} do tutorial mostra as opções do Windows, macOS e X11. Seu host Linux fornece handles Xlib; usá-lo em uma sessão Wayland requer o XWayland. Uma aplicação nativa Wayland forneceria handles diferentes por meio de {surfaceWayland}. -concepts.platforms.surface.table.android.backend: Vulkan no Android. -concepts.platforms.surface.table.apple.backend: Metal nas plataformas Apple. -concepts.platforms.surface.table.headings.backend: Caminho do backend -concepts.platforms.surface.table.headings.factory: Fábrica de superfícies -concepts.platforms.surface.table.headings.handles: Handles fornecidos pelo host -concepts.platforms.surface.table.wayland.backend: Vulkan com um host nativo Wayland. -concepts.platforms.surface.table.wayland.handles: Display e superfície Wayland -concepts.platforms.surface.table.win32.backend: DirectX 12 ou Vulkan no Windows. -concepts.platforms.surface.table.xlib.backend: Vulkan no Linux com X11 ou XWayland. -concepts.platforms.surface.table.xlib.handles: Display e janela X11 -concepts.platforms.surface.title: Fornecer uma superfície nativa quando a aplicação possui a apresentação -concepts.platforms.title: Integração de plataforma -concepts.resources.allocation.context: "Comece com recursos criados pelo contexto, a menos que precise de um alocador próprio. Ao usar um heap, aguarde a conclusão de todo o trabalho de GPU que usa seus recursos; depois libere os recursos posicionados e, por último, o próprio heap." -concepts.resources.allocation.description: "Um {heap} fornece memória na qual você posiciona recursos em deslocamentos explícitos em bytes. A aplicação escolhe esses deslocamentos e acompanha quais regiões estão em uso." -concepts.resources.allocation.details: "Antes de posicionar um recurso, use {contextGetSizeAndAlignment} com sua descrição exata de buffer ou textura. Escolha um deslocamento múltiplo do alinhamento retornado, reserve o tamanho retornado e mantenha o recurso dentro do tamanho total do heap. Alocações ainda em uso não devem se sobrepor. O armazenamento de texturas pode incluir preenchimento e alinhamento específicos do backend; multiplicar a quantidade de pixels pelos bytes por pixel não calcula o tamanho da alocação." -concepts.resources.allocation.guidance: "Para buffers posicionados, mantenha a residência do buffer consistente com a do heap. Use heaps exclusivos de GPU para as texturas de GPU comuns descritas aqui. Tamanho e alinhamento são requisitos de posicionamento, não uma garantia de que qualquer recurso possa ser colocado em qualquer heap em todos os backends." -concepts.resources.allocation.title: Posicionar recursos em um heap quando o controle de alocação for necessário -concepts.resources.bufferUsages.table.constant.role: Parâmetros de shader lidos por meio de uma vinculação de buffer de constantes. +concepts.execution.context.description: "Um {graphicsContext} conecta a aplicação a um dispositivo GPU por meio de um backend específico e fornece suas filas gráfica, de computação e de transferência. Recursos usados em conjunto devem pertencer ao mesmo contexto; buffers, texturas, shaders, pipelines e seus identificadores não podem ser vinculados entre contextos diferentes." +concepts.execution.context.details: "{capabilities} informa o nome do dispositivo e as funcionalidades disponíveis. Consulte {rayTracingSupported} e {meshShadingSupported} antes de criar os recursos necessários a essas operações. Os exemplos de {link} e {detail} fazem essas verificações durante a inicialização." +concepts.execution.context.details.detail: "sombreamento de malha" +concepts.execution.context.details.link: "traçado de raios" +concepts.execution.context.title: "Contexto gráfico" +concepts.execution.description: "O trabalho da GPU é preparado na CPU: a aplicação cria recursos, registra comandos que os utilizam e envia esses comandos a uma fila. Após o envio, a CPU pode continuar enquanto a GPU executa o trabalho. Os recursos precisam permanecer disponíveis até o fim dessa execução." +concepts.execution.ownership.description: "A propriedade define quem libera um objeto; a conclusão do trabalho na GPU determina quando isso pode ocorrer. Chamar {dispose} libera os recursos nativos mesmo que ainda existam referências C# ao objeto. Enviar comandos não transfere à fila a propriedade dos recursos utilizados." +concepts.execution.ownership.details: "Ao encerrar a aplicação, pare de enviar trabalho e espere o último uso dos recursos em cada fila envolvida. Depois, libere os recursos da aplicação e o contexto. O contexto libera suas filas e estruturas auxiliares internas, portanto essa última etapa deve ocorrer após a conclusão de todo o trabalho da aplicação." +concepts.execution.ownership.guidance: "Durante a renderização, acompanhe a conclusão do trabalho que utiliza dados a serem sobrescritos ou recursos a serem substituídos. Espere esses usos terminarem antes de modificar ou liberar o armazenamento afetado. {link} explica como esse modelo de tempo de vida se aplica às visualizações e aos recursos que as sustentam." +concepts.execution.ownership.guidance.link: "Gerenciamento de recursos" +concepts.execution.ownership.table.applicationResources.object: "Recursos criados pela aplicação" +concepts.execution.ownership.table.applicationResources.ownership: "A aplicação os libera após o último uso na GPU." +concepts.execution.ownership.table.commandBuffers.object: "Buffers de comandos emprestados" +concepts.execution.ownership.table.commandBuffers.ownership: "A fila os gerencia e recicla." +concepts.execution.ownership.table.headings.object: "Objeto" +concepts.execution.ownership.table.headings.ownership: "Responsabilidade pela liberação" +concepts.execution.ownership.table.queues.object: "Filas do contexto e suas linhas do tempo" +concepts.execution.ownership.table.queues.ownership: "O contexto e as filas as gerenciam." +concepts.execution.ownership.table.swapChainDrawable.ownership: "A cadeia de troca o gerencia." +concepts.execution.ownership.title: "Responsabilidade e tempo de vida" +concepts.execution.pipelines.description: "Um pipeline gráfico define os shaders, a disposição dos atributos de vértice, a montagem de primitivas, os formatos dos anexos e o estado usado nas operações de desenho. Selecione o pipeline antes de vincular dados de vértices, índices ou constantes. Os formatos dos anexos e a quantidade de amostras devem corresponder aos da passagem de renderização." +concepts.execution.pipelines.details: "Um pipeline de computação seleciona o ponto de entrada do shader executado por um despacho. Vincule o pipeline e suas constantes antes do despacho, fora de uma passagem de renderização gráfica." +concepts.execution.pipelines.guidance: "O {link} apresenta a sequência gráfica. O {detail} acrescenta um despacho de computação antes da passagem que exibe seu resultado." +concepts.execution.pipelines.guidance.detail: "exemplo de computação" +concepts.execution.pipelines.guidance.link: "callback de renderização do triângulo" +concepts.execution.pipelines.title: "Estado do pipeline" +concepts.execution.queues.description: "A {graphicsQueue} costuma ser o ponto de partida para um quadro com desenho, computação e cópias. Manter operações dependentes na mesma fila simplifica a ordenação." +concepts.execution.queues.details: "Filas distintas permitem enviar cargas de trabalho independentes separadamente, mas nem sempre correspondem a mecanismos de hardware independentes. Use filas adicionais quando houver benefício em sobrepor a execução. Se uma fila utilizar dados produzidos por outra, estabeleça uma dependência explícita entre seus envios." +concepts.execution.queues.guidance: "Dentro de uma fila, operações dependentes também podem precisar de barreiras ou transições de textura para que os acessos posteriores vejam as escritas anteriores. Essas dependências de memória são diferentes da ordem de envio; {link} explica como expressá-las." +concepts.execution.queues.guidance.link: "Sincronização" +concepts.execution.queues.table.computeQueue.workToRecord: "Despachos de computação e trabalho de transferência compatível, sem passagens de renderização gráfica." +concepts.execution.queues.table.graphicsQueue.workToRecord: "Passagens de renderização, desenho, computação e transferências." +concepts.execution.queues.table.headings.queue: "Fila" +concepts.execution.queues.table.headings.workToRecord: "Operações aceitas" +concepts.execution.queues.table.transferQueue.workToRecord: "Uploads, downloads e cópias, sem desenho ou despachos de computação." +concepts.execution.queues.title: "Seleção de filas" +concepts.execution.recording.context: "A fila recupera os buffers de comandos concluídos para reutilizá-los. Obtenha um com {queueCommandBuffer} para cada registro de comandos, use uma thread por vez e envie-o uma única vez. Após o envio, deixe seu gerenciamento com a fila: não o modifique, envie novamente ou libere." +concepts.execution.recording.description: "{queueCommandBuffer} retorna um {commandBuffer} já em gravação. Registre as operações e suas dependências e chame {submit} uma vez. O envio encerra a gravação e retorna um {timelineValue}, que identifica o ponto de conclusão naquela fila." +concepts.execution.recording.details: "Após registrar o quadro em {commandBuffer}, o tutorial do triângulo envia os comandos e aguarda a conclusão:" +concepts.execution.recording.guidance: "O registro monta a sequência de comandos; {submit} agenda sua execução. A chamada seguinte a {wait} bloqueia a thread da CPU até esse envio terminar. Isso facilita a compreensão do loop do tutorial, pois cada quadro termina antes do início do próximo." +concepts.execution.recording.title: "Gravação e envio" +concepts.execution.title: "Modelo de execução" +concepts.platforms.description: "A apresentação pode ser gerenciada pela aplicação ou por um controle de interface. Essa escolha define quem obtém a textura de saída do quadro, registra e envia os comandos e apresenta o resultado. Essa textura de saída é o drawable." +concepts.platforms.frame.context: "Registre as vinculações de pipeline e os comandos de desenho dentro da passagem e encerre-a antes de o manipulador retornar. O controle envia os comandos e apresenta o resultado. O manipulador não deve enviar o buffer de comandos nem liberar qualquer um dos objetos recebidos. Se alterar o layout da textura de saída, restaure {colorAttachment} antes de retornar para que o controle realize a transição final." +concepts.platforms.frame.description: "Os controles implementam {iZenithView}. A aplicação atribui {graphicsContext}, atualiza a cena em {updateRequested} e registra comandos em {renderRequested} usando o {renderEventArgs} recebido." +concepts.platforms.frame.details: "A cada quadro, o controle obtém uma textura de saída e um buffer de comandos, faz a transição da textura para {colorAttachment} e chama os manipuladores de atualização e renderização. Depois, envia o trabalho registrado e apresenta a imagem pelo mecanismo do framework." +concepts.platforms.frame.guidance: "Adicione {usingZenithNET} ao arquivo. Para uma instância de {iZenithView} chamada {view}, já inicializada e com um contexto gráfico atribuído, registre este manipulador para limpar sua textura de saída:" +concepts.platforms.frame.notes: "A transição inicial usa {undefined}, que permite descartar o conteúdo anterior da imagem. Desenhe ou limpe a imagem inteira a cada quadro. Mantenha resultados acumulados ou em cache em uma textura da aplicação e depois a desenhe na textura de saída do controle." +concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat} fornece o formato de cor padrão dessas integrações." +concepts.platforms.frame.title: "Renderização em controles de interface" +concepts.platforms.integration.context: "WinForms, WPF e a integração Windows do WinUI executam no Windows. Para MAUI, instale a carga de trabalho da plataforma de destino e registre o manipulador do controle com {useZenithView}, como mostra {extensionsCs}." +concepts.platforms.integration.description: "A interface de eventos é comum, mas o mecanismo de apresentação depende do framework:" +concepts.platforms.integration.details: "Essas implementações diferem na forma de levar a imagem da GPU à interface. A leitura como bitmap copia os pixels para a memória da CPU antes da exibição. A interoperabilidade por texturas compartilhadas evita essa cópia, mas ainda pode exigir cópias na GPU e sincronização. Ao escolher uma integração, considere esse caminho de apresentação além do evento comum {renderRequested}." +concepts.platforms.integration.guidance: "Adicione pelo NuGet o pacote de integração correspondente ao seu framework de interface. Para Avalonia, use {avaloniaPackage}." +concepts.platforms.integration.table.avalonia.integration: "Avalonia" +concepts.platforms.integration.table.avalonia.presentation: "Renderiza em uma textura e copia os pixels para a memória da CPU em {writeableBitmap}. Implementação: {zenithViewCs} e {surfaceCs}." +concepts.platforms.integration.table.headings.integration: "Integração" +concepts.platforms.integration.table.headings.presentation: "Mecanismo de apresentação" +concepts.platforms.integration.table.maui.integration: ".NET MAUI" +concepts.platforms.integration.table.maui.presentation: "Usa superfícies nativas no Android, iOS e Mac Catalyst, e composição de textura compartilhada no Windows. Consulte as {link}." +concepts.platforms.integration.table.maui.presentation.link: "implementações de plataforma" +concepts.platforms.integration.table.uno.integration: "Caminho Uno" +concepts.platforms.integration.table.uno.presentation: "Copia os pixels para a memória da CPU em {writeableBitmap}. Implementação: {zenithViewUnoCs}." +concepts.platforms.integration.table.winForms.integration: "WinForms" +concepts.platforms.integration.table.winForms.presentation: "Cria uma cadeia de troca do Zenith.NET para o {hWND} do controle. Consulte {zenithViewCs}." +concepts.platforms.integration.table.winUI.integration: "WinUI no Windows" +concepts.platforms.integration.table.winUI.presentation: "Renderiza em uma textura Direct3D 11 compartilhada importada e copia o resultado para uma cadeia de troca de composição conectada a {swapChainPanel}. Consulte {zenithViewWinUICs}." +concepts.platforms.integration.table.wpf.integration: "WPF" +concepts.platforms.integration.table.wpf.presentation: "Importa uma textura Direct3D 11 compartilhada e copia seu conteúdo, por meio da interoperabilidade com Direct3D, para uma superfície exibida por {d3DImage}. Consulte {surfaceCs}." +concepts.platforms.integration.title: "Framework e apresentação" +concepts.platforms.lifecycle.context: "Ao criar anexos compatíveis, use {descWidth}, {descHeight}, {descFormat} e {descSampleCount} da textura de saída fornecida pelo evento de renderização. Essa textura informa as dimensões reais do destino; elas não devem ser deduzidas do tamanho de layout do controle nem da escala de exibição." +concepts.platforms.lifecycle.description: "A cadeia de troca usa a largura e a altura do framebuffer em pixels, que podem diferir das dimensões lógicas da janela quando há escala de exibição. Adie a renderização e o redimensionamento da cadeia enquanto alguma dimensão for zero. Obtenha {swapChainDrawable} a cada quadro: a textura pertence à cadeia de troca, que pode substituí-la após apresentar ou redimensionar." +concepts.platforms.lifecycle.details: "Quando o tamanho do framebuffer mudar, espere os usos pendentes das imagens antigas na GPU antes de chamar {swapChainResize}. Para substituir o destino nativo de apresentação, aguarde esses usos da mesma forma e passe a nova descrição da superfície e seus identificadores a {swapChainRefresh}. No encerramento, libere a cadeia de troca antes de destruir seu destino nativo." +concepts.platforms.lifecycle.guidance: "Se a aplicação tiver texturas de profundidade ou fora da tela que acompanham o tamanho da janela, recrie-as quando esse tamanho mudar e atualize as constantes que contêm seus identificadores. O pipeline pode ser reutilizado enquanto os formatos e as quantidades de amostras dos anexos continuarem correspondentes. O {link} mostra essa separação entre as texturas redimensionadas e o pipeline reutilizável." +concepts.platforms.lifecycle.guidance.link: "renderizador de cubo giratório" +concepts.platforms.lifecycle.title: "Dimensões e tempo de vida da cadeia de troca" +concepts.platforms.ownership.description: "O contexto atribuído e os recursos de renderização pertencem à aplicação; os recursos de apresentação pertencem ao controle. Quando {graphicsContext} muda na visualização, o agendador recria os recursos do controle para o novo contexto. Recrie também os pipelines, buffers e texturas da aplicação para esse contexto." +concepts.platforms.ownership.details: "Antes de substituir recursos de renderização, interrompa o processamento de quadros da visualização e espere o trabalho da GPU que os utiliza. Só então libere os recursos ou o contexto antigos. Ao remover a visualização, a aplicação continua responsável por liberar o contexto atribuído a ela." +concepts.platforms.ownership.guidance: "O componente compartilhado {frameSchedulerCs} executa os manipuladores de quadro pelo dispatcher da interface. Concentre esses manipuladores na atualização da cena e no registro de comandos: um processamento prolongado na CPU também atrasa a resposta da interface." +concepts.platforms.ownership.title: "Responsabilidades da aplicação e do controle" +concepts.platforms.surface.description: "O {link} usa Silk.NET para criar a janela e processar seus eventos. O Zenith.NET recebe os identificadores nativos e as dimensões em uma descrição {surface}, usada para criar uma {swapChain}. A aplicação continua responsável pela janela do sistema operacional." +concepts.platforms.surface.description.link: "tutorial do triângulo" +concepts.platforms.surface.details: "Os identificadores da superfície devem corresponder ao backend:" +concepts.platforms.surface.guidance: "O programa hospedeiro em {appCs} oferece suporte a Windows, macOS e X11. Sua janela Linux fornece identificadores Xlib, portanto uma sessão Wayland precisa de XWayland para executá-lo. Uma aplicação nativa de Wayland fornece os identificadores de display e superfície por meio de {surfaceWayland}." +concepts.platforms.surface.table.android.backend: "Vulkan no Android." +concepts.platforms.surface.table.apple.backend: "Metal nas plataformas Apple." +concepts.platforms.surface.table.headings.backend: "Backend e plataforma" +concepts.platforms.surface.table.headings.factory: "Fábrica de superfícies" +concepts.platforms.surface.table.headings.handles: "Identificadores fornecidos pelo programa hospedeiro" +concepts.platforms.surface.table.wayland.backend: "Vulkan com um host nativo Wayland." +concepts.platforms.surface.table.wayland.handles: "Display e superfície Wayland" +concepts.platforms.surface.table.win32.backend: "DirectX 12 ou Vulkan no Windows." +concepts.platforms.surface.table.xlib.backend: "Vulkan no Linux com X11 ou XWayland." +concepts.platforms.surface.table.xlib.handles: "Display e janela X11" +concepts.platforms.surface.title: "Superfícies nativas de apresentação" +concepts.platforms.title: "Integração de plataforma" +concepts.resources.allocation.context: "Os recursos colocados em um heap dependem de seu armazenamento durante todo o tempo de vida. Depois do último uso na GPU, libere os recursos antes de liberar o heap." +concepts.resources.allocation.description: "Use um {heap} quando a aplicação precisar gerenciar as alocações por conta própria. Um heap fornece armazenamento no qual os recursos são colocados em deslocamentos explícitos em bytes; a aplicação escolhe esses deslocamentos e acompanha as regiões ocupadas." +concepts.resources.allocation.details: "Para cada recurso, chame {contextGetSizeAndAlignment} com a descrição de buffer ou textura que será usada na criação. Reserve o tamanho retornado em um deslocamento múltiplo do alinhamento informado, dentro dos limites do heap e sem sobrepor outra alocação ainda em uso. Texturas podem incluir preenchimento específico do backend; por isso, a quantidade de pixels e os bytes por pixel não bastam para calcular o tamanho da alocação." +concepts.resources.allocation.guidance: "Um buffer colocado em um heap deve declarar a mesma residência desse heap. Para armazenar texturas, use um heap exclusivo da GPU." +concepts.resources.allocation.title: "Alocação em heaps" +concepts.resources.bufferUsages.table.constant.role: "Parâmetros de shader lidos por meio de uma vinculação de buffer de constantes." concepts.resources.bufferUsages.table.headings.role: "Função" -concepts.resources.bufferUsages.table.headings.usage: Uso -concepts.resources.bufferUsages.table.index.role: Índices usados pelo desenho indexado. -concepts.resources.bufferUsages.table.indirect.role: "Argumentos lidos por comandos de desenho ou dispatch indiretos." -concepts.resources.bufferUsages.table.none.role: "Nenhum sinalizador de uso de buffer é declarado." +concepts.resources.bufferUsages.table.headings.usage: "Uso" +concepts.resources.bufferUsages.table.index.role: "Índices usados pelo desenho indexado." +concepts.resources.bufferUsages.table.indirect.role: "Argumentos lidos por comandos de desenho ou despacho indiretos." +concepts.resources.bufferUsages.table.none.role: "Nenhum indicador de uso de buffer é declarado." concepts.resources.bufferUsages.table.storageReadOnly.role: "Dados de buffer acessados por uma vinculação de shader somente leitura." concepts.resources.bufferUsages.table.storageReadWrite.role: "Dados de buffer acessados por uma vinculação de shader de leitura e gravação." concepts.resources.bufferUsages.table.transferDst.role: "Armazenamento de destino para uma cópia de GPU." concepts.resources.bufferUsages.table.transferSrc.role: "Dados de origem para uma cópia de GPU." -concepts.resources.bufferUsages.table.vertex.role: Atributos de vértice buscados para desenho. -concepts.resources.bufferUsages.title: Usos de buffer -concepts.resources.description: "Escolha a descrição do recurso de acordo com as operações que o usarão. Uma textura que recebe renderização, é amostrada por um shader e é lida pela CPU precisa declarar os três usos e estabelecer a sincronização entre eles. O posicionamento da memória e o tempo de vida do recurso são decisões adicionais." -concepts.resources.memory.context: Para um buffer acessível pela CPU, {map} fornece um endereço à CPU. Ele não espera que a GPU pare de acessar os mesmos bytes. {unmap} da mesma forma não envia trabalho nem espera pela conclusão. Antes de sobrescrever dados graváveis pela CPU, conclua as leituras de GPU que ainda precisam do conteúdo antigo. -concepts.resources.memory.description: "Um {bufferDesc} tem um campo {residency}. Escolha-o de acordo com a forma como a CPU e a GPU acessarão os dados:" -concepts.resources.memory.details: A residência descreve o acesso pretendido da CPU à alocação. Ela não implica que cada dispositivo tenha memórias físicas separadas de CPU e GPU. O triângulo usa {cpuWriteOnly} para inicializar um pequeno buffer de vértices diretamente. Uma malha estática grande pode, em vez disso, se beneficiar de armazenamento exclusivo de GPU com um upload único. -concepts.resources.memory.guidance: "{textureDesc} não tem campo de residência. Texturas comuns criadas por contexto usam armazenamento de GPU. Sua API pública fornece operações de upload e download para transferências de dados da CPU, sem expor um método de mapeamento direto. Heaps explícitos fornecem controle de posicionamento, descrito abaixo." -concepts.resources.memory.table.cpuReadOnly.cPUAccess: "Ler a memória mapeada após a conclusão da cópia de GPU." +concepts.resources.bufferUsages.table.vertex.role: "Atributos de vértice buscados para desenho." +concepts.resources.bufferUsages.title: "Usos de buffer" +concepts.resources.description: "A descrição de um recurso define como a aplicação pode usar seu armazenamento. Por exemplo, uma textura usada como destino de renderização, amostrada por um shader e copiada de volta à CPU precisa dos indicadores de uso das três operações. A localização da memória determina o acesso da CPU; a sincronização e o gerenciamento do tempo de vida determinam quando os dados podem ser acessados ou o armazenamento liberado." +concepts.resources.memory.context: "Nos buffers acessíveis pela CPU, {map} fornece o endereço pelo qual os dados são lidos ou escritos. Nem o mapeamento nem {unmap} esperam o trabalho da GPU: antes de ler um resultado, a aplicação precisa esperar a escrita que o produz; antes de modificar os mesmos bytes, precisa esperar os acessos pendentes da GPU." +concepts.resources.memory.description: "O campo {residency} de {bufferDesc} especifica o acesso pretendido pela CPU:" +concepts.resources.memory.details: "A residência expressa os requisitos de acesso da CPU, inclusive em sistemas em que CPU e GPU compartilham memória física. O triângulo utiliza {cpuWriteOnly} para inicializar diretamente seu pequeno buffer de vértices. Para geometrias estáticas maiores, pode ser mais adequado enviar os dados para armazenamento exclusivo da GPU." +concepts.resources.memory.guidance: "Texturas criadas diretamente pelo contexto usam armazenamento da GPU. Por isso, {textureDesc} não possui um campo de residência; a aplicação troca seus dados com a memória da CPU por meio de uploads e downloads." +concepts.resources.memory.table.cpuReadOnly.cPUAccess: "Somente leitura" concepts.resources.memory.table.cpuReadOnly.typicalRole: "Dados produzidos pela GPU para leitura na CPU" -concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "Gravar na memória mapeada após o término das leituras anteriores da GPU." +concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "Somente escrita" concepts.resources.memory.table.cpuWriteOnly.typicalRole: "Dados fornecidos ou atualizados pela CPU" -concepts.resources.memory.table.gpuOnly.cPUAccess: "Transferir bytes por meio de um buffer de upload ou de leitura da GPU." +concepts.resources.memory.table.gpuOnly.cPUAccess: "Nenhum" concepts.resources.memory.table.gpuOnly.typicalRole: "Geometria estática e dados de trabalho da GPU" -concepts.resources.memory.table.headings.cPUAccess: Acesso da CPU -concepts.resources.memory.table.headings.residency: Residência -concepts.resources.memory.table.headings.typicalRole: Função típica -concepts.resources.memory.title: "Escolher a memória conforme o acesso necessário da CPU" -concepts.resources.textureUsages.description: "Os sinalizadores de uso de transferência descrevem a direção das cópias de GPU. O acesso da CPU é uma decisão separada de posicionamento de memória, descrita abaixo." -concepts.resources.textureUsages.details: "Combinar sinalizadores de uso declara várias funções; não executa as operações nem ordena seus acessos. As texturas ainda precisam de {link} adequados, e seus formatos devem oferecer suporte aos usos solicitados no dispositivo escolhido." +concepts.resources.memory.table.headings.cPUAccess: "Acesso previsto da CPU" +concepts.resources.memory.table.headings.residency: "Residência" +concepts.resources.memory.table.headings.typicalRole: "Função típica" +concepts.resources.memory.title: "Acesso pela CPU e localização na memória" +concepts.resources.textureUsages.description: "Os indicadores de transferência descrevem se o recurso é a origem ou o destino de uma cópia na GPU. A possibilidade de acesso direto pela CPU é uma decisão separada, tomada ao escolher a localização da memória." +concepts.resources.textureUsages.details: "Os indicadores de uso declaram as funções que uma textura pode desempenhar. Alternar entre elas exige os cuidados de {link} correspondentes, e o dispositivo escolhido deve oferecer suporte a esses usos para o formato da textura." concepts.resources.textureUsages.details.link: "layout e sincronização" concepts.resources.textureUsages.table.colorAttachment.role: "Um anexo de cor em uma passagem de renderização." concepts.resources.textureUsages.table.depthStencilAttachment.role: "Um anexo de profundidade e estêncil em uma passagem de renderização." concepts.resources.textureUsages.table.headings.role: "Função" -concepts.resources.textureUsages.table.headings.usage: Uso -concepts.resources.textureUsages.table.none.role: "Nenhum sinalizador de uso de textura é declarado." +concepts.resources.textureUsages.table.headings.usage: "Uso" +concepts.resources.textureUsages.table.none.role: "Nenhum indicador de uso de textura é declarado." concepts.resources.textureUsages.table.sampled.role: "Dados de textura lidos por uma vinculação de textura amostrada." concepts.resources.textureUsages.table.storage.role: "Dados de textura acessados por uma vinculação de textura de armazenamento para leituras ou gravações de shaders." concepts.resources.textureUsages.table.transferDst.role: "Armazenamento da imagem de destino para uma cópia de GPU." concepts.resources.textureUsages.table.transferSrc.role: "Dados da imagem de origem para uma cópia de GPU." -concepts.resources.textureUsages.title: Usos de textura -concepts.resources.title: Gerenciamento de recursos -concepts.resources.transfers.context: Um download grava uma cópia de GPU no armazenamento interno de leitura. A biblioteca copia esses bytes para o destino de CPU fornecido quando redefine o buffer de comandos concluído para reutilização. Mantenha o destino alocado e mantenha a memória gerenciada fixada até que o {wait} do valor de envio retorne. -concepts.resources.transfers.description: "Um upload copia dados da CPU para um recurso de GPU; um download copia dados do recurso de volta para a memória da CPU. Os métodos do próprio recurso concluem essa transferência antes de retornar:" -concepts.resources.transfers.details: "Essas esperas cobrem apenas a transferência enviada pelos métodos. Elas não descobrem dependências de outra fila que já estivesse lendo ou gravando o recurso. Estabeleça essas dependências antes de chamar o método do recurso. Uma cópia direta por memória mapeada também depende de quem chama para garantir a conclusão do trabalho de GPU correspondente." -concepts.resources.transfers.guidance: "Use {commandBufferUpload} ou {commandBufferDownload} quando as cópias precisarem ser gravadas com outros trabalhos. O tempo de vida de seus ponteiros difere:" -concepts.resources.transfers.item: "Um upload copia a origem da CPU para um buffer interno de upload, também chamado de memória de staging, durante a chamada. O ponteiro de origem só precisa permanecer válido durante essa chamada." -concepts.resources.transfers.notes: "Para uma textura, o passo de linha é a distância em bytes entre linhas consecutivas dos dados da CPU, e o passo de fatia é a distância em bytes entre fatias de profundidade consecutivas. Eles não representam o layout interno da textura na memória da GPU. Consulte {link} para distinguir a conclusão da GPU da disponibilidade dos dados lidos." -concepts.resources.transfers.notes.link: Sincronização -concepts.resources.transfers.table.bufferDownload.transfer: Cópia direta da CPU para {cpuReadOnly}; caso contrário, envia um download na fila de transferência e aguarda. -concepts.resources.transfers.table.bufferUpload.transfer: Cópia direta da CPU para {cpuWriteOnly}; caso contrário, envia um upload na fila de transferência e aguarda. -concepts.resources.transfers.table.headings.method: Método -concepts.resources.transfers.table.headings.transfer: "Como os dados são transferidos" +concepts.resources.textureUsages.title: "Usos de textura" +concepts.resources.title: "Gerenciamento de recursos" +concepts.resources.transfers.context: "Um download copia primeiro os dados da GPU para uma área interna de leitura. A biblioteca os copia para o destino de CPU fornecido quando recupera o buffer de comandos concluído. Chamar {wait} no valor de envio do download completa as duas etapas. Mantenha o destino alocado e a memória gerenciada fixada até o retorno dessa chamada." +concepts.resources.transfers.description: "Uploads copiam dados da CPU para um recurso da GPU; downloads copiam dados do recurso para a memória da CPU. Os métodos de buffers e texturas concluem essa transferência antes de retornar:" +concepts.resources.transfers.details: "Antes de chamar esses métodos, resolva os acessos conflitantes em outras filas. A espera interna do método abrange sua própria transferência; ela não estabelece uma dependência de outra fila. Nas cópias diretas por memória mapeada, cabe inteiramente a quem chama esperar os acessos conflitantes da GPU." +concepts.resources.transfers.guidance: "Para enviar transferências junto com outro trabalho da GPU, registre-as com {commandBufferUpload} ou {commandBufferDownload}. A memória de origem de um upload e a de destino de um download precisam permanecer válidas por períodos diferentes:" +concepts.resources.transfers.item: "Durante uma chamada de upload, a biblioteca copia os dados de origem para uma área temporária de transferência. A GPU lê dessa área posteriormente, portanto o ponteiro de origem da aplicação só é necessário até o retorno da chamada." +concepts.resources.transfers.notes: "Nas transferências de textura, o passo de linha é a distância em bytes entre linhas consecutivas dos dados da CPU; o passo de fatia é a distância entre fatias de profundidade consecutivas. Esses valores permitem copiar os dados entre sua organização na CPU e o armazenamento da textura na GPU. {link} explica por que concluir a cópia na GPU e entregar os dados ao destino de um download são etapas distintas." +concepts.resources.transfers.notes.link: "Sincronização" +concepts.resources.transfers.table.bufferDownload.transfer: "Para {cpuReadOnly}, copia diretamente da memória mapeada. Nos demais casos, envia o download à fila de transferência e espera sua conclusão." +concepts.resources.transfers.table.bufferUpload.transfer: "Para {cpuWriteOnly}, copia diretamente para a memória mapeada. Nos demais casos, envia o upload à fila de transferência e espera sua conclusão." +concepts.resources.transfers.table.headings.method: "Método" +concepts.resources.transfers.table.headings.transfer: "Comportamento da transferência" concepts.resources.transfers.table.textureTransfers.method: "{textureUpload} / {textureDownload}" -concepts.resources.transfers.table.textureTransfers.transfer: "Usa a fila gráfica, faz a transição do sub-recurso escolhido para o layout de cópia, depois para o layout final solicitado, e aguarda a conclusão da transferência." -concepts.resources.transfers.title: "Escolher entre transferências imediatas e transferências gravadas" -concepts.resources.usages.description: "{bufferUsages} e {textureUsages} são enumerações de sinalizadores que declaram as funções pretendidas de um recurso. Elas são atribuídas a {bufferDescUsages} e {textureDescUsages}, respectivamente. Uma enumeração de sinalizadores permite que vários membros sejam combinados com {value} quando um recurso tem mais de uma função." -concepts.resources.usages.title: Declarar os usos necessários antes de criar um recurso -concepts.resources.views.description: Uma {bufferView} descreve uma região de buffer e sua interpretação. Uma {textureView} seleciona um tipo de textura compatível, formato e intervalo de sub-recursos. Uma visualização compartilha o armazenamento subjacente; ela não copia os dados nem adiciona usos que faltavam quando o recurso foi criado. Seu intervalo também não é uma garantia portátil de verificação de limites no shader. -concepts.resources.views.details: "Use o handle do próprio recurso para sua visualização padrão ou crie uma visualização quando precisar de outra região ou interpretação compatível. Mantenha referências C# à visualização e ao recurso subjacente enquanto o trabalho de GPU puder usá-los; um handle de recurso sozinho não mantém nenhum dos objetos vivo. Libere-os somente após seu último uso na GPU. Ao substituir qualquer um deles, atualize as constantes que contêm seu antigo {link}." -concepts.resources.views.details.link: "handle de recurso" -concepts.resources.views.guidance: O {link} mostra uma textura de profundidade substituída no redimensionamento. O {detail} mostra uma textura de entrada mantida separada de sua saída gravável. Ambos fazem o tempo de vida do recurso acompanhar o trabalho que realmente o utiliza. -concepts.resources.views.guidance.detail: exemplo de computação -concepts.resources.views.guidance.link: renderizador de cubo giratório -concepts.resources.views.title: "Manter visualizações e seus recursos subjacentes utilizáveis juntos" -concepts.shaders.binding.context: "No exemplo de computação, {input} é preenchido com {inputTextureSampledHandle} e {output} com {outputTextureStorageHandle}. O {descriptorHandle} tipado do Slang informa ao shader como acessar cada recurso:" -concepts.shaders.binding.description: "{setConstantBuffer} vincula um buffer e um deslocamento de bytes para os dados de constantes da pipeline atual. Ele vincula armazenamento visível pela GPU existente; não faz upload de um valor C#. Preencha o buffer primeiro e garanta que os leitores anteriores da GPU tenham terminado antes de sobrescrever seus bytes." -concepts.shaders.binding.details: "Defina a pipeline antes de seu buffer de constantes. Para uma carga de trabalho de computação com recursos já criados e carregados, a gravação usa esta ordem:" -concepts.shaders.binding.guidance: Este fragmento assume um {commandBuffer} em gravação, uma {computePipeline}, um {constantBuffer} carregado com uso {bufferUsagesConstant} e as contagens de grupos de threads para a carga de trabalho. O deslocamento 0 vincula o início do buffer. Se vários registros de dados de constantes compartilharem um buffer, o deslocamento inicial de cada registro deverá atender ao alinhamento de vinculação do backend. Esse requisito é independente do layout dos campos dentro do registro. -concepts.shaders.binding.notes: "{resourceHandle} armazena dois campos de 32 bits, mas sua interpretação pertence ao backend. Não o trate como um índice de descritor universal, endereço ou valor que possa ser transferido entre contextos. Um handle não cria um recurso, não adiciona um uso ausente nem realiza sincronização." -concepts.shaders.binding.reference: Mantenha referências ao recurso e a qualquer visualização usada para obter seu handle, e descarte-os apenas após a conclusão do último uso do shader. Ao substituir uma textura ou visualização, atualize as constantes que contêm seu handle antigo. O {link} explica essa relação de tempo de vida. -concepts.shaders.binding.reference.link: Gerenciamento de recursos -concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: Ler elementos estruturados do tipo de shader {t}. -concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: Ler ou gravar elementos estruturados do tipo de shader {t}. -concepts.shaders.binding.table.headings.access: Acesso pretendido -concepts.shaders.binding.table.headings.cHandle: "Handle C#" -concepts.shaders.binding.table.headings.slangFieldType: Tipo de campo Slang -concepts.shaders.binding.table.samplerHandle.access: Fornecer estado de amostragem de textura. -concepts.shaders.binding.table.textureSampledHandle.access: Ler uma textura. -concepts.shaders.binding.table.textureStorageHandle.access: Ler ou gravar uma textura de armazenamento. -concepts.shaders.binding.title: Vincular o buffer de constantes e os recursos que ele descreve -concepts.shaders.compilation.description: "O {zenithCompiler} compila um ponto de entrada nomeado do Slang e retorna uma {shaderDesc}. Use o {graphicsApi} do contexto para que o resultado seja direcionado ao backend que criará o shader: DXIL para DirectX 12, uma biblioteca Metal para Metal ou SPIR-V para Vulkan." -concepts.shaders.compilation.details: "Por exemplo, com um {context} existente e o shader do triângulo copiado ao lado do executável:" -concepts.shaders.compilation.guidance: "{vSMain} deve corresponder exatamente ao nome do ponto de entrada no arquivo de shader. Mantenha os objetos de shader válidos enquanto cria a pipeline e, em seguida, descarte-os após a criação da pipeline, como mostrado em {link}. Execute essa inicialização uma vez em vez de recompilar a cada quadro." -concepts.shaders.compilation.guidance.link: Primeiro triângulo -concepts.shaders.compilation.title: Compilar um ponto de entrada para o contexto selecionado -concepts.shaders.description: "Um shader recebe dados fornecidos pela aplicação. Atributos de vértice descrevem vértices individuais; buffers armazenam parâmetros ou arrays; handles de recursos identificam outros recursos que o shader acessará. As declarações C# e as declarações Slang devem concordar sobre o que esses valores significam. Fazer a correspondência de um nome de campo não é suficiente: layout, acesso a recursos e vinculação precisam coincidir." -concepts.shaders.dispatch.description: "{dispatch} recebe o número de grupos de threads. O ponto de entrada {numthreads} do exemplo de computação executa 16 × 16 threads por grupo. Divida as dimensões da imagem por 16 e arredonde para cima para encontrar as contagens de grupos. Por exemplo, uma imagem de 17 × 19 precisa de 2 × 2 grupos. O shader verifica suas coordenadas de pixel em relação às dimensões da imagem porque os últimos grupos podem conter threads fora da imagem." -concepts.shaders.dispatch.details: O compilador armazena o tamanho de grupo declarado do ponto de entrada em {shaderDescThreadGroupSize}; ele não converte as dimensões em pixels fornecidas ao {dispatch} em contagens de grupos. Use o {computeShaderRendererCs} com seu shader para o exemplo completo de vinculação e dispatch, e {link} antes que outra passagem consuma a saída. -concepts.shaders.dispatch.details.link: Sincronização -concepts.shaders.dispatch.title: Despachar grupos de threads, não pixels -concepts.shaders.layout.context: "As {link} tornam seus deslocamentos explícitos. Esta declaração precisa de {systemRuntimeInteropServices} e {zenithNET} no escopo:" +concepts.resources.transfers.table.textureTransfers.transfer: "Envia a cópia e as transições de textura à fila gráfica e espera sua conclusão. O sub-recurso selecionado fica no layout final solicitado." +concepts.resources.transfers.title: "Transferências imediatas e registradas" +concepts.resources.usages.description: "{bufferUsages} e {textureUsages} são enumerações de indicadores que declaram os usos de um recurso. Seus valores são atribuídos a {bufferDescUsages} e {textureDescUsages}, respectivamente. Para vários usos, combine os membros necessários com {value}." +concepts.resources.usages.title: "Usos de recursos" +concepts.resources.views.description: "Uma {bufferView} descreve uma região de um buffer e a interpretação de seus dados. Uma {textureView} seleciona um intervalo de sub-recursos, com um tipo e formato de textura compatíveis. Ambas se referem ao armazenamento existente, com os usos declarados na criação. Os intervalos das visualizações descrevem o acesso, mas não garantem uma verificação de limites uniforme nos shaders de todos os backends." +concepts.resources.views.details: "O identificador do próprio recurso fornece sua visualização padrão. Crie uma visualização separada para escolher outra região ou uma interpretação compatível diferente. Mantenha vivos tanto a visualização quanto o recurso que a sustenta até a GPU terminar de utilizá-los; um identificador não mantém nenhum desses objetos vivo. Ao substituir qualquer um deles, atualize as constantes que contêm o {link} anterior." +concepts.resources.views.details.link: "identificador de recurso" +concepts.resources.views.title: "Visualizações e recursos subjacentes" +concepts.shaders.binding.context: "O exemplo de computação atribui {inputTextureSampledHandle} a {input} e {outputTextureStorageHandle} a {output}. Em Slang, o parâmetro de tipo de {descriptorHandle} define como o shader acessa cada recurso:" +concepts.shaders.binding.description: "{setConstantBuffer} seleciona um buffer existente e o deslocamento de byte a partir do qual o pipeline atual lê suas constantes. Envie os parâmetros para esse armazenamento antes de serem usados pelo shader. Se um trabalho anterior da GPU ainda estiver lendo os mesmos bytes, espere sua conclusão antes de atualizá-los." +concepts.shaders.binding.details: "Com o buffer de comandos, o pipeline de computação, o buffer de constantes preenchido e as quantidades de grupos de threads prontos, registre o despacho nesta ordem. Selecione primeiro o pipeline, pois a vinculação do buffer de constantes se aplica a ele:" +concepts.shaders.binding.guidance: "Aqui, {commandBuffer} registra um despacho com {computePipeline} e os parâmetros armazenados em {constantBuffer}. O buffer precisa do uso {bufferUsagesConstant}, e o deslocamento 0 seleciona seu início. Se vários registros de constantes compartilharem um buffer, o deslocamento inicial de cada registro também deve atender ao alinhamento de vinculação do backend, independentemente do layout de seus campos internos." +concepts.shaders.binding.notes: "{resourceHandle} contém dois campos de 32 bits cuja interpretação depende do backend. Seus valores são válidos apenas no contexto em que o recurso foi criado." +concepts.shaders.binding.reference: "Mantenha o recurso e a visualização usada para obter seu identificador até o último acesso do shader. A substituição exige atualizar constantes que ainda contenham o identificador antigo. {link} apresenta as regras de responsabilidade." +concepts.shaders.binding.reference.link: "Gerenciamento de recursos" +concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: "Leitura de elementos estruturados do tipo {t} do shader" +concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: "Leitura e escrita de elementos estruturados do tipo {t} do shader" +concepts.shaders.binding.table.headings.access: "Acesso pretendido" +concepts.shaders.binding.table.headings.cHandle: "Identificador C#" +concepts.shaders.binding.table.headings.slangFieldType: "Tipo de campo Slang" +concepts.shaders.binding.table.samplerHandle.access: "Estado de amostragem de texturas" +concepts.shaders.binding.table.textureSampledHandle.access: "Leitura de texturas" +concepts.shaders.binding.table.textureStorageHandle.access: "Leitura e escrita de texturas de armazenamento" +concepts.shaders.binding.title: "Buffers de constantes e identificadores de recursos" +concepts.shaders.compilation.description: "{zenithCompiler} compila um ponto de entrada Slang em uma {shaderDesc}. O {graphicsApi} do contexto define o destino: DXIL para DirectX 12, biblioteca Metal para Metal ou SPIR-V para Vulkan." +concepts.shaders.compilation.details: "Com um contexto gráfico já criado e chamado {context}, compile o shader do triângulo a partir da cópia ao lado do executável:" +concepts.shaders.compilation.guidance: "O nome do ponto de entrada {vSMain} deve corresponder à declaração no arquivo de shader. Compile os shaders e crie os pipelines na inicialização; depois, reutilize os pipelines durante a renderização. Após a criação dos pipelines, os objetos shader podem ser liberados, como mostra {link}." +concepts.shaders.compilation.guidance.link: "Primeiro triângulo" +concepts.shaders.compilation.title: "Compilação de shaders" +concepts.shaders.description: "As declarações em C# e Slang precisam concordar quanto à posição de cada valor e ao acesso feito pelo shader. Layouts de entrada descrevem os atributos dos vértices; declarações de buffers do shader descrevem parâmetros e arrays; identificadores apontam para os recursos usados pelo shader." +concepts.shaders.dispatch.description: "{dispatch} especifica quantos grupos de threads serão executados. O exemplo de computação declara {numthreads}, portanto cada grupo contém 16 × 16 threads. Para cobrir uma imagem, divida a largura e a altura por 16 e arredonde cada resultado para cima: uma imagem de 17 × 19 precisa de 2 × 2 grupos. O shader verifica as coordenadas de cada thread e ignora as que ficam fora da imagem." +concepts.shaders.dispatch.details: "O tamanho de grupo declarado está disponível em {shaderDescThreadGroupSize} e permite calcular as quantidades de grupos passadas a {dispatch}. {computeShaderRendererCs} mostra o cálculo completo. Depois do despacho, o acesso à imagem resultante deve seguir os requisitos descritos em {link}." +concepts.shaders.dispatch.details.link: "Sincronização" +concepts.shaders.dispatch.title: "Grupos de threads" +concepts.shaders.layout.context: "As {link} ilustram essa organização com as dimensões de uma imagem e dois identificadores de textura. Deslocamentos explícitos indicam onde cada campo começa. A declaração usa {systemRuntimeInteropServices} e {zenithNET}:" concepts.shaders.layout.context.link: "constantes C# do exemplo de computação" -concepts.shaders.layout.description: "Para a entrada de vértices, o {inputLayout} da pipeline descreve formatos, deslocamentos, stride e semânticas. A posição {float3} do triângulo seguida por uma cor {float4} ocupa 28 bytes, com a cor no byte 12. {inputLayoutAdd} calcula esse layout compactado; ele não inspeciona a struct C#. Se os campos C# contiverem padding, forneça um layout correspondente em vez de presumir que os campos estão compactados." -concepts.shaders.layout.details: "Buffers de constantes contêm parâmetros de shader, enquanto buffers estruturados contêm arrays de elementos de um tipo declarado. Ambos são lidos de acordo com suas declarações Slang. Eles não usam {inputLayout}. Verifique deslocamentos de campos e tamanhos de elementos para a representação de shader compilada, incluindo padding. Um tipo C# não gerenciado é adequado para cópia como bytes, mas isso por si só não prova que ele corresponda a um tipo de shader. Em particular, não aplique o layout {float3} compactado de um vértice a todos os buffers de shader." -concepts.shaders.layout.guidance: Um handle de recurso é um valor pequeno que faz referência a um recurso existente. Copiar o handle para um buffer de constantes não copia o conteúdo do recurso. +concepts.shaders.layout.description: "Para a entrada de vértices, {inputLayout} descreve o formato, o deslocamento e a semântica de cada atributo, além do passo entre vértices. O triângulo coloca uma posição {float3} antes de uma cor {float4}: a cor começa no deslocamento de byte 12 e cada vértice ocupa 28 bytes. {inputLayoutAdd} calcula essa organização compacta a partir dos formatos. Se a estrutura C# contiver preenchimento, informe deslocamentos e um passo que o considerem." +concepts.shaders.layout.details: "Buffers de constantes contêm parâmetros do shader, e buffers estruturados contêm arrays de elementos tipados. Seus layouts seguem as declarações de Slang, e não {inputLayout}. Ajuste os deslocamentos dos campos, tamanhos dos elementos e preenchimento em C# ao layout do shader compilado. Um tipo não gerenciado de C# pode ser copiado byte a byte, mas seu layout na memória não corresponde necessariamente ao do shader; um {float3} armazenado sem preenchimento em um vértice pode exigir outro alinhamento em um buffer do shader." +concepts.shaders.layout.guidance: "Os parâmetros do shader podem incluir identificadores de recursos além de valores comuns. Um identificador aponta para armazenamento já existente, portanto copiá-lo para um buffer de constantes não copia o conteúdo do recurso." concepts.shaders.layout.notes: "A declaração correspondente em {computeShaderSlang} é:" -concepts.shaders.layout.reference: "As dimensões ocupam os primeiros oito bytes, seguidas por dois handles de recursos de oito bytes. O exemplo em C# reserva 256 bytes no total. Esse tamanho é o tamanho de armazenamento escolhido pelo exemplo, não uma regra de que todas as structs Slang ou cargas úteis de constantes devam ocupar 256 bytes. Preencher o tamanho total também não corrige um campo no deslocamento errado." -concepts.shaders.layout.title: A entrada de vértices e os dados de shaders têm regras de layout diferentes -concepts.shaders.matrices.description: "O compilador solicita armazenamento de matrizes por linhas (row-major), mantendo os elementos de cada linha contíguos. O {link} posiciona três valores {matrix4x4} nos deslocamentos 0, 64 e 128. Seu {detail} usa {mulVectorMatrix} na ordem modelo, visualização e projeção." -concepts.shaders.matrices.description.detail: shader -concepts.shaders.matrices.description.link: renderizador de cubo giratório -concepts.shaders.matrices.details: A ordem de armazenamento determina como os elementos da matriz ocupam a memória; a ordem de multiplicação determina a transformação. Mantenha ambos os lados consistentes. Adicionar uma transposição sem verificar essas duas opções pode ocultar uma inconsistência enquanto introduz outra. -concepts.shaders.matrices.title: Manter o armazenamento e a multiplicação de matrizes consistentes -concepts.shaders.title: Dados de shaders e vinculação -concepts.synchronization.backends.description: DirectX 12 e Vulkan codificam transições de textura com informações de layout e acesso. O Metal não tem nenhuma operação na implementação de {transition} do Zenith.NET. O Metal agrupa o trabalho gravado em codificadores de renderização e computação. O backend insere barreiras de visibilidade quando encerra esses grupos, disponibilizando gravações anteriores para trabalhos posteriores. Chamadas explícitas a {barrier} lidam com dependências como dispatches sucessivos de computação dentro do mesmo codificador. -concepts.synchronization.backends.details: Essa distinção é importante ao alterar uma carga de trabalho. No {link}, o dispatch é seguido por uma passagem de renderização gráfica, o que também cria um limite de codificador no Metal. Dois dispatches de computação dependentes não criam esse limite apenas alterando o layout declarado da textura. Mantenha as transições exigidas pela API compartilhada e identifique separadamente a dependência entre os comandos reais de produção e consumo. -concepts.synchronization.backends.details.link: exemplo de computação -concepts.synchronization.backends.title: Uma transição não é idêntica em todos os backends -concepts.synchronization.barriers.context: "{barrierStagesAll} é um escopo mais amplo, não um detector automático de dependências. Selecione estágios que realmente cubram o trabalho e use-os apenas em uma fila que suporte essas operações." -concepts.synchronization.barriers.description: "Considere dois dispatches de computação: o primeiro grava dados de simulação e o segundo lê esses dados para executar a etapa seguinte. Ambos usam buffers de armazenamento, portanto não há layout de textura a ser alterado. Insira isto entre os dispatches em seu buffer de comandos:" -concepts.synchronization.barriers.details: O primeiro argumento identifica o estágio produtor e o segundo o estágio consumidor. A barreira estabelece a dependência correspondente de execução e memória na GPU. O backend traduz esses estágios em suas regras de execução e acesso à memória. Esta barreira não altera o layout de uma textura nem espera por todo o trabalho no dispositivo. -concepts.synchronization.barriers.guidance: "A {link} usa esse padrão entre dispatches dependentes. Coloque a barreira onde ocorre a dependência. Uma barreira gravada depois do consumidor não pode ordenar esse consumidor após um produtor anterior." -concepts.synchronization.barriers.guidance.link: simulação FluidTank -concepts.synchronization.barriers.title: Ordenar comandos dependentes com uma barreira -concepts.synchronization.dependencies.description: Para cada recurso compartilhado, identifique a operação que o acessa primeiro, a operação seguinte e se algum dos acessos grava. Ler os mesmos dados duas vezes não requer ordenação para proteger seu conteúdo, embora alterações de layout ou apresentação possam impor outros requisitos. Uma gravação seguida por uma leitura, uma leitura seguida por uma sobrescrita ou duas gravações podem exigir uma dependência. -concepts.synchronization.dependencies.details: "Em seguida, escolha o mecanismo de acordo com onde essas operações são executadas:" -concepts.synchronization.dependencies.guidance: Esses mecanismos são relacionados, mas não intercambiáveis. Enviar comandos em ordem não substitui todas as dependências de memória. Uma espera de fila não declara um novo layout de textura, e uma barreira de comandos não aguarda na thread de CPU chamadora. -concepts.synchronization.dependencies.table.cpuAccess.mechanism: Chamar {wait} no valor de conclusão relevante. -concepts.synchronization.dependencies.table.cpuAccess.situation: A CPU deve esperar antes de acessar ou liberar dados -concepts.synchronization.dependencies.table.crossQueue.mechanism: Passar seu {timelineValue} para o {submit} do buffer de comandos consumidor. -concepts.synchronization.dependencies.table.crossQueue.situation: Um envio em outra fila produz os dados -concepts.synchronization.dependencies.table.headings.mechanism: Mecanismo -concepts.synchronization.dependencies.table.headings.situation: Situação +concepts.shaders.layout.reference: "As duas dimensões ocupam os primeiros oito bytes, seguidas de dois identificadores de oito bytes cada. O exemplo C# reserva 256 bytes para o registro completo. Para outros registros, determine o tamanho a partir de seus próprios campos e requisitos de layout e alinhamento." +concepts.shaders.layout.title: "Layout de dados" +concepts.shaders.matrices.description: "O compilador usa armazenamento de matrizes por linhas, mantendo cada linha contígua. O {link} armazena três valores {matrix4x4} nos deslocamentos 0, 64 e 128. Seu {detail} aplica {mulVectorMatrix} na ordem modelo, visão e projeção." +concepts.shaders.matrices.description.detail: "shader" +concepts.shaders.matrices.description.link: "renderizador de cubo giratório" +concepts.shaders.matrices.details: "A ordem de armazenamento determina a disposição dos elementos da matriz na memória; a ordem de multiplicação determina a transformação. C# e Slang devem adotar convenções compatíveis." +concepts.shaders.matrices.title: "Convenções de matrizes" +concepts.shaders.title: "Dados de shaders e vinculação" +concepts.synchronization.backends.description: "DirectX 12 e Vulkan codificam as transições de textura como mudanças de layout e acesso. Em Metal, a implementação de {transition} do Zenith.NET não executa uma operação equivalente. O backend de Metal reúne os comandos em codificadores de renderização e computação e insere barreiras de visibilidade ao encerrar cada codificador. Operações dependentes no mesmo codificador, como despachos de computação sucessivos, usam chamadas explícitas a {barrier}." +concepts.synchronization.backends.details: "No {link}, iniciar a passagem gráfica encerra o codificador de computação e torna sua saída visível ao trabalho gráfico. Dois despachos consecutivos permanecem no mesmo codificador, portanto sua dependência exige uma barreira mesmo que haja uma transição de textura entre eles. Por isso, uma sequência de comandos portável deve considerar as dependências de acesso além dos layouts de textura." +concepts.synchronization.backends.details.link: "exemplo de computação" +concepts.synchronization.backends.title: "Comportamento dos backends" +concepts.synchronization.barriers.context: "Escolha etapas que incluam os acessos envolvidos e sejam compatíveis com a fila. {barrierStagesAll} inclui todas as etapas compatíveis; selecione um conjunto menor quando a dependência envolver apenas essas etapas." +concepts.synchronization.barriers.description: "Considere dois despachos de computação registrados no mesmo buffer de comandos: o primeiro escreve dados de simulação e o segundo os lê. Coloque uma barreira entre eles para que o segundo veja as escritas concluídas. Em um buffer de armazenamento, isso ordena os acessos sem uma transição de layout de textura:" +concepts.synchronization.barriers.details: "O primeiro argumento identifica as etapas que produzem os dados; o segundo, as etapas que os consomem. Juntos, eles descrevem a ordem de execução e a visibilidade de memória necessárias entre os dois despachos." +concepts.synchronization.barriers.guidance: "A {link} usa esse padrão entre etapas da simulação. Cada barreira fica depois do despacho que produz os dados e antes daquele que os utiliza." +concepts.synchronization.barriers.guidance.link: "simulação FluidTank" +concepts.synchronization.barriers.title: "Barreiras do pipeline" +concepts.synchronization.dependencies.description: "Para cada recurso, identifique os acessos aos mesmos dados. Se algum deles escrever, preserve a ordem necessária entre as operações. Duas leituras não entram em conflito, embora os requisitos de layout de textura e apresentação continuem válidos. Atualizações pela CPU e a liberação de recursos também precisam esperar a GPU terminar de usar o armazenamento afetado." +concepts.synchronization.dependencies.details: "O mecanismo adequado depende de onde as operações são executadas:" +concepts.synchronization.dependencies.guidance: "Uma carga de trabalho pode precisar de mais de um mecanismo. Por exemplo, uma textura produzida em outra fila precisa de uma dependência entre envios e do layout adequado para o próximo uso. Nenhuma dessas operações exige bloquear a CPU, a menos que ela própria precise acessar ou liberar os dados." +concepts.synchronization.dependencies.table.cpuAccess.mechanism: "Chamar {wait} no valor de conclusão relevante." +concepts.synchronization.dependencies.table.cpuAccess.situation: "O acesso da CPU ou a liberação de recursos depende da conclusão na GPU" +concepts.synchronization.dependencies.table.crossQueue.mechanism: "Passe o {timelineValue} do produtor para o {submit} do consumidor." +concepts.synchronization.dependencies.table.crossQueue.situation: "Uma fila consome dados produzidos em outra" +concepts.synchronization.dependencies.table.headings.mechanism: "Mecanismo" +concepts.synchronization.dependencies.table.headings.situation: "Situação" concepts.synchronization.dependencies.table.layoutChange.mechanism: "{commandBufferTransition} com seus layouts anterior e seguinte." -concepts.synchronization.dependencies.table.layoutChange.situation: Um sub-recurso de textura altera como é usado +concepts.synchronization.dependencies.table.layoutChange.situation: "Um sub-recurso de textura altera como é usado" concepts.synchronization.dependencies.table.pipelineStages.mechanism: "{commandBufferBarrier} com os estágios produtor e consumidor." -concepts.synchronization.dependencies.table.pipelineStages.situation: Estágios dependentes da GPU em um fluxo de comandos -concepts.synchronization.dependencies.title: Começar com o produtor e o consumidor -concepts.synchronization.description: Um comando que lê dados gravados por um comando anterior depende de que essas gravações estejam concluídas e visíveis para ele. Quem grava é o produtor; quem lê é o consumidor. A CPU também precisa de um ponto de conclusão antes de ler, sobrescrever ou liberar dados compartilhados. O Zenith.NET fornece barreiras, transições de textura e linhas do tempo para essas diferentes dependências. -concepts.synchronization.layouts.context: "{undefined} significa que o conteúdo anterior não precisa ser preservado. É adequado para uma nova imagem ou um anexo que será totalmente limpo. Não é uma forma de evitar rastrear o layout de uma imagem cujo conteúdo será carregado, amostrado ou acumulado." -concepts.synchronization.layouts.description: "Sinalizadores de uso descrevem quais funções uma textura suporta. {textureLayout} descreve como um sub-recurso específico será acessado para uma operação. Um sub-recurso é um nível mip e uma camada de array selecionados. Alterar seu layout prepara esse acesso; não converte a textura para um formato de pixel diferente. Por exemplo, o exemplo de computação grava uma textura de saída no layout {storage} e depois a amostra em uma passagem gráfica. Entre esses usos, ele grava:" -concepts.synchronization.layouts.details: Este fragmento assume que {outputTexture} foi criada com uso {sampledStorage} e que seu sub-recurso selecionado está no layout {storage}. {default} seleciona o nível mip 0 e a camada de array 0. A operação não faz a transição de cada mip ou camada de uma textura. -concepts.synchronization.layouts.guidance: A aplicação fornece o layout anterior. {transition} não mantém um rastreador de layout visível pela aplicação nem infere esse valor a partir de comandos anteriores. Rastreie o layout onde quer que um recurso passe entre estágios de renderização. -concepts.synchronization.layouts.title: Rastrear o layout de cada sub-recurso de textura -concepts.synchronization.readback.description: "{isCompleted} apenas consulta se a linha do tempo da GPU atingiu um valor. Ele não recupera buffers de comandos nem copia os dados de download armazenados temporariamente para o ponteiro de destino da aplicação." -concepts.synchronization.readback.details: "{commandBufferDownload} grava primeiro uma cópia no armazenamento interno de leitura. Ao redefinir o buffer de comandos concluído para reutilização, a CPU copia os dados para o ponteiro fornecido. Mantenha esse destino válido e a memória gerenciada fixada até que {wait} retorne para esse envio de download. Só então leia os dados ou libere a memória. Esperar por um envio posterior de outra fila não faz a sondagem da fila que gerencia o download." -concepts.synchronization.readback.guidance: É por isso que sondar {isCompleted} e ler imediatamente o destino de um download assíncrono é insuficiente. O {link} aborda os caminhos de cópia direta e transferência intermediária. -concepts.synchronization.readback.guidance.link: Gerenciamento de recursos -concepts.synchronization.readback.title: A conclusão na GPU e os dados baixados na CPU são etapas separadas -concepts.synchronization.reuse.description: Para um primeiro renderizador, uma espera imediata após cada quadro é direta. Para sobrepor o trabalho, forneça aos quadros pendentes dados mutáveis separados e guarde o valor de conclusão do uso final de cada quadro. Antes de atualizar um buffer de constantes, substituir uma textura ou descartar uma pipeline, conclua todos os acessos pendentes ao recurso afetado. -concepts.synchronization.reuse.details: No redimensionamento ou desligamento, pare novos usos antes de esperar pelos antigos. {swapChainResize}, descarte de recursos e descarte de contexto não servem como esperas gerais para o trabalho da aplicação. O triângulo pode redimensionar com segurança entre callbacks porque cada quadro precedente já concluiu seu envio. -concepts.synchronization.reuse.guidance: O {swapChainPresent} atual também sinaliza e aguarda na fila gráfica após sua operação de apresentação. Portanto, remover a espera de envio explícita do triângulo não estabelece por si só um loop de apresentação sobreposto. Uma espera na fila gráfica também não diz nada sobre trabalhos independentes ainda em execução em outra fila. -concepts.synchronization.reuse.title: Reutilizar dados somente após o seu acesso final -concepts.synchronization.timelines.context: "Antes que a CPU leia, sobrescreva ou libere esses recursos, aguarde seu uso final:" -concepts.synchronization.timelines.description: Uma linha do tempo rastreia a conclusão em uma fila usando valores crescentes. {submit} retorna um {timelineValue} contendo essa linha do tempo e o valor associado ao envio. Valores de conclusão de diferentes linhas do tempo não são comparáveis apenas por seus campos numéricos {value}. -concepts.synchronization.timelines.details: "Suponha que {producer} e {consumer} sejam buffers de comandos já gravados de duas filas do mesmo contexto. O produtor grava dados que o consumidor usa. Envie-os assim:" -concepts.synchronization.timelines.guidance: Passar o valor produzido faz com que a fila consumidora aguarde por ele na GPU. A CPU não chama {producedWait} aqui. Mantenha os recursos compartilhados válidos até que {consumed} seja concluído e grave quaisquer alterações de layout de textura exigidas pelo consumidor. -concepts.synchronization.timelines.notes: "{wait} aguarda o valor da linha do tempo e verifica a fila responsável em busca de envios concluídos. Os buffers de comandos finalizados são redefinidos para reutilização, e seus dados de download armazenados temporariamente são copiados para os destinos de CPU fornecidos. {queueTimelineSignal} também pode enfileirar um ponto de conclusão após o trabalho já enviado para essa fila. Chamar {signal} não significa que a GPU já atingiu o ponto." -concepts.synchronization.timelines.title: Usar uma linha do tempo para conclusão e transferências entre filas -concepts.synchronization.title: Sincronização -home.actions.reference: Navegar na API -home.actions.tutorial: Começar com um triângulo -home.entries.description: Um primeiro quadro. Um exemplo focado. Uma visão detalhada da API. -home.entries.label: Explorar a documentação -home.entries.reference.action: Explorar a API -home.entries.reference.category: Referência -home.entries.reference.description: Encontre os tipos, assinaturas e membros que sustentam sua aplicação. -home.entries.reference.title: Referência da API -home.entries.samples.action: Procurar exemplos -home.entries.samples.category: Exemplos -home.entries.samples.description: Explore técnicas focadas de renderização e computação por meio do código-fonte. -home.entries.samples.title: Exemplos -home.entries.title: Comece a construir. -home.entries.tutorial.action: Iniciar tutorial -home.entries.tutorial.category: Tutorial -home.entries.tutorial.description: Crie uma aplicação de renderização completa, desde a configuração até o primeiro quadro. -home.entries.tutorial.title: Primeiro triângulo -home.introduction.accent: "Em C#." -home.introduction.description: Crie recursos, grave comandos e envie tarefas gráficas ou de computação por meio de uma única API .NET. -home.introduction.title: Crie seu renderizador. -home.meta.description: "Uma API C# consistente para computação e gráficos no DirectX, Metal e Vulkan." -home.scene.description: Estudo de geometria rotativa. Arraste ou use as teclas de direção para ajustar a visualização. -home.scene.label: Exibição de geometria -home.scene.surface: Superfície -home.scene.wireframe: Wireframe -home.title: RHI moderno para .NET -learning.concepts.description: Entenda como comandos, recursos, dados de shader e sincronização se encaixam antes de combinar passagens de renderização. -learning.concepts.execution.description: Grave tarefas na GPU, envie-as e mantenha seus recursos ativos. -learning.concepts.platforms.description: Conecte uma janela nativa ou um controle de renderização de interface. -learning.concepts.resources.description: Escolha usos de recursos, alocação de memória e visualizações. -learning.concepts.shaders.description: "Faça a correspondência de layouts C# e handles de recursos com Slang." -learning.concepts.synchronization.description: Ordene acessos dependentes e saiba quando o trabalho é concluído. -learning.concepts.title: Conceitos fundamentais -learning.description: Comece com um tutorial completo de triângulo. Em seguida, utilize os exemplos focados e os guias conceituais para compreender os recursos, dados e dependências por trás de um renderizador maior. -learning.entries.samples.action: Procurar exemplos -learning.entries.samples.description: "Encontre exemplos em C# e Slang para geometria, computação, consultas de raios e sombreamento de malhas." -learning.entries.tutorial.action: Abrir tutorial -learning.entries.tutorial.description: Crie uma aplicação de console, abra uma janela e desenhe um triângulo. -learning.meta.description: Primeiros passos com o Zenith.NET e exploração do seu modelo de programação. -learning.title: Aprender -reference.description: Consulte tipos de recursos, assinaturas de comandos e integrações de plataforma. -reference.entries.commands.description: Grave comandos de gráficos, computação e transferência. -reference.entries.commands.label: Gravar trabalho -reference.entries.context.description: Crie recursos de GPU para o backend selecionado. -reference.entries.context.label: Comece aqui -reference.meta.description: Explore os tipos e membros no Zenith.NET. -reference.navigation.core: Navegar na API principal. -reference.title: Referência da API -samples.computeShader.description: Converte uma imagem para escala de cinza com um dispatch de computação e exibe a textura resultante. Demonstra handles de recursos para uma textura de entrada amostrada e uma textura de saída gravável, contagens de grupos de threads arredondadas para cima e uma verificação de limites no shader. Mantenha o recurso {assetsTexturesShokoPng} incluído; o renderizador o processa uma vez e apresenta o resultado nos quadros subsequentes. +concepts.synchronization.dependencies.table.pipelineStages.situation: "Estágios dependentes da GPU em um fluxo de comandos" +concepts.synchronization.dependencies.title: "Dependências de acesso" +concepts.synchronization.description: "A sincronização estabelece a ordem de acesso aos dados compartilhados e garante que operações posteriores vejam os resultados necessários. Em uma dependência de escrita para leitura, quem escreve é o produtor e quem lê é o consumidor. Barreiras e transições de textura coordenam os acessos da GPU; linhas do tempo conectam envios e permitem que a CPU espere a conclusão do trabalho na GPU." +concepts.synchronization.layouts.context: "Use {undefined} como layout anterior quando o conteúdo existente puder ser descartado, como em uma imagem nova ou em um anexo que será limpo por completo. Para preservar o conteúdo para carregamento, amostragem ou acumulação, informe o layout do acesso anterior." +concepts.synchronization.layouts.description: "Os indicadores de uso declaram as funções permitidas da textura. {textureLayout} descreve o acesso a um sub-recurso, identificado pelo nível de mip e pela camada do array de texturas, em determinado ponto da sequência de comandos. Quando esse acesso mudar, registre uma transição. No exemplo de computação, a textura de saída é escrita em layout {storage} e depois preparada para amostragem em uma passagem gráfica:" +concepts.synchronization.layouts.details: "Aqui, {outputTexture} foi criada com uso {sampledStorage}, e o sub-recurso selecionado está em {storage}. {default} seleciona o nível de mip 0 e a camada 0. A transição não afeta outros níveis ou camadas." +concepts.synchronization.layouts.guidance: "Em {transition}, informe o layout do uso anterior do sub-recurso. A aplicação acompanha esse estado ao registrar comandos e passar texturas entre as etapas de renderização." +concepts.synchronization.layouts.title: "Layouts de textura" +concepts.synchronization.readback.description: "{isCompleted} informa a conclusão na GPU. Um download registrado tem uma etapa adicional: copiar o resultado da área interna de leitura para a memória de destino da aplicação." +concepts.synchronization.readback.details: "{commandBufferDownload} registra a cópia da GPU para essa área interna. Quando o envio termina, a biblioteca realiza a cópia na CPU ao recuperar o buffer de comandos concluído. Chamar {wait} no valor de envio do download espera a GPU e processa os buffers concluídos daquela fila, completando as duas etapas. Mantenha o destino alocado e a memória gerenciada fixada até o retorno da chamada." +concepts.synchronization.readback.guidance: "Consultar apenas {isCompleted} não executa a cópia final na CPU. Esperar em outra fila também não recupera os buffers concluídos da fila do download. {link} descreve quando uploads e downloads usam acesso direto à memória ou armazenamento temporário de transferência." +concepts.synchronization.readback.guidance.link: "Gerenciamento de recursos" +concepts.synchronization.readback.title: "Conclusão da leitura de dados" +concepts.synchronization.reuse.description: "O triângulo espera cada quadro terminar antes de reutilizar seus dados. Para sobrepor quadros, reserve armazenamento mutável próprio para cada quadro em andamento e acompanhe quando ele volta a estar disponível. Antes de modificar dados, espere o trabalho da GPU que ainda acessa os bytes afetados; antes de liberar um recurso, espere todos os seus usos pendentes." +concepts.synchronization.reuse.details: "Redimensionamento e encerramento seguem a mesma regra: impedir novos usos, esperar os existentes terminarem e então substituir ou liberar os recursos. Respeite essa ordem antes de chamar {swapChainResize} ou liberar recursos ou o contexto. Como o triângulo já espera a cada quadro, ele pode redimensionar entre as chamadas dos callbacks." +concepts.synchronization.reuse.guidance: "{swapChainPresent} sinaliza um ponto da fila gráfica e espera por ele após a apresentação. Assim, o triângulo continua esperando ao apresentar, mesmo sem a espera explícita do envio. O trabalho independente em outras filas precisa de seu próprio acompanhamento de conclusão." +concepts.synchronization.reuse.title: "Reutilização de recursos" +concepts.synchronization.timelines.context: "Se a CPU precisar ler o resultado, sobrescrever os dados compartilhados ou liberar os recursos após o consumidor terminar, espere esse envio:" +concepts.synchronization.timelines.description: "Uma linha do tempo identifica a conclusão na fila por valores crescentes. {submit} retorna um {timelineValue} contendo a linha do tempo e o valor do envio. Campos {value} de linhas do tempo distintas não são diretamente comparáveis." +concepts.synchronization.timelines.details: "Considere {producer} e {consumer}, buffers já gravados em duas filas do mesmo contexto, com o consumidor usando dados escritos pelo produtor. Envie-os com esta dependência:" +concepts.synchronization.timelines.guidance: "A fila consumidora espera o valor de conclusão recebido antes de executar seus comandos. A CPU pode continuar sem chamar {producedWait}. Mantenha os recursos compartilhados vivos até a conclusão de {consumed} e registre as transições de textura necessárias ao acesso do consumidor." +concepts.synchronization.timelines.notes: "O valor retornado por {queueTimelineSignal} também pode ser usado para esperar com {wait} ou estabelecer uma dependência para outra fila. {signal} coloca esse ponto de conclusão depois do trabalho já enviado; a GPU o alcança quando esse trabalho termina." +concepts.synchronization.timelines.title: "Linhas do tempo e dependências entre filas" +concepts.synchronization.title: "Sincronização" +home.actions.reference: "Navegar na API" +home.actions.tutorial: "Começar com um triângulo" +home.entries.description: "Tutoriais, exemplos e referência da API" +home.entries.label: "Seções da documentação" +home.entries.reference.action: "Explorar a API" +home.entries.reference.category: "Referência" +home.entries.reference.description: "Consulte tipos, membros e declarações da API" +home.entries.reference.title: "Referência da API" +home.entries.samples.action: "Procurar exemplos" +home.entries.samples.category: "Exemplos" +home.entries.samples.description: "Exemplos executáveis de técnicas gráficas e de computação" +home.entries.samples.title: "Exemplos" +home.entries.title: "Documentação" +home.entries.tutorial.action: "Iniciar tutorial" +home.entries.tutorial.category: "Tutorial" +home.entries.tutorial.description: "De um projeto vazio ao primeiro triângulo na tela" +home.entries.tutorial.title: "Primeiro triângulo" +home.introduction.accent: "com .NET" +home.introduction.description: "Zenith.NET oferece uma API comum de gráficos e computação para DirectX, Metal e Vulkan" +home.introduction.title: "Gráficos multiplataforma{lineBreak}{accent}" +home.meta.description: "Gráficos e computação multiplataforma em .NET com uma API comum para DirectX, Metal e Vulkan" +home.scene.description: "Geometria interativa em rotação. Arraste ou use as teclas de direção para ajustar a visualização." +home.scene.label: "Exibição de geometria" +home.scene.surface: "Superfície" +home.scene.wireframe: "Wireframe" +home.title: "RHI moderna para .NET" +learning.concepts.description: "Critérios para escolher usos de recursos, descrever dados de shaders e coordenar a execução na GPU" +learning.concepts.execution.description: "Gravação de comandos, envio e tempo de vida dos recursos" +learning.concepts.platforms.description: "Apresentação nativa e controles de renderização" +learning.concepts.resources.description: "Usos de recursos, localização na memória e visualizações" +learning.concepts.shaders.description: "Convenções de layout e vinculação entre C# e Slang" +learning.concepts.synchronization.description: "Dependências, visibilidade e conclusão" +learning.concepts.title: "Conceitos fundamentais" +learning.description: "Comece pelo tutorial do triângulo para criar sua primeira aplicação. Depois, consulte os artigos sobre recursos, dados de shaders e sincronização, ou escolha um exemplo da técnica que deseja implementar." +learning.entries.samples.action: "Procurar exemplos" +learning.entries.samples.description: "Implementações em C# e Slang de geometria, computação, consultas de raios e sombreamento de malha" +learning.entries.tutorial.action: "Abrir tutorial" +learning.entries.tutorial.description: "Uma aplicação de console que abre uma janela e renderiza um triângulo" +learning.meta.description: "Tutoriais e fundamentos do modelo de programação de Zenith.NET" +learning.title: "Aprender" +reference.description: "Referência de recursos, comandos e integrações de plataforma" +reference.entries.commands.description: "Comandos gráficos, de computação e de transferência" +reference.entries.commands.label: "Registrar comandos" +reference.entries.context.description: "Criação de recursos da GPU no backend selecionado" +reference.entries.context.label: "Comece aqui" +reference.meta.description: "Namespaces, tipos e membros de Zenith.NET" +reference.navigation.core: "Referência da API principal" +reference.title: "Referência da API" +samples.computeShader.description: "O exemplo carrega {assetsTexturesShokoPng}, converte a imagem para tons de cinza em um despacho de computação e exibe a textura resultante. A conversão ocorre uma vez; os quadros seguintes exibem o mesmo resultado. O renderizador mostra como vincular texturas para amostragem e escrita, arredondar para cima as quantidades de grupos de threads para cobrir a imagem e verificar seus limites no shader." samples.computeShader.details: "{computeShaderRendererCs} · {computeShaderSlang}" -samples.computeShader.title: Shader de computação -samples.cube.description: Adiciona desenho indexado, matrizes de modelo, visualização e projeção em um buffer de constantes e teste de profundidade. A textura de profundidade é recriada no redimensionamento. Use ao passar de geometria em espaço de recorte para um objeto transformado; o renderizador usa um anexo de profundidade/estêncil {d32FloatS8UInt}. +samples.computeShader.title: "Shader de computação" +samples.cube.description: "O cubo acrescenta desenho indexado, matrizes de modelo, visão e projeção em um buffer de constantes e teste de profundidade. Sua textura de profundidade e estêncil {d32FloatS8UInt} é recriada no redimensionamento." samples.cube.details: "{spinningCubeRendererCs} · {spinningCubeSlang}" -samples.cube.title: Cubo giratório -samples.description: "Escolha um exemplo focado para o recurso que deseja estudar. Cada exemplo faz link com o renderizador em C# e seu respectivo shader em Slang. Comece com {link} se desejar uma aplicação completa explicada a partir de um projeto vazio." -samples.description.link: Primeiro triângulo -samples.execution.description: "{link} contém seis renderizadores independentes em uma única aplicação de desktop. Use o SDK do .NET 10 e um backend de desktop suportado, conforme descrito abaixo. Compile e execute a aplicação e, em seguida, escolha um exemplo no menu do console:" -samples.execution.description.link: ZenithTutorials -samples.execution.details: O host seleciona o DirectX 12 no Windows, Metal no macOS e Vulkan no Linux. Use um dispositivo, driver e ambiente de compilador de shader suportados pelo backend selecionado. O caminho de janelas do Linux requer X11 ou XWayland. O {link} declara as dependências de pacotes e copia os recursos de shader e textura necessários em tempo de execução. -samples.execution.details.link: arquivo de projeto -samples.execution.guidance: Os exemplos compartilham código de janelas e apresentação. Você pode escolher qualquer exemplo de forma independente com base no recurso que deseja estudar. -samples.execution.title: Executar os exemplos do tutorial -samples.host.description: "{appCs} cria o contexto, a janela e a cadeia de troca. Ele obtém um buffer de comandos, chama o renderizador selecionado, envia o quadro e o apresenta. {iRendererCs} define os métodos de atualização, renderização, redimensionamento e descarte do renderizador." -samples.host.details: Computação e traçado de raios produzem texturas fora da tela. {texturePresenterCs} e {presentTextureSlang} desenham essas texturas na textura de saída do quadro atual da janela. O host continua sendo o proprietário do envio e da apresentação da cadeia de troca. -samples.host.title: Host e apresentação compartilhados -samples.indirectDrawing.description: Desenha várias cópias de um cubo usando um buffer de argumentos indiretos indexados e dados por instância em um buffer estruturado. A CPU fornece os argumentos de desenho e atualiza as transformações. Use para compreender o layout de argumentos indiretos e o acesso de shaders a dados de instância antes de adicionar argumentos gerados pela GPU. +samples.cube.title: "Cubo giratório" +samples.description: "Cada exemplo reúne um renderizador C# e seu shader Slang em torno de uma técnica. Para a configuração completa da aplicação e a sequência de renderização, comece por {link}." +samples.description.link: "Primeiro triângulo" +samples.execution.description: "Execute o projeto {link} e escolha um exemplo no menu do console." +samples.execution.description.link: "ZenithTutorials" +samples.execution.title: "Execução dos exemplos" +samples.host.description: "{appCs} inicializa contexto, janela e cadeia de troca. A cada quadro, obtém um buffer de comandos, chama o renderizador selecionado, envia os comandos e apresenta o resultado. {iRendererCs} define as operações de atualização, renderização, redimensionamento e liberação." +samples.host.details: "Os renderizadores de computação e traçado de raios produzem texturas fora da tela. {texturePresenterCs} e {presentTextureSlang} desenham essas texturas na saída do quadro atual; em seguida, o programa hospedeiro compartilhado envia os comandos e apresenta o quadro." +samples.host.title: "Programa hospedeiro e apresentação" +samples.indirectDrawing.description: "O desenho indireto renderiza várias instâncias de cubos a partir de um buffer de argumentos de desenho indexado e de um buffer estruturado de dados por instância. A CPU fornece os argumentos e atualiza as transformações." samples.indirectDrawing.details: "{indirectDrawingRendererCs} · {indirectDrawingSlang}" -samples.indirectDrawing.title: Desenho indireto -samples.meshShading.description: Usa um task shader para descartar instâncias de esferas e passar seus índices para um mesh shader que emite geometria. O renderizador verifica {contextCapabilitiesMeshShadingSupported} antes de criar sua pipeline. Use para rastrear handles de recursos e dados de payload através dos estágios de tarefa e malha. +samples.indirectDrawing.title: "Desenho indireto" +samples.meshShading.description: "Um shader de tarefa descarta as instâncias de esferas não visíveis e passa os índices restantes ao shader de malha, que gera a geometria. O renderizador verifica {contextCapabilitiesMeshShadingSupported} antes de criar o pipeline." samples.meshShading.details: "{meshShadingRendererCs} · {meshShadingSlang}" -samples.meshShading.title: Sombreamento de malhas -samples.rayTracing.description: Cria estruturas de aceleração de nível inferior e superior para um chão e esferas procedurais e, em seguida, executa consultas de raios em linha em um shader de computação. O renderizador verifica {contextCapabilitiesRayTracingSupported} antes de construir a carga de trabalho. Use este exemplo para entradas de estrutura de aceleração e travessia de raios no lado do shader. +samples.meshShading.title: "Sombreamento de malha" +samples.rayTracing.description: "O exemplo cria estruturas de aceleração de nível inferior e superior para um piso e esferas procedurais e realiza consultas de raios em um shader de computação. Verifica {contextCapabilitiesRayTracingSupported} antes da inicialização." samples.rayTracing.details: "{rayTracingRendererCs} · {rayTracingSlang}" -samples.rayTracing.title: Traçado de raios -samples.title: Exemplos -samples.triangle.description: Cria um buffer de vértices e um layout de entrada correspondente e, em seguida, desenha três vértices por meio de uma pipeline gráfica. Use para conectar a criação de recursos com os comandos em uma passagem de renderização. +samples.rayTracing.title: "Traçado de raios" +samples.title: "Exemplos" +samples.triangle.description: "O triângulo associa um buffer de vértices ao layout de entrada correspondente e desenha três vértices por um pipeline gráfico." samples.triangle.details: "{helloTriangleRendererCs} · {helloTriangleSlang} · {link}" -samples.triangle.details.link: Tutorial completo -samples.triangle.title: Olá triângulo -samples.workloads.description: "O {link} do repositório principal contém aplicações que combinam vários recursos. Seus projetos fazem referência ao código-fonte da biblioteca. A partir de um clone do Zenith.NET, execute o projeto escolhido, por exemplo:" -samples.workloads.description.link: diretório Experiments -samples.workloads.details: Os experimentos com janelas usam as mesmas opções de host para Windows, macOS e Linux/X11. Para desenhar dentro de Avalonia, WinForms, WPF, WinUI/Uno ou MAUI, consulte {link} para obter informações sobre o ciclo de vida do quadro do controle e links de implementação. -samples.workloads.details.link: Integração de plataforma +samples.triangle.details.link: "Tutorial completo" +samples.triangle.title: "Olá triângulo" +samples.workloads.description: "O {link} do repositório principal contém aplicações de maior porte que referenciam o código-fonte da biblioteca." +samples.workloads.description.link: "diretório Experiments" +samples.workloads.details: "Os experimentos com janela usam os mesmos mecanismos de apresentação em Windows, macOS e Linux/X11. {link} trata dos controles para Avalonia, WinForms, WPF, WinUI/Uno e MAUI, incluindo o ciclo dos quadros e as implementações." +samples.workloads.details.link: "Integração de plataforma" samples.workloads.table.cornellBox.example: "{link}" -samples.workloads.table.cornellBox.example.link: CornellBox -samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: Traçado de caminhos, redução de ruído, mapeamento de tons, upscaling e controles ImGui. Requer suporte a traçado de raios e o ambiente de compilação de shaders para seu backend de desktop. +samples.workloads.table.cornellBox.example.link: "CornellBox" +samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: "Traçado de caminhos, redução de ruído, mapeamento de tons, ampliação de resolução e controles ImGui. Requer suporte a traçado de raios." samples.workloads.table.fluidTank.example: "{link}" -samples.workloads.table.fluidTank.example.link: FluidTank -samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: Simulação de fluidos por computação, dependências entre estágios de simulação e renderização de superfície em várias passagens. Requer seu backend de desktop e o ambiente de compilação de shaders. -samples.workloads.table.headings.example: Exemplo -samples.workloads.table.headings.whatItDemonstratesAndRequires: O que demonstra e o que requer +samples.workloads.table.fluidTank.example.link: "FluidTank" +samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: "Simulação de fluidos por computação, dependências entre estágios de simulação e renderização de superfície em várias passagens." +samples.workloads.table.headings.example: "Exemplo" +samples.workloads.table.headings.whatItDemonstratesAndRequires: "Técnicas e requisitos" samples.workloads.table.inkCanvas.example: "{link}" -samples.workloads.table.inkCanvas.example.link: InkCanvas -samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: Desenho com Skia e tratamento de entrada em uma janela nativa. Requer o backend e a biblioteca nativa do Skia para a plataforma de destino. +samples.workloads.table.inkCanvas.example.link: "InkCanvas" +samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: "Desenho com Skia e tratamento de entrada em uma janela nativa. Requer o backend e a biblioteca nativa do Skia para a plataforma de destino." samples.workloads.table.platformDetection.example: "{link}" -samples.workloads.table.platformDetection.example.link: PlatformDetection -samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: Tenta a criação de contexto para cada backend e relata os recursos do dispositivo. Se a criação do contexto falhar, ela será relatada como não suportada; esse resultado também pode indicar um driver ausente ou dependência de tempo de execução não atendida. -samples.workloads.title: Explorar cargas de trabalho maiores -tutorial.context.description: A janela agora pode abrir, mas ainda não criamos os objetos de GPU que renderizarão nela. Um {graphicsContext} fornece acesso ao backend gráfico selecionado e às suas filas de comandos. -tutorial.context.details: "Insira este bloco {emphasis}:" -tutorial.context.details.emphasis: após as diretivas using, antes de {iWindowWindow} -tutorial.context.guidance: Os branches selecionam DirectX 12 no Windows, Metal no macOS e Vulkan no Linux. O código de renderização a seguir usa a API compartilhada do Zenith.NET. Solicitamos validação durante o desenvolvimento e exibimos as mensagens relatadas por meio de {validationMessage}. Os diagnósticos dependem do backend e dos componentes de validação disponíveis na máquina. -tutorial.context.title: Criar o contexto gráfico -tutorial.description: Crie uma aplicação de console .NET que abre uma janela e desenha um triângulo com um gradiente de cor suave. Você aprenderá como dados de vértices, shaders e estado de pipeline funcionam juntos e, em seguida, gravará e enviará os comandos que produzem a imagem. -tutorial.details: Siga as seções em ordem. Primeiro você abrirá uma janela vazia, depois exibirá uma cor de fundo e, finalmente, desenhará o triângulo. Cada ponto de verificação confirma uma parte da aplicação antes de você adicionar a próxima. A inicialização é executada uma vez; o callback de renderização grava um novo quadro a cada chamada. +samples.workloads.table.platformDetection.example.link: "PlatformDetection" +samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: "Tenta criar um contexto para cada backend e informa as capacidades do dispositivo. Uma tentativa que falha é indicada como não compatível; a causa pode estar no dispositivo, no driver ou em uma dependência de execução ausente." +samples.workloads.title: "Aplicações de maior porte" +tutorial.context.description: "Um {graphicsContext} conecta a aplicação à GPU por meio de um backend e fornece os métodos para criar os recursos de renderização." +tutorial.context.details: "Insira a inicialização do contexto {emphasis}:" +tutorial.context.details.emphasis: "após as diretivas using, antes de {iWindowWindow}" +tutorial.context.guidance: "Cada ramo seleciona o backend da plataforma e solicita a validação. As mensagens de {validationMessage} são exibidas no console." +tutorial.context.imports: "Adicione as seguintes diretivas using no início de {programCs}:" +tutorial.context.title: "Contexto gráfico" +tutorial.description: "Neste tutorial, um projeto de console .NET vazio se torna uma aplicação que abre uma janela e desenha um triângulo colorido." +tutorial.details: "O tutorial tem três pontos de verificação: uma janela vazia, um fundo de cor uniforme e o triângulo colorido. Execute a aplicação em cada ponto antes de acrescentar a próxima parte." tutorial.draw.context: "Os argumentos para {draw} são:" -tutorial.draw.description: "No callback {windowRender}, substitua {addTheTriangleDrawCommandsHereLater} por estes três comandos, entre {beginRenderPass} e {endRenderPass}:" -tutorial.draw.details: "{setPipeline} seleciona os shaders e o estado que acabamos de criar. Defina-o antes de vincular dados de vértices: o backend usa o layout de entrada da pipeline para interpretar a vinculação." -tutorial.draw.guidance: "{setVertexBufferVertexBuffer} vincula o buffer a partir do deslocamento de byte 0 ao slot de entrada 0. Esse slot corresponde à entrada única em {inputLayouts}. Ele não copia nem envia os dados novamente." -tutorial.draw.notes: Os comandos continuam sendo apenas gravados neste ponto. As chamadas {submitWait} e {present} já presentes no final do callback de renderização executam o trabalho e exibem o resultado. A limpeza continua necessária porque o triângulo cobre apenas parte da imagem; o fundo também deve receber uma cor definida a cada quadro. -tutorial.draw.table.firstInstance.meaning: Iniciar a numeração de instâncias em zero. -tutorial.draw.table.firstVertex.meaning: Começar com o primeiro vértice no buffer. -tutorial.draw.table.headings.argument: Argumento -tutorial.draw.table.headings.description: Valor -tutorial.draw.table.headings.meaning: Significado -tutorial.draw.table.instanceCount.meaning: Desenhar uma cópia do triângulo. -tutorial.draw.table.vertexCount.meaning: Ler três vértices. -tutorial.draw.title: Desenhar o triângulo dentro da passagem -tutorial.execution.description: "Compile e execute a partir do diretório {firstTriangle}:" -tutorial.execution.details: A janela deve exibir um triângulo com um canto superior vermelho, um canto inferior direito verde e um canto inferior esquerdo azul contra um fundo escuro. O interior deve exibir um gradiente suave entre essas cores. -tutorial.execution.guidance: Redimensione a janela. O callback de redimensionamento atualiza as dimensões do framebuffer e redimensiona a cadeia de troca. A passagem de renderização estabelece uma viewport que corresponde a essa imagem. Como as posições dos vértices permanecem em coordenadas normalizadas, o triângulo mantém a mesma fração da largura e altura da janela; alterar a proporção da tela pode esticar sua forma. Preservar a proporção de um objeto requer uma política de projeção ou viewport, o que está além deste primeiro desenho. -tutorial.execution.title: Executar, redimensionar e fechar -tutorial.frame.commands.context: Após {endRenderPass}, a segunda transição prepara a imagem para apresentação. {submit} conclui a gravação e envia o buffer de comandos; {wait} aguarda a GPU concluir esse envio. {present} então solicita a exibição da imagem renderizada. -tutorial.frame.commands.description: Uma passagem de renderização agrupa operações de desenho que usam os mesmos anexos. Aqui, o anexo de cor é a textura de saída da cadeia de troca, a imagem que recebe nosso desenho. {colorAttachmentClear} cria uma descrição instruindo a passagem a limpar para a cor RGBA especificada e manter o resultado quando a passagem terminar. {beginRenderPass} grava essas instruções; a GPU realiza a limpeza após o envio dos comandos. -tutorial.frame.commands.details: Os colchetes contêm nosso único anexo de cor. O argumento {null} significa que não há anexo de profundidade/estêncil, que armazenaria valores de profundidade e máscaras de estêncil para testes de profundidade e estêncil. -tutorial.frame.commands.guidance: "{beginRenderPass} define uma viewport e um retângulo de recorte (scissor) que cobrem o anexo. A viewport mapeia as coordenadas renderizadas para pixels, e o retângulo de recorte limita quais pixels podem ser gravados. Esses padrões cobrem toda a textura de saída, como necessário para este triângulo." -tutorial.frame.commands.title: Limpar, enviar e apresentar -tutorial.frame.description: Primeiro preencha a imagem com uma única cor de fundo. Essa operação é chamada de limpeza (clear). Se essa cor aparecer na janela, a superfície, o envio de comandos e o caminho de apresentação estão funcionando juntos. Esse ponto de verificação permite testar o loop de quadros antes de adicionar geometria e shaders. -tutorial.frame.details: "Um callback de renderização é um código que o Silk.NET chama quando é hora de desenhar um quadro. Esse callback não precisa do argumento de tempo decorrido do evento, portanto é chamado de {value}. Registre-o {emphasis}:" -tutorial.frame.details.emphasis: antes de {windowRun} -tutorial.frame.target.description: "{graphicsQueueCommandBuffer} obtém um buffer de comandos com a gravação já iniciada. A gravação descreve o trabalho para a GPU; ela não executa esse trabalho imediatamente." -tutorial.frame.target.details: A primeira {transition} prepara a textura de saída para acesso como anexo de cor. {default} seleciona o nível mip 0 e a camada de array 0. Usamos {undefined} como layout anterior porque limparemos toda a imagem e descartaremos seu conteúdo anterior. Uma passagem que precisa preservar o conteúdo existente deve usar seu layout anterior real. -tutorial.frame.target.guidance: Use a textura de saída atual da cadeia de troca a cada quadro. A apresentação pode alterar qual imagem está disponível, portanto uma textura salva de um quadro anterior não é um destino de renderização permanente da janela. -tutorial.frame.target.title: Preparar a textura de saída -tutorial.frame.title: Exibir uma cor de fundo -tutorial.geometry.data.description: Adicione este array {emphasis}. As seguintes etapas de criação de recursos também pertencem ao trecho anterior a esse callback, na ordem mostrada. -tutorial.geometry.data.description.emphasis: antes de {windowRender} -tutorial.geometry.data.details: "Cada entrada do array cria um {vertex}. As duas expressões {new} internas criam sua posição {vector3} e sua cor {vector4}. Os vértices descrevem os cantos superior, inferior direito e inferior esquerdo. O vertex shader fornecerá uma quarta coordenada de posição, {w}. Com w igual a 1, x e y descrevem diretamente coordenadas normalizadas do dispositivo: -1 e +1 são as bordas da imagem, e 0 é o centro. Essas coordenadas não dependem das dimensões em pixels da janela." -tutorial.geometry.data.guidance: Cada cor contém componentes vermelho, verde, azul e alfa. Alfa é 1 em todos os três cantos. Todas as três posições têm z = 0, colocando-as no mesmo plano. Essas posições não precisam de câmera ou matriz de transformação porque já descrevem as coordenadas que queremos renderizar. Para este triângulo plano único, também desativaremos a mesclagem e o teste de profundidade e omitiremos um buffer de profundidade. -tutorial.geometry.data.title: Escolher os cantos -tutorial.geometry.description: Um vértice é um ponto acompanhado dos dados usados para desenhá-lo. Nosso triângulo tem três vértices, um para cada canto. Cada um contém uma posição e uma cor. A GPU interpolará as cores, calculando valores intermediários ao longo do triângulo. -tutorial.geometry.format.description: "Anexe esta declaração {emphasis}:" -tutorial.geometry.format.description.emphasis: no final de {programCs}, após as instruções de limpeza -tutorial.geometry.format.details: "{file} limita este tipo a {programCs}, e o construtor inicializa seus campos de posição e cor. {layoutKindSequential} mantém os campos na ordem de declaração. {position} contém três floats de 32 bits e {color} contém quatro. Nesta struct, a posição começa no byte 0, a cor começa no byte 12 e o vértice completo ocupa 28 bytes. Descreveremos esse mesmo layout para a pipeline gráfica." -tutorial.geometry.format.title: Definir um vértice -tutorial.geometry.title: Fornecer três vértices à GPU -tutorial.geometry.upload.context: "{fixed} impede que o coletor de lixo mova o array enquanto seu endereço está sendo usado. Para este buffer gravável pela CPU, {upload} mapeia, copia e desmapeia a memória antes de retornar, para que o array não precise permanecer fixado posteriormente. O buffer deve permanecer ativo durante toda a renderização, e o envio só precisa ocorrer uma vez porque os vértices não mudam." -tutorial.geometry.upload.description: "O array gerenciado é dado da CPU. Um {buffer} fornece à GPU armazenamento do qual ela pode ler os vértices. Após o array, adicione:" -tutorial.geometry.upload.details: "O tamanho total é {sizeofVertexVerticesLength}: 28 bytes por vértice, três vértices, 84 bytes no total. {bufferUsagesVertex} permite o acesso de entrada de vértices. {cpuWriteOnly} permite que a CPU inicialize esse pequeno buffer diretamente. O stride do descritor registra o tamanho do elemento; o layout de entrada que criaremos a seguir informará ao fetch de vértices como ler os atributos individuais." -tutorial.geometry.upload.guidance: Criar um buffer não o preenche. {upload} copia o array para essa alocação a partir do deslocamento de byte de destino 0. Sua descrição de origem fornece um ponteiro e o número de bytes a serem copiados. -tutorial.geometry.upload.notes: Adicione {vertexBufferDispose} imediatamente antes de {swapChainDispose} na limpeza na parte inferior de {programCs}. Para geometrias estáticas maiores, {link} explica quando escolher armazenamento exclusivo de GPU e transferências de upload. -tutorial.geometry.upload.notes.link: Gerenciamento de recursos -tutorial.geometry.upload.title: Alocar um buffer e enviar o array -tutorial.input.description: "Os bytes dos vértices e os shaders estão prontos. A seguir, descreva como a GPU deve ler cada vértice. Um atributo é um valor único, como posição ou cor. O layout de entrada fornece a cada atributo um formato e um deslocamento de bytes; o stride fornece a distância em bytes de um vértice ao próximo. Adicione este bloco de inicialização após a criação do shader:" -tutorial.input.details: "{inputLayoutAdd} anexa um elemento no stride atual e aumenta esse stride pelo tamanho do elemento. Ele não inspeciona a struct C#. Aqui ele produz a seguinte correspondência entre a memória da CPU e as entradas do shader:" -tutorial.input.guidance: "Alterar a ordem dos campos C# ou o padding sem atualizar esta descrição faria com que a GPU lesse os bytes errados. O {semanticIndex} padrão é zero, correspondendo a {pOSITION0} e {cOLOR0}. Ambos os elementos pertencem ao mesmo buffer, portanto a pipeline conterá um layout de entrada e vincularemos esse buffer ao slot 0." -tutorial.input.table.headings.byteOffset: Deslocamento de bytes +tutorial.draw.description: "No callback {windowRender}, substitua {addTheTriangleDrawCommandsHereLater} pelos comandos abaixo, entre {beginRenderPass} e {endRenderPass}:" +tutorial.draw.details: "{setPipeline} seleciona shaders e estado de renderização. Deve preceder o vínculo dos vértices, pois o backend interpreta esse vínculo conforme o layout de entrada do pipeline." +tutorial.draw.guidance: "{setVertexBufferVertexBuffer} vincula os dados de vértices já transferidos, a partir do deslocamento de byte 0, ao slot de entrada 0, correspondente à única entrada de {inputLayouts}." +tutorial.draw.notes: "Essas chamadas registram os comandos de desenho. A chamada existente a {submitWait} os envia e espera a GPU terminar; em seguida, {present} solicita a exibição da imagem concluída. Mantenha a limpeza no início da passagem para definir a cor de fundo na área externa ao triângulo." +tutorial.draw.table.firstInstance.meaning: "Iniciar a numeração de instâncias em zero." +tutorial.draw.table.firstVertex.meaning: "Começar com o primeiro vértice no buffer." +tutorial.draw.table.headings.argument: "Argumento" +tutorial.draw.table.headings.description: "Valor" +tutorial.draw.table.headings.meaning: "Significado" +tutorial.draw.table.instanceCount.meaning: "Desenhar uma cópia do triângulo." +tutorial.draw.table.vertexCount.meaning: "Ler três vértices." +tutorial.draw.title: "Comandos de desenho" +tutorial.execution.description: "Compile e execute o projeto {firstTriangle}." +tutorial.execution.details: "A janela deve exibir um triângulo sobre fundo escuro, vermelho no alto, verde embaixo à direita e azul embaixo à esquerda. A interpolação das cores dos vértices forma um gradiente suave em seu interior." +tutorial.execution.guidance: "O redimensionamento muda as dimensões da imagem em pixels, mas mantém as coordenadas dos vértices. O viewport ajusta essas coordenadas à nova largura e altura, por isso o triângulo se deforma quando a proporção da janela muda." +tutorial.execution.title: "Execução da aplicação" +tutorial.frame.commands.context: "Após {endRenderPass}, a segunda transição prepara a textura de saída para apresentação. {submit} encerra o registro e envia o buffer de comandos; {wait} bloqueia a thread até a conclusão desse envio. Em seguida, {present} solicita a exibição da imagem renderizada." +tutorial.frame.commands.description: "Uma passagem de renderização reúne operações de desenho que escrevem nos mesmos anexos. Nesta passagem, a textura de saída da cadeia de troca recebe a cor. {colorAttachmentClear} descreve como inicializar esse anexo com uma cor RGBA e preservar seu conteúdo ao encerrar a passagem. {beginRenderPass} registra o início da passagem com essas configurações." +tutorial.frame.commands.details: "A coleção contém um anexo de cor. {null} indica que a passagem não possui anexo de profundidade e estêncil." +tutorial.frame.commands.guidance: "{beginRenderPass} ajusta o viewport e a região de recorte para todo o anexo. O viewport converte coordenadas de renderização em posições de pixels; o recorte limita a região em que se pode escrever." +tutorial.frame.commands.title: "Limpeza, envio e apresentação" +tutorial.frame.description: "Comece preenchendo a janela com uma cor de fundo. Essa operação é chamada de limpeza. Quando o fundo aparece, a superfície, o envio de comandos e a apresentação já funcionam juntos. A partir daí, acrescente os vértices e os shaders do triângulo." +tutorial.frame.details: "Silk.NET chama o callback quando há um quadro a renderizar. Como o exemplo não usa o argumento de tempo decorrido, o parâmetro se chama {value}. Registre o callback {emphasis}:" +tutorial.frame.details.emphasis: "antes de {windowRun}" +tutorial.frame.target.description: "{graphicsQueueCommandBuffer} retorna um buffer pronto para gravação. Gravar define o trabalho da GPU; sua execução só começa após o envio." +tutorial.frame.target.details: "O layout de uma textura descreve o acesso necessário a uma operação. A primeira chamada a {transition} prepara a textura de saída para uso como anexo de cor. Aqui, {default} seleciona o nível de mip 0 e a camada 0 do array, ou seja, a imagem base da textura. Como a passagem limpa a imagem inteira, {undefined} permite descartar o conteúdo anterior." +tutorial.frame.target.guidance: "Obtenha a textura de saída atual a cada quadro, pois a apresentação pode passar a usar outra imagem." +tutorial.frame.target.title: "Preparação da textura de saída" +tutorial.frame.title: "O primeiro quadro" +tutorial.geometry.data.description: "Adicione o array de vértices {emphasis}. Mantenha também as próximas inicializações de recursos antes desse callback, na ordem apresentada." +tutorial.geometry.data.description.emphasis: "antes de {windowRender}" +tutorial.geometry.data.details: "Cada entrada constrói um {vertex}; os dois {new} internos fornecem a posição {vector3} e a cor {vector4}. As posições formam os cantos superior, inferior direito e inferior esquerdo. O shader de vértices acrescenta {w} como quarta coordenada. Com w igual a 1, x e y também são coordenadas normalizadas de dispositivo: -1 e +1 marcam os limites da imagem, e 0, o centro. Sua interpretação independe da quantidade de pixels." +tutorial.geometry.data.guidance: "Cada cor tem componentes vermelho, verde, azul e alfa, com alfa igual a 1. Os três vértices têm z = 0 e estão no mesmo plano." +tutorial.geometry.data.title: "Posições e cores dos vértices" +tutorial.geometry.description: "Cada um dos três vértices tem posição e cor. A GPU determina a forma do triângulo a partir das posições e interpola as cores em sua superfície." +tutorial.geometry.format.description: "Acrescente a declaração do vértice {emphasis}:" +tutorial.geometry.format.description.emphasis: "no final de {programCs}, após as instruções de limpeza" +tutorial.geometry.format.details: "{file} restringe o tipo a {programCs}, e {layoutKindSequential} mantém os campos na ordem de declaração. {position} contém três valores de ponto flutuante de 32 bits e começa no deslocamento de byte 0; {color} contém quatro e começa no deslocamento de byte 12. Cada vértice ocupa, portanto, 28 bytes. O layout de entrada descreverá essa organização para que a GPU leia os campos corretamente." +tutorial.geometry.format.imports: "Adicione estas diretivas using no início de {programCs} para usar os tipos vetoriais e o atributo de layout da estrutura:" +tutorial.geometry.format.title: "Representação dos vértices" +tutorial.geometry.title: "Dados de vértices" +tutorial.geometry.upload.context: "{fixed} impede que o coletor de lixo mova o array enquanto seu endereço estiver em uso. Neste buffer gravável pela CPU, {upload} mapeia a memória, copia os bytes e desfaz o mapeamento antes de retornar. O array só precisa permanecer fixado durante a chamada. Envie os vértices uma vez na inicialização e mantenha o buffer vivo até o fim da renderização." +tutorial.geometry.upload.description: "Armazene os vértices em um {buffer} para que a GPU possa lê-los durante o desenho. Acrescente a alocação e o envio dos dados logo após o array:" +tutorial.geometry.upload.details: "O tamanho é {sizeofVertexVerticesLength}: três vértices de 28 bytes, ou 84 bytes. {bufferUsagesVertex} declara o uso como entrada de vértices, e {cpuWriteOnly} permite a inicialização direta pela CPU. O passo do descritor registra o tamanho do elemento. O layout definido adiante especifica como cada atributo será lido." +tutorial.geometry.upload.guidance: "A alocação não inicializa o conteúdo do buffer. {upload} copia o array para o deslocamento 0 do destino, usando o ponteiro de origem e a quantidade de bytes da descrição de dados." +tutorial.geometry.upload.imports: "Em {programCs}, adicione {bufferAlias} às diretivas using para distinguir o tipo de buffer do Zenith.NET de {systemBuffer}." +tutorial.geometry.upload.notes: "Na limpeza ao final de {programCs}, insira {vertexBufferDispose} imediatamente antes de {swapChainDispose}. {link} trata do armazenamento exclusivo da GPU e de transferências para geometria estática maior." +tutorial.geometry.upload.notes.link: "Gerenciamento de recursos" +tutorial.geometry.upload.title: "Alocação e transferência do buffer" +tutorial.input.description: "A GPU precisa saber onde estão os atributos de cada vértice, como posição e cor. O layout de entrada fornece o formato e o deslocamento de cada atributo, além do passo: a distância em bytes até o próximo vértice. Adicione este código após criar os shaders:" +tutorial.input.details: "{inputLayoutAdd} coloca cada atributo após o anterior e soma seu tamanho ao passo entre vértices. Os deslocamentos são calculados a partir dos formatos informados, sem inspecionar a estrutura C#. Para esses dois campos, o resultado é:" +tutorial.input.guidance: "O valor padrão de {semanticIndex} é zero, correspondente a {pOSITION0} e {cOLOR0} no shader. Posição e cor ficam juntas em um buffer de vértices, portanto o pipeline utiliza um único layout de entrada no slot 0. Se a ordem dos campos ou o preenchimento da estrutura C# mudar, ajuste também esse layout." +tutorial.input.table.headings.byteOffset: "Deslocamento de bytes" tutorial.input.table.headings.cField: "Campo C#" -tutorial.input.table.headings.format: Formato -tutorial.input.table.headings.shaderInput: Entrada do shader -tutorial.input.table.nextVertex.cField: Próximo vértice -tutorial.input.table.nextVertex.format: "Stride total: 28 bytes" -tutorial.input.table.nextVertex.shaderInput: Próximo registro de entrada +tutorial.input.table.headings.format: "Formato" +tutorial.input.table.headings.shaderInput: "Entrada do shader" +tutorial.input.table.nextVertex.cField: "Próximo vértice" +tutorial.input.table.nextVertex.format: "Passo total: 28 bytes" +tutorial.input.table.nextVertex.shaderInput: "Próximo registro de entrada" tutorial.input.table.vertexColor.format: "{float4} (16 bytes)" tutorial.input.table.vertexPosition.format: "{float3} (12 bytes)" -tutorial.input.title: Descrever o layout de entrada de vértices -tutorial.lifecycle.description: "A aplicação concluída repete esta sequência:" -tutorial.lifecycle.details: "Fechar a janela retorna de {run}. Cada quadro renderizado já aguardou a conclusão de seu trabalho de GPU, portanto agora podemos descartar os recursos usados. A limpeza após {windowRun} deve ser:" -tutorial.lifecycle.guidance: "Libere a cadeia de troca antes da janela nativa e o contexto depois de todos os seus recursos. A fila possui e recicla os buffers de comandos enviados; a cadeia de troca possui sua textura de saída. Esses buffers de comandos e essa textura não precisam de uma chamada {dispose} separada nesta aplicação." -tutorial.lifecycle.title: Acompanhar o ciclo de vida de um quadro -tutorial.pipeline.behavior: "Após o layout de entrada, adicione:" -tutorial.pipeline.context: "{cullNone} preenche o triângulo sem descartar nenhuma orientação de face. A ordem de seus vértices determina a orientação da face, portanto desativar o descarte impede que essa ordem oculte nosso primeiro triângulo." -tutorial.pipeline.description: Agora temos dados de vértices, um layout de entrada e dois shaders. A {graphicsPipeline} os conecta e especifica como a GPU monta os vértices em primitivas e grava o resultado em um anexo. -tutorial.pipeline.details: "Uma pipeline combina estágios de shader programáveis com configurações de função fixa, que controlam operações de GPU como montagem de triângulos, descarte de faces (culling) e mesclagem. Para este triângulo, escolha estas configurações:" -tutorial.pipeline.guidance: O formato de cor vem de {swapChainDescFormat}. Ele deve corresponder à imagem usada pela passagem de renderização. {count1} significa uma amostra por pixel. -tutorial.pipeline.item: "{triangleList} monta cada grupo consecutivo de três vértices em um triângulo. Forneceremos três vértices e desenharemos uma vez, portanto nenhum buffer de índices é necessário." -tutorial.pipeline.notes: "{depthNone} desativa os testes e a gravação de profundidade, correspondendo à passagem sem anexo de profundidade." -tutorial.pipeline.reference: "{opaque} desativa a mesclagem, portanto a cor do fragment shader substitui o fundo dentro do triângulo." -tutorial.pipeline.title: Conectar os shaders e o layout de vértices -tutorial.pipeline.usage: Os objetos de shader podem ser descartados após a criação da pipeline, como feito no renderizador de exemplo. Mantenha a pipeline em si ativa para cada quadro desenhado com ela. Adicione {pipelineDispose} antes de {vertexBufferDispose} na limpeza. A criação da pipeline é a etapa final de inicialização antes do callback de renderização. -tutorial.pipeline.validation: A descrição da pipeline declara a configuração do anexo; ela não cria outra imagem. {inputLayouts} tem uma entrada porque a posição e a cor são armazenadas juntas em um único buffer. -tutorial.presentation.title: Conectar a GPU à janela -tutorial.project.context: Habilite {emphasis} ({allowUnsafeBlocks}) nas configurações de compilação do projeto. Nós o usaremos para passar dados de vértices para a GPU e para as chamadas nativas do assistente de janela. -tutorial.project.context.emphasis: Permitir código não seguro -tutorial.project.description: "Crie o projeto e entre no diretório:" -tutorial.project.details: "Instale os pacotes:" -tutorial.project.guidance: O {zenithNET} fornece a API de renderização compartilhada. Os três pacotes de backend permitem que o mesmo programa selecione a implementação para sua plataforma. O {zenithNETCompiler} compila shaders Slang, os pequenos programas de GPU que escreveremos mais tarde, para essa implementação. O Silk.NET fornece a janela e o loop de eventos. -tutorial.project.title: Criar um projeto de console -tutorial.requirements.context: Você pode acompanhar esta página a partir de um projeto vazio. O {link} e seu {detail} estão disponíveis como referência para as APIs de renderização e janelas usadas aqui. -tutorial.requirements.context.detail: host compartilhado -tutorial.requirements.context.link: exemplo Olá triângulo -tutorial.requirements.description: "Você precisa do {emphasis}, de um editor de código ou IDE e de um desktop com uma GPU e driver suportados por um backend do Zenith.NET. Familiaridade básica com C# é suficiente; os conceitos gráficos são introduzidos conforme são usados. Este é um projeto de console {net10} comum. Um backend traduz as operações do Zenith.NET em chamadas a uma API gráfica, como DirectX 12, Metal ou Vulkan. A aplicação escolhe uma na inicialização:" -tutorial.requirements.description.emphasis: SDK do .NET 10 -tutorial.requirements.details: O Linux precisa de uma sessão de janelas compatível com X11 para o caminho de janelas usado aqui. Recursos opcionais de traçado de raios e sombreamento de malhas não são necessários para este triângulo. -tutorial.requirements.guidance: O Zenith.NET renderiza em uma superfície fornecida pela aplicação. O Silk.NET.Windowing criará a janela de desktop e processará seus eventos. No macOS, o destino de apresentação é uma camada Metal ({cAMetalLayerCs}); o assistente de janela do tutorial anexa essa camada para nós. -tutorial.requirements.table.headings.graphicsBackend: Backend gráfico -tutorial.requirements.table.headings.platform: Plataforma -tutorial.requirements.table.headings.windowSurface: Superfície da janela -tutorial.requirements.table.linux.graphicsBackend: Vulkan 1.4 -tutorial.requirements.table.linux.platform: Linux -tutorial.requirements.table.linux.windowSurface: Janela e display X11; XWayland também é adequado -tutorial.requirements.table.macOS.graphicsBackend: Metal 4 -tutorial.requirements.table.macOS.platform: macOS -tutorial.requirements.table.macOS.windowSurface: Camada Metal anexada à janela -tutorial.requirements.table.windows.graphicsBackend: DirectX 12 -tutorial.requirements.table.windows.platform: Windows -tutorial.requirements.table.windows.windowSurface: Handle de janela Win32 -tutorial.requirements.title: Antes de começar -tutorial.resize.context: "Execute {dotnetRun} novamente. A janela agora deve ter um fundo escuro uniforme que continua a preenchê-la após o redimensionamento. Mantenha este callback: o triângulo será desenhado dentro de sua passagem de renderização existente." -tutorial.resize.description: "As imagens da cadeia de troca devem seguir as dimensões do framebuffer. Use {framebufferResize} para responder a alterações no tamanho em pixels, incluindo alterações causadas por dimensionamento de tela. Após o callback de renderização, ainda antes de {windowRun}, adicione:" -tutorial.resize.details: "O Silk.NET distingue mudanças no tamanho da janela de {link}. Precisamos destas últimas porque a cadeia de troca armazena pixels. Uma janela minimizada pode ter um framebuffer de tamanho zero. Nesse caso, ambos os callbacks pulam o trabalho de GPU. Após o redimensionamento, a passagem de renderização usa as novas dimensões do anexo para a viewport e o retângulo de recorte." -tutorial.resize.details.link: alterações no tamanho do framebuffer -tutorial.resize.guidance: Aguardamos após cada envio, portanto nenhum quadro anterior continua usando as imagens quando o manipulador de redimensionamento as substitui. A implementação atual de {present} também aguarda na fila gráfica. Esse loop simples mantém o trabalho de um quadro concluído antes que o próximo comece; {link} aborda um agendamento mais avançado. -tutorial.resize.guidance.link: Sincronização -tutorial.resize.title: Responder ao redimensionamento -tutorial.shaders.compilation.context: A compilação ocorre uma vez durante a inicialização. {appContextBaseDirectory} localiza o shader copiado ao lado do executável, independentemente do diretório de trabalho atual. Esses shaders consomem apenas entrada de vértices, portanto ainda não há buffers de constantes, texturas ou handles de recursos para vincular. -tutorial.shaders.compilation.description: Nas propriedades de arquivo de {triangleSlang}, defina {emphasis} como {detail}. Isso torna o shader disponível ao lado do executável. -tutorial.shaders.compilation.description.detail: Copiar se mais recente -tutorial.shaders.compilation.description.emphasis: Copiar para o Diretório de Saída -tutorial.shaders.compilation.details: "Retorne a {programCs}. Após o envio de vértices, adicione estas instruções de inicialização antes do callback de renderização:" -tutorial.shaders.compilation.guidance: "{zenithCompiler} retorna uma descrição de shader contendo código para a API gráfica solicitada. {createShader} cria o objeto de backend correspondente. Tanto a API gráfica quanto os nomes dos pontos de entrada são importantes: use {contextGraphicsApi} e escreva {vSMain} e {fSMain} exatamente como no arquivo Slang." -tutorial.shaders.compilation.title: Compilar para o backend selecionado -tutorial.shaders.context: "{fSInput} conecta a saída do vertex shader à entrada do fragment shader. Quando gravado pelo vertex shader, {sVPOSITION} fornece uma posição no espaço de recorte: as quatro coordenadas que a GPU usa para determinar o que fica dentro da imagem visível. {cOLOR0} carrega a cor a ser interpolada entre os vértices. Os dois estágios devem concordar quanto ao tipo e semântica." -tutorial.shaders.description: Um shader é um programa executado pela GPU. Este desenho precisa de um vertex shader para posicionar os vértices e de um fragment shader para produzir as cores dentro do triângulo. Nós os escreveremos em Slang, uma linguagem de shader, e compilaremos dois pontos de entrada a partir do mesmo arquivo. Um ponto de entrada é a função onde a execução de um estágio de shader começa. -tutorial.shaders.details: "Crie {triangleSlang}, começando com estas duas estruturas:" -tutorial.shaders.fragment.description: "Anexe o ponto de entrada de fragmento ao mesmo arquivo:" -tutorial.shaders.fragment.details: A rasterização determina quais posições da imagem o triângulo cobre. Ela produz fragmentos (os dados processados pelo fragment shader) com cores de vértices interpoladas pela área coberta. {fSMain} retorna essa cor interpolada por meio de {sVTARGET}, que identifica o primeiro anexo de cor. -tutorial.shaders.fragment.guidance: A interpolação de cor dos vértices é separada da mesclagem de anexos. A mesclagem combina a saída de um fragmento com a cor já armazenada no anexo. Nosso estado de mesclagem opaco desativa essa combinação, de modo que a cor interpolada substitui o fundo dentro do triângulo. -tutorial.shaders.fragment.title: Colorir os fragmentos -tutorial.shaders.guidance: "{vSInput} descreve o que o vertex shader recebe do buffer de vértices. As semânticas {pOSITION0} e {cOLOR0} identificam as entradas; os nomes dos campos C# sozinhos não estabelecem esse mapeamento." -tutorial.shaders.title: Escrever os dois estágios de shader -tutorial.shaders.vertex.description: "Anexe o ponto de entrada de vértice a {triangleSlang}:" -tutorial.shaders.vertex.details: A GPU invoca este ponto de entrada para cada vértice de entrada. Ele adiciona a coordenada homogênea {w} à posição e encaminha a cor. Após o estágio de vértice, a posição é dividida por w; aqui, essa divisão mantém x, y e z inalterados. É por isso que as posições escolhidas acima podem ser compreendidas diretamente em coordenadas normalizadas do dispositivo. -tutorial.shaders.vertex.title: Posicionar cada vértice -tutorial.surface.description: "O contexto também precisa saber onde exibir sua saída. Adicione o seguinte {emphasis}:" -tutorial.surface.description.emphasis: após {windowCenter} e antes de {windowRun} -tutorial.surface.details: "{surface} descreve um destino de apresentação nativo e suas dimensões em pixels. O framebuffer é a imagem de pixels associada à janela. {framebufferSize} fornece suas dimensões em pixels; as dimensões lógicas da janela podem ser diferentes quando o dimensionamento de tela está ativado." -tutorial.surface.guidance: A superfície corresponde ao backend selecionado acima. O Windows fornece um handle de janela, o Linux fornece um display e janela X11, e o assistente do macOS fornece a camada Metal anexada. Esta é a única parte específica da plataforma para conectar nossa janela à renderização. -tutorial.surface.title: Descrever a superfície nativa -tutorial.swapChain.context: "A cadeia de troca usa tanto o contexto quanto a janela nativa. Substitua a linha {windowDispose} na parte inferior de {programCs} por esta ordem de limpeza:" -tutorial.swapChain.description: "Use a descrição da superfície para criar as imagens que serão apresentadas. Imediatamente após o bloco da superfície, adicione:" -tutorial.swapChain.details: A {swapChain} gerencia as imagens exibidas na janela. A cada quadro, {drawable} nos fornece a imagem atual como uma {texture}, o tipo de API para dados de imagem. Após o desenho, {present} solicita a exibição do resultado e avança para o próximo drawable. -tutorial.swapChain.guidance: "{b8G8R8A8UNorm} armazena quatro canais de cor de 8 bits na ordem azul, verde, vermelho e alfa. {uNorm} significa que valores inteiros de 0 a 255 representam valores de 0 a 1. O shader continuará retornando um valor RGBA lógico; esse formato determina como esses canais são armazenados na imagem. Mais tarde, a pipeline gráfica usará {swapChainDescFormat} para corresponder a esse anexo." -tutorial.swapChain.title: Criar a cadeia de troca -tutorial.title: Primeiro triângulo -tutorial.troubleshooting.description: "Leia primeiro qualquer erro no console e, em seguida, use os pontos de verificação anteriores para identificar o estágio que falhou:" -tutorial.troubleshooting.details: Use o {link} e o {detail} para comparar os dados dos vértices, o layout de entrada e a operação de desenho. Aquele exemplo coloca as janelas e o envio em um host compartilhado; este tutorial mantém o fluxo da aplicação em {programCs}. Continue com {context} para aprender sobre desenho indexado, transformações e testes de profundidade. -tutorial.troubleshooting.details.context: Cubo giratório -tutorial.troubleshooting.details.detail: shader Slang -tutorial.troubleshooting.details.link: renderizador de exemplo -tutorial.troubleshooting.table.backend.check: Verifique se o backend selecionado é suportado pelo dispositivo e pelo driver gráfico instalado. -tutorial.troubleshooting.table.backend.symptom: Falha na criação do backend -tutorial.troubleshooting.table.drawing.check: Verifique o tamanho do upload, o layout de entrada, a seleção de pipeline e o posicionamento dos comandos de desenho dentro da passagem de renderização. -tutorial.troubleshooting.table.drawing.symptom: O fundo aparece, mas o triângulo não -tutorial.troubleshooting.table.headings.check: Verificação -tutorial.troubleshooting.table.headings.symptom: Sintoma -tutorial.troubleshooting.table.input.check: Verifique o stride de 28 bytes e os deslocamentos de posição/cor de 0 e 12. -tutorial.troubleshooting.table.input.symptom: Posições ou cores dos vértices estão corrompidas -tutorial.troubleshooting.table.shaders.check: Verifique o {triangleSlang} copiado, a ortografia do ponto de entrada e o diagnóstico relatado pelo compilador. -tutorial.troubleshooting.table.shaders.symptom: A etapa de cor de limpeza funciona, mas o carregamento do shader falha -tutorial.troubleshooting.table.window.check: Confirme se o projeto .NET compila e se a etapa somente de janela é executada em uma sessão de desktop. No Linux, verifique se o X11 ou XWayland está disponível. -tutorial.troubleshooting.table.window.symptom: Nenhuma janela se abre -tutorial.troubleshooting.title: Verificar o estágio que falhou -tutorial.window.context: "{usingZenithTutorials} importa o namespace do assistente. Cada arquivo C# usa suas próprias diretivas using comuns, portanto a importação de interoperabilidade é necessária em ambos os arquivos. O alias {buffer} refere-se ao tipo de buffer do Zenith.NET e o distingue de {systemBuffer}." -tutorial.window.description: Adicione {cocoaHelperCs} ao projeto, mantendo seu namespace. Adicione {interopUsing} no topo desse arquivo, antes de sua declaração de namespace. O assistente anexa uma camada Metal à janela no macOS; os outros branches de plataforma não o chamam. -tutorial.window.details: "Substitua o arquivo {programCs} gerado pelo seguinte código. Ele usa instruções de nível superior, que são executadas em ordem sem um método {main} explícito. Seções posteriores indicarão onde adicionar código a este mesmo arquivo:" -tutorial.window.guidance: "{graphicsAPINone} solicita ao Silk.NET que crie uma janela sem seu próprio contexto gráfico. Criaremos esse contexto com o Zenith.NET. {initialize} cria a janela nativa e disponibiliza seus handles. Um handle é um identificador fornecido pelo sistema de janelas. {center} centraliza a janela e {run} processa eventos até que ela seja fechada. A execução continua então para {dispose}, que libera a janela." -tutorial.window.notes: Execute {dotnetRun}. Uma janela vazia deve abrir e responder a movimentação, redimensionamento e fechamento. Seu conteúdo ainda não está definido porque não enviamos comandos de renderização. Feche-a antes de continuar. -tutorial.window.title: Abrir uma janela -ui.action.copy: Copiar -ui.action.navigate: Navegar -ui.action.open: Abrir -ui.action.source: Ver código-fonte -ui.api.browse: Navegar por namespaces e tipos. -ui.api.clearTypeSearch: Limpar busca de tipos -ui.api.findType: Localizar um tipo -ui.api.loadError: Não foi possível carregar os tipos. Recarregue esta página para tentar novamente. -ui.api.loadingNamespaces: Carregando namespaces… -ui.api.loadingTypes: Carregando tipos… -ui.api.matchingTypes: Tipos correspondentes -ui.api.namespace: Namespace -ui.api.namespaces: Namespaces -ui.api.noNamespaceTypes: Nenhum tipo neste namespace. -ui.api.noTypes: Nenhum tipo correspondente. -ui.api.types: Tipos -ui.content.reference: Referência -ui.content.source: Código-fonte -ui.content.tutorial: Tutorial +tutorial.input.title: "Layout de entrada dos vértices" +tutorial.lifecycle.description: "Cada quadro segue esta sequência:" +tutorial.lifecycle.details: "Quando a janela fecha, {run} retorna e a execução continua no código de limpeza. Como cada quadro já esperou seus comandos terminarem, os recursos usados por eles podem ser liberados. O bloco completo de limpeza após {windowRun} é:" +tutorial.lifecycle.guidance: "Libere a cadeia de troca antes de destruir sua janela nativa e o contexto depois de seus recursos. A fila recicla os buffers de comandos enviados, e a cadeia de troca gerencia a textura de saída; nenhum deles precisa de uma chamada separada a {dispose}." +tutorial.lifecycle.title: "Ciclo dos quadros e liberação" +tutorial.pipeline.behavior: "Após o layout de entrada, crie o pipeline:" +tutorial.pipeline.context: "{cullNone} desativa o descarte de faces, de modo que o triângulo seja desenhado tanto com os vértices em sentido horário quanto em sentido anti-horário." +tutorial.pipeline.description: "Um {graphicsPipeline} reúne o layout dos vértices, os dois shaders e as configurações de montagem de primitivas e escrita nos anexos." +tutorial.pipeline.details: "Os shaders processam vértices e fragmentos. As demais configurações do pipeline controlam a montagem de primitivas, o descarte de faces, o teste de profundidade e a mesclagem de cores:" +tutorial.pipeline.guidance: "O formato de cor do pipeline deve corresponder ao anexo da passagem, por isso é obtido de {swapChainDescFormat}. {count1} especifica uma amostra por pixel." +tutorial.pipeline.item: "{triangleList} monta um triângulo a cada grupo de três vértices consecutivos." +tutorial.pipeline.notes: "{depthNone} desativa teste e escrita de profundidade, de acordo com a ausência desse anexo." +tutorial.pipeline.reference: "{opaque} desativa a mesclagem. A saída do shader de fragmentos substitui, portanto, a cor de fundo dentro do triângulo." +tutorial.pipeline.title: "Pipeline gráfico" +tutorial.pipeline.usage: "Os objetos de shader podem ser liberados após a criação do pipeline. Mantenha o pipeline durante a renderização e adicione {pipelineDispose} antes de {vertexBufferDispose} na limpeza." +tutorial.presentation.title: "Contexto gráfico e apresentação" +tutorial.project.context: "Ative {emphasis} ({allowUnsafeBlocks}) nas opções de compilação do projeto. As chamadas nativas do auxiliar de janela e a transferência de vértices exigem código não seguro." +tutorial.project.context.emphasis: "Permitir código não seguro" +tutorial.project.description: "Crie um projeto de console C# chamado {firstTriangle}, com .NET 10 como framework de destino." +tutorial.project.details: "Adicione os seguintes pacotes NuGet ao projeto:" +tutorial.project.guidance: "{zenithNET} fornece a API comum de renderização; os três pacotes de backend, suas implementações. {zenithNETCompiler} compila os shaders Slang apresentados adiante para o backend selecionado. Silk.NET cria a janela e processa eventos." +tutorial.project.title: "Configuração do projeto" +tutorial.requirements.context: "O {link} e seu {detail} fornecem as implementações de referência deste tutorial." +tutorial.requirements.context.detail: "programa hospedeiro" +tutorial.requirements.context.link: "exemplo Olá triângulo" +tutorial.requirements.description: "São necessários o {emphasis} e conhecimentos básicos de C#. A aplicação tem {net10} como destino. A GPU e o driver devem oferecer suporte ao backend escolhido para sua plataforma:" +tutorial.requirements.description.emphasis: "SDK do .NET 10" +tutorial.requirements.guidance: "Zenith.NET renderiza em uma superfície nativa fornecida pela aplicação. Silk.NET.Windowing cria a janela e processa seus eventos. No macOS, a apresentação usa uma camada Metal, representada por {cAMetalLayerCs}, que o auxiliar associa à janela." +tutorial.requirements.table.headings.graphicsBackend: "Backend gráfico" +tutorial.requirements.table.headings.platform: "Plataforma" +tutorial.requirements.table.linux.graphicsBackend: "Vulkan 1.4" +tutorial.requirements.table.linux.platform: "Linux (X11 ou XWayland)" +tutorial.requirements.table.macOS.graphicsBackend: "Metal 4" +tutorial.requirements.table.macOS.platform: "macOS" +tutorial.requirements.table.windows.graphicsBackend: "DirectX 12" +tutorial.requirements.table.windows.platform: "Windows" +tutorial.requirements.title: "Pré-requisitos" +tutorial.resize.context: "Compile e execute a aplicação novamente. O fundo deve continuar preenchendo a janela quando ela for redimensionada: cada nova passagem ajusta o viewport e o retângulo de recorte às dimensões do anexo. Mantenha o callback de renderização; o triângulo será desenhado dentro dessa mesma passagem." +tutorial.resize.description: "A cadeia de troca precisa acompanhar as mudanças de tamanho do framebuffer. Registre um callback de {framebufferResize} depois do callback de renderização e antes de {windowRun}:" +tutorial.resize.details: "Responda às {link}, medidas em pixels, em vez de às mudanças no tamanho lógico da janela. Se minimizar a janela fizer alguma dimensão chegar a zero, o callback de redimensionamento mantém a cadeia de troca como está. O callback de renderização também retorna enquanto alguma dimensão for zero, interrompendo a renderização até que o framebuffer volte a ter um tamanho utilizável." +tutorial.resize.details.link: "alterações no tamanho do framebuffer" +tutorial.resize.guidance: "O callback de renderização espera cada quadro enviado terminar antes de chamar {present}. Assim, o callback de redimensionamento pode substituir as imagens da cadeia de troca sem interromper o trabalho de um quadro anterior. O artigo {link} detalha essa relação entre a conclusão do trabalho e o tempo de vida dos recursos." +tutorial.resize.guidance.link: "Sincronização" +tutorial.resize.title: "Redimensionamento" +tutorial.shaders.compilation.context: "{appContextBaseDirectory} permite carregar a cópia do shader no diretório de saída da aplicação. Assim, iniciar a aplicação a partir de outro diretório de trabalho não altera o local em que ela procura o arquivo." +tutorial.shaders.compilation.description: "Nas propriedades de {triangleSlang}, defina {emphasis} como {detail}. A compilação copiará o shader para o diretório do executável." +tutorial.shaders.compilation.description.detail: "Copiar se mais recente" +tutorial.shaders.compilation.description.emphasis: "Copiar para o Diretório de Saída" +tutorial.shaders.compilation.details: "Em {programCs}, acrescente a inicialização dos shaders após a transferência dos vértices e antes do callback de renderização:" +tutorial.shaders.compilation.guidance: "{zenithCompiler} compila o código-fonte para {contextGraphicsApi}, e {createShader} cria um objeto shader a partir da descrição compilada. Os nomes de ponto de entrada {vSMain} e {fSMain} selecionam as duas funções definidas no arquivo Slang." +tutorial.shaders.compilation.title: "Compilação dos shaders" +tutorial.shaders.context: "{fSInput} conecta as duas etapas do shader. O shader de vértices escreve em {sVPOSITION} uma posição no espaço de recorte, que a GPU usa para determinar a parte visível do triângulo. O campo {cOLOR0} leva a cor do vértice, interpolada ao longo do triângulo antes de chegar ao shader de fragmentos. Seu tipo e sua semântica devem corresponder nas duas etapas." +tutorial.shaders.description: "Shaders são programas executados na GPU. O shader de vértices determina a posição de cada vértice, e o shader de fragmentos determina a cor em cada posição coberta da imagem. As duas etapas serão escritas em um único arquivo Slang, cada uma com seu ponto de entrada: a função em que a execução começa." +tutorial.shaders.details: "Crie {triangleSlang} com estas estruturas de entrada e saída:" +tutorial.shaders.fragment.description: "Acrescente o ponto de entrada de fragmentos ao mesmo arquivo:" +tutorial.shaders.fragment.details: "A rasterização identifica as posições da imagem cobertas pelo triângulo e gera fragmentos para elas. Cada fragmento recebe uma cor interpolada a partir das cores dos três vértices. {fSMain} retorna essa cor, e {sVTARGET} direciona o resultado ao primeiro anexo de cor." +tutorial.shaders.fragment.title: "Sombreamento de fragmentos" +tutorial.shaders.guidance: "{vSInput} define as entradas do shader de vértices. {pOSITION0} e {cOLOR0} identificam os atributos por semântica; nomes de campos em C# não estabelecem sozinhos essa correspondência." +tutorial.shaders.title: "Estágios dos shaders" +tutorial.shaders.vertex.description: "Acrescente o ponto de entrada de vértices a {triangleSlang}:" +tutorial.shaders.vertex.details: "A GPU executa esse ponto de entrada para cada vértice. Ele acrescenta a coordenada homogênea {w} e repassa a cor. Após o processamento dos vértices, a posição é dividida por w. Como w vale 1, x, y e z permanecem iguais e podem ser interpretados como coordenadas normalizadas de dispositivo." +tutorial.shaders.vertex.title: "Sombreamento de vértices" +tutorial.surface.description: "Especifique o destino nativo de apresentação {emphasis}:" +tutorial.surface.description.emphasis: "após {windowCenter} e antes de {windowRun}" +tutorial.surface.details: "O framebuffer é a imagem da janela em pixels. {surface} descreve o destino nativo de apresentação e suas dimensões; {framebufferSize} fornece o tamanho em pixels. Com a escala da tela, esse tamanho pode diferir das dimensões lógicas da janela." +tutorial.surface.guidance: "A superfície fornece os identificadores nativos do backend: uma janela Win32 no Windows, display e janela X11 no Linux ou a camada Metal associada no macOS." +tutorial.surface.title: "Superfície nativa" +tutorial.swapChain.context: "A cadeia de troca depende do contexto e da janela. Substitua {windowDispose} no final de {programCs} por esta ordem de liberação:" +tutorial.swapChain.description: "Crie a cadeia de troca logo após a descrição da superfície:" +tutorial.swapChain.details: "A {swapChain} gerencia as imagens apresentadas pela janela. {drawable} fornece a imagem atual como uma {texture}, o recurso de imagem da API. Após a renderização, {present} solicita sua exibição e avança para a próxima textura de saída." +tutorial.swapChain.guidance: "{b8G8R8A8UNorm} armazena quatro canais de 8 bits na ordem azul, verde, vermelho e alfa. {uNorm} mapeia os inteiros de 0–255 para 0–1. A saída do shader continua sendo um valor RGBA lógico; o formato define sua representação no armazenamento. O pipeline usará {swapChainDescFormat} para corresponder a esse anexo." +tutorial.swapChain.title: "Cadeia de troca" +tutorial.title: "Primeiro triângulo" +tutorial.troubleshooting.description: "Use os diagnósticos do console e os três pontos de verificação para localizar a etapa com falha:" +tutorial.troubleshooting.details: "O {link} e o {detail} servem de referência para dados de vértices, layout e desenho. O exemplo separa janela e envio em um programa hospedeiro comum; este tutorial mantém o fluxo em {programCs}. O {context} introduz desenho indexado, transformações e teste de profundidade." +tutorial.troubleshooting.details.context: "Cubo giratório" +tutorial.troubleshooting.details.detail: "shader Slang" +tutorial.troubleshooting.details.link: "renderizador de exemplo" +tutorial.troubleshooting.table.backend.check: "Verifique se o backend selecionado é suportado pelo dispositivo e pelo driver gráfico instalado." +tutorial.troubleshooting.table.backend.symptom: "Falha na criação do backend" +tutorial.troubleshooting.table.drawing.check: "Verifique o tamanho do upload, o layout de entrada, a seleção de pipeline e o posicionamento dos comandos de desenho dentro da passagem de renderização." +tutorial.troubleshooting.table.drawing.symptom: "O fundo aparece, mas o triângulo não" +tutorial.troubleshooting.table.headings.check: "Verificação" +tutorial.troubleshooting.table.headings.symptom: "Sintoma" +tutorial.troubleshooting.table.input.check: "Verifique o passo de 28 bytes e os deslocamentos de posição/cor de 0 e 12." +tutorial.troubleshooting.table.input.symptom: "Posições ou cores dos vértices estão corrompidas" +tutorial.troubleshooting.table.shaders.check: "Verifique o {triangleSlang} copiado, a ortografia do ponto de entrada e o diagnóstico relatado pelo compilador." +tutorial.troubleshooting.table.shaders.symptom: "O fundo aparece, mas o carregamento dos shaders falha" +tutorial.troubleshooting.table.window.check: "Confirme se o projeto .NET compila e se a etapa somente de janela é executada em uma sessão de desktop. No Linux, verifique se o X11 ou XWayland está disponível." +tutorial.troubleshooting.table.window.symptom: "Nenhuma janela se abre" +tutorial.troubleshooting.title: "Diagnóstico de problemas" +tutorial.window.description: "Baixe {cocoaHelperCs} para o diretório do projeto. Essa classe auxiliar conecta a camada Metal à janela do macOS." +tutorial.window.details: "Substitua o conteúdo gerado de {programCs} pelo código abaixo. Ele usa instruções de nível superior, executadas em ordem sem um método {main} explícito. As próximas seções indicarão onde acrescentar cada trecho:" +tutorial.window.guidance: "{graphicsAPINone} deixa a criação do contexto gráfico a cargo de Zenith.NET. {initialize} cria a janela nativa e disponibiliza os identificadores do sistema de janelas. {center} a coloca no centro da tela. {run} processa eventos até seu fechamento; depois, {dispose} libera a janela." +tutorial.window.notes: "Compile e execute a aplicação. Verifique se a janela abre e fecha normalmente e se é possível movê-la e redimensioná-la. O conteúdo ainda não está definido, pois nenhum comando de renderização foi enviado. Feche a janela antes de continuar." +tutorial.window.title: "Criação da janela" +ui.action.copy: "Copiar" +ui.action.navigate: "Navegar" +ui.action.open: "Abrir" +ui.action.source: "Ver código-fonte" +ui.api.browse: "Navegar por namespaces e tipos." +ui.api.clearTypeSearch: "Limpar busca de tipos" +ui.api.findType: "Localizar um tipo" +ui.api.loadError: "Não foi possível carregar os tipos. Recarregue esta página para tentar novamente." +ui.api.loadingNamespaces: "Carregando namespaces…" +ui.api.loadingTypes: "Carregando tipos…" +ui.api.matchingTypes: "Tipos correspondentes" +ui.api.namespace: "Namespace" +ui.api.namespaces: "Namespaces" +ui.api.noNamespaceTypes: "Nenhum tipo neste namespace." +ui.api.noTypes: "Nenhum tipo correspondente." +ui.api.types: "Tipos" +ui.content.reference: "Referência" +ui.content.source: "Código-fonte" +ui.content.tutorial: "Tutorial" ui.contents.close: "Fechar sumário" ui.contents.open: "Abrir sumário" ui.contents.title: "Sumário" -ui.footer.caption: RHI moderno para .NET. -ui.footer.label: Rodapé -ui.language.label: Idioma -ui.language.unavailable: Não traduzido -ui.members.clear: Limpar busca de membros -ui.members.close: Fechar localizador de membros -ui.members.empty: Nenhum membro correspondente. -ui.members.open: Ir para o membro -ui.members.placeholder: Nome ou assinatura… -ui.members.search: Buscar membros -ui.members.title: Localizar um membro -ui.members.undeclared: Este tipo não possui membros declarados. -ui.navigation.api: API -ui.navigation.concepts: Conceitos -ui.navigation.home: Início -ui.navigation.label: Navegação principal -ui.navigation.toggle: Alternar navegação -ui.outline.title: Nesta página -ui.reference.assembly: Assembly -ui.reference.classes: Classes -ui.reference.constructors: Construtores +ui.footer.caption: "RHI moderna para .NET" +ui.footer.label: "Rodapé" +ui.language.label: "Idioma" +ui.language.unavailable: "Não traduzido" +ui.members.clear: "Limpar busca de membros" +ui.members.close: "Fechar localizador de membros" +ui.members.empty: "Nenhum membro correspondente." +ui.members.open: "Ir para o membro" +ui.members.placeholder: "Nome ou assinatura…" +ui.members.search: "Buscar membros" +ui.members.title: "Localizar um membro" +ui.members.undeclared: "Este tipo não possui membros declarados." +ui.navigation.api: "API" +ui.navigation.concepts: "Conceitos" +ui.navigation.home: "Início" +ui.navigation.label: "Navegação principal" +ui.navigation.toggle: "Alternar navegação" +ui.outline.title: "Nesta página" +ui.reference.assembly: "Assembly" +ui.reference.classes: "Classes" +ui.reference.constructors: "Construtores" ui.reference.declaration: "Declaração de tipo C#" ui.reference.delegates: "Delegados" -ui.reference.derived: Tipos derivados -ui.reference.enums: Enumerações -ui.reference.events: Eventos -ui.reference.examples: Exemplos -ui.reference.exceptions: Exceções -ui.reference.extensionMethods: Métodos de extensão -ui.reference.fields: Campos -ui.reference.implementations: Implementações explícitas de interface -ui.reference.implements: Implementa -ui.reference.inheritance: Herança -ui.reference.inheritedMembers: Membros herdados -ui.reference.interfaces: Interfaces -ui.reference.metadata: Metadados do tipo -ui.reference.methods: Métodos -ui.reference.namespace: Namespace -ui.reference.open: Abrir referência para {name} -ui.reference.operators: Operadores -ui.reference.parameters: Parâmetros -ui.reference.properties: Propriedades -ui.reference.related: Consulte também -ui.reference.relationships: Herança e metadados -ui.reference.remarks: Comentários -ui.reference.returns: Retornos -ui.reference.structs: Estruturas -ui.reference.typeParameters: Parâmetros de tipo -ui.reference.value: Valor -ui.reference.values: Valores -ui.search.close: Fechar busca -ui.search.empty: Nenhum resultado para “{query}”. -ui.search.hint: Pesquise tutoriais, conceitos, exemplos e a referência da API. -ui.search.loading: Carregando busca… -ui.search.more: Mostrar mais resultados -ui.search.pending: Buscando… -ui.search.placeholder: O que você está procurando? +ui.reference.derived: "Tipos derivados" +ui.reference.enums: "Enumerações" +ui.reference.events: "Eventos" +ui.reference.examples: "Exemplos" +ui.reference.exceptions: "Exceções" +ui.reference.extensionMethods: "Métodos de extensão" +ui.reference.fields: "Campos" +ui.reference.implementations: "Implementações explícitas de interface" +ui.reference.implements: "Implementa" +ui.reference.inheritance: "Herança" +ui.reference.inheritedMembers: "Membros herdados" +ui.reference.interfaces: "Interfaces" +ui.reference.metadata: "Metadados do tipo" +ui.reference.methods: "Métodos" +ui.reference.namespace: "Namespace" +ui.reference.open: "Abrir referência para {name}" +ui.reference.operators: "Operadores" +ui.reference.parameters: "Parâmetros" +ui.reference.properties: "Propriedades" +ui.reference.related: "Consulte também" +ui.reference.relationships: "Herança e metadados" +ui.reference.remarks: "Comentários" +ui.reference.returns: "Retornos" +ui.reference.structs: "Estruturas" +ui.reference.typeParameters: "Parâmetros de tipo" +ui.reference.value: "Valor" +ui.reference.values: "Valores" +ui.search.close: "Fechar busca" +ui.search.empty: "Nenhum resultado para “{query}”." +ui.search.hint: "Pesquise tutoriais, conceitos, exemplos e a referência da API." +ui.search.loading: "Carregando busca…" +ui.search.more: "Mostrar mais resultados" +ui.search.pending: "Buscando…" +ui.search.placeholder: "O que você está procurando?" ui.search.resultCount: "Resultados: {count}" -ui.search.title: Pesquisar documentação -ui.search.unavailable: A busca não está disponível. Você ainda pode abrir as páginas abaixo. +ui.search.title: "Pesquisar documentação" +ui.search.unavailable: "A busca não está disponível. Você ainda pode abrir as páginas abaixo." diff --git a/documents/locales/pt-BR/translation.md b/documents/locales/pt-BR/translation.md index d1283533..829bf443 100644 --- a/documents/locales/pt-BR/translation.md +++ b/documents/locales/pt-BR/translation.md @@ -8,6 +8,16 @@ Navegação, ordem dos capítulos, âncoras, links, formatação, código e imag Altere apenas os valores da `strings.yml` deste idioma. O conjunto de chaves deve corresponder exatamente ao inglês. Não adicione, remova ou renomeie chaves por conta própria, mesmo que os textos pareçam iguais ou ainda não tenham aparecido na interface. Se encontrar um problema no original, informe a chave e o problema aos responsáveis pelo projeto. Corrija primeiro a fonte inglesa e as páginas compartilhadas; depois, atualize as traduções. +## Estilo e contexto + +Adote o tom de um manual técnico: preciso, sóbrio e acessível. Explique a relação entre as operações antes de apresentar suas restrições. Nos tutoriais, mantenha instruções claras e resultados verificáveis. Rigor não exige voz passiva nem frases longas. + +Revise cada artigo na ordem de leitura, considerando os parágrafos, tabelas e código ao redor. As chaves delimitam o armazenamento, não unidades isoladas de tradução. Confira concordância, artigos e preposições dos links e trechos destacados na frase completa. + +Títulos, rótulos, textos curtos visíveis da página inicial e legenda do rodapé não levam ponto final. Parágrafos, diagnósticos e instruções de acessibilidade mantêm a pontuação normal. Use um termo consagrado por conceito, sem acrescentar equivalentes ingleses entre parênteses de forma seletiva. Preserve identificadores de API, arquivos e configurações. Use pipeline no masculino. + +Mantenha uma frase quando ela explicar a operação atual, uma escolha de projeto, um resultado verificável ou uma condição necessária. Elimine listas de funções não utilizadas, ressalvas genéricas e requisitos repetidos. Traduza títulos e frases separados pela formatação como um todo, na ordem natural do português. Os marcadores `{accent}` e `{lineBreak}` do título inicial podem ser movidos; o estilo visual não deve impor a ordem inglesa. A manutenção coordena a retirada de um trecho e de suas chaves no original, na marcação compartilhada e em todos os dicionários. + ## Texto e marcadores Traduza frases ou parágrafos completos para um português brasileiro técnico, claro e natural. Preserve condições, negações, unidades, etapas e restrições de tempo de vida. Não acrescente garantias técnicas, requisitos de plataforma, versões de pacotes ou notas de versão ausentes no original. Mantenha nomes de produtos, pacotes e arquivos, além dos identificadores C# e Slang, inclusive maiúsculas e minúsculas. diff --git a/documents/locales/ru-RU/strings.yml b/documents/locales/ru-RU/strings.yml index 246d4416..e3848961 100644 --- a/documents/locales/ru-RU/strings.yml +++ b/documents/locales/ru-RU/strings.yml @@ -1,62 +1,62 @@ ### YamlMime:Resources -concepts.execution.context.description: Объект {graphicsContext} представляет устройство бэкенда и предоставляет его очереди графики, вычислений и передачи данных. Создавайте буферы, текстуры, шейдеры и конвейеры для рабочей нагрузки через один и тот же контекст. Ресурс или дескриптор, созданный другим контекстом, нельзя просто привязать к командным буферам текущего контекста. -concepts.execution.context.details: Выберите бэкенд для платформы и поверхности презентации. API остаётся общим, но возможности устройства имеют решающее значение. Объект {capabilities} предоставляет имя устройства и флаги {rayTracingSupported} и {meshShadingSupported}. Проверяйте соответствующий флаг перед созданием опциональной рабочей нагрузки, как это сделано в примерах {link} и {detail}. Эти флаги не представляют собой исчерпывающий список ограничений форматов, памяти или платформы. -concepts.execution.context.details.detail: mesh shading +concepts.execution.context.description: "{graphicsContext} связывает приложение с устройством GPU через определённый бэкенд и предоставляет его графическую, вычислительную и передающую очереди. Совместно используемые ресурсы должны принадлежать одному контексту: буферы, текстуры, шейдеры, конвейеры и их дескрипторы нельзя привязывать между разными контекстами." +concepts.execution.context.details: "{capabilities} сообщает имя устройства и поддерживаемые возможности. Перед созданием ресурсов для трассировки лучей или меш-шейдинга проверяйте соответственно {rayTracingSupported} и {meshShadingSupported}. Такие проверки при инициализации показаны в примерах {link} и {detail}." +concepts.execution.context.details.detail: "меш-шейдинга" concepts.execution.context.details.link: трассировки лучей -concepts.execution.context.title: Контекст объединяет ресурсы и очереди -concepts.execution.description: Приложение Zenith.NET создаёт ресурсы GPU, записывает команды, использующие их, и отправляет эти команды в очередь. CPU может продолжать работу, пока GPU выполняет отправленные задачи. Сохраняйте ресурсы активными до завершения этой работы, даже после того, как вызовы записи команд завершились. -concepts.execution.ownership.description: "Здесь владение означает ответственность за освобождение ресурса. Ссылка C# удерживает управляемый объект от сборки мусора; она не препятствует уничтожению нативного ресурса при явном вызове {dispose}. Аналогично, отправка команды, использующей буфер, не передаёт владение этим буфером очереди." -concepts.execution.ownership.details: При завершении работы прекратите отправку новых задач, дождитесь окончания последних операций во всех задействованных очередях, освободите ресурсы приложения и затем освободите контекст. Освобождение контекста очищает его собственные очереди и внутренние вспомогательные структуры; оно не ожидает все задачи приложения и не освобождает каждый ресурс, созданный приложением. -concepts.execution.ownership.guidance: Применяйте те же правила времени жизни и во время рендеринга. Сохраняйте значение завершения для последнего использования ресурса, чтобы знать, когда его байты можно перезаписать или когда ресурс можно заменить. О времени жизни представлений и базовых ресурсов см. в разделе {link}. +concepts.execution.context.title: "Графический контекст" +concepts.execution.description: "Подготовка работы GPU начинается на CPU: приложение создаёт ресурсы, записывает команды, которые их используют, и отправляет команды в очередь. После отправки CPU может продолжать работу, пока GPU выполняет команды. Нужные им ресурсы должны оставаться доступными до завершения выполнения." +concepts.execution.ownership.description: "Владение определяет, кто освобождает объект, а завершение работы GPU — когда его можно освободить. Вызов {dispose} освобождает нативные ресурсы, даже если ссылки C# на объект ещё существуют. Отправка команд не передаёт очереди владение их ресурсами." +concepts.execution.ownership.details: "При завершении приложения прекратите новые отправки и дождитесь последнего использования ресурсов во всех задействованных очередях. Затем освободите ресурсы приложения и контекст. Контекст освобождает свои очереди и внутренние вспомогательные объекты, поэтому этот последний шаг должен выполняться после завершения работы приложения с GPU." +concepts.execution.ownership.guidance: "Во время рендеринга отслеживайте завершение обращений к данным, которые предстоит перезаписать, или к ресурсам, которые предстоит заменить. Прежде чем изменять или освобождать память, дождитесь окончания этих обращений. Время жизни представлений и лежащих в их основе ресурсов описано в статье «{link}»." concepts.execution.ownership.guidance.link: Управление ресурсами concepts.execution.ownership.table.applicationResources.object: Ресурсы, созданные приложением concepts.execution.ownership.table.applicationResources.ownership: Приложение освобождает их после последнего использования на GPU. -concepts.execution.ownership.table.commandBuffers.object: Заимствованные командные буферы +concepts.execution.ownership.table.commandBuffers.object: "Заимствованные буферы команд" concepts.execution.ownership.table.commandBuffers.ownership: Очередь управляет ими и повторно использует их. concepts.execution.ownership.table.headings.object: Объект -concepts.execution.ownership.table.headings.ownership: Кто освобождает? +concepts.execution.ownership.table.headings.ownership: "Ответственность за освобождение" concepts.execution.ownership.table.queues.object: Очереди контекста и их временные шкалы concepts.execution.ownership.table.queues.ownership: Контекст и очереди управляют ими. concepts.execution.ownership.table.swapChainDrawable.ownership: Цепочка обмена управляет ею. -concepts.execution.ownership.title: Разделение владения и завершения на GPU -concepts.execution.pipelines.description: Графический конвейер объединяет шейдеры, разметку входных вершин, правила сборки вершин в примитивы, форматы вложений и состояние рендеринга. Установите его перед привязкой данных вершин, индексов или констант и перед вызовом команд отрисовки. Форматы его вложений и число сэмплов должны совпадать со свойствами вложений прохода рендеринга. -concepts.execution.pipelines.details: Вычислительный конвейер предоставляет точку входа шейдера для диспатча, запускающего группы потоков GPU. Установите его и его константы перед вызовом диспатча. Вычислительные диспатчи должны находиться вне графических проходов рендеринга. Смена конвейера меняет то, как последующие команды интерпретируют свои входные данные; привязывайте данные, требуемые выбранным конвейером, перед его использованием. -concepts.execution.pipelines.guidance: В разделе {link} показана полная последовательность графических операций. В {detail} записывается диспатч с последующим графическим проходом, отображающим результат. -concepts.execution.pipelines.guidance.detail: примере вычислений -concepts.execution.pipelines.guidance.link: обратный вызов рендеринга треугольника -concepts.execution.pipelines.title: Конвейер определяет, как команды интерпретируют данные -concepts.execution.queues.description: Начинайте с {graphicsQueue}, если кадр сочетает отрисовку, вычисления и копирование. Размещение зависимых задач в одной очереди упрощает контроль за их очерёдностью. -concepts.execution.queues.details: Очередь принимает пакеты команд для выполнения. Раздельные очереди не обязательно соответствуют отдельным аппаратным движкам, поэтому их работа может не выполняться параллельно. Используйте другую очередь, когда нагрузка может выиграть от перекрытия выполнения, и добавляйте явную зависимость, если одна очередь использует результаты другой. -concepts.execution.queues.guidance: Когда последующие команды зависят от предыдущих записей, приложение должно гарантировать, что эти записи доступны последующим командам. Отправка обоих командных буферов в одну и ту же очередь не устанавливает автоматически каждую такую зависимость. Команды могут выполняться на разных стадиях GPU, и последующим обращениям может потребоваться барьер или переход текстуры. В разделе {link} объясняется различие между порядком отправки и видимостью ресурсов. +concepts.execution.ownership.title: "Владение и время жизни" +concepts.execution.pipelines.description: "Графический конвейер задаёт шейдеры, формат вершинных данных, сборку примитивов, форматы вложений и состояние для команд рисования. Выберите конвейер до привязки вершин, индексов и констант. Форматы вложений и число выборок должны соответствовать проходу рендеринга." +concepts.execution.pipelines.details: "Вычислительный конвейер выбирает точку входа шейдера для запуска вычислений. Привяжите конвейер и его константы перед запуском, вне графического прохода рендеринга." +concepts.execution.pipelines.guidance: "Последовательность графических команд разобрана в {link}. В {detail} перед графическим проходом добавляется вычисление изображения, которое затем выводится на экран." +concepts.execution.pipelines.guidance.detail: "вычислительном примере" +concepts.execution.pipelines.guidance.link: "обработчике рендеринга треугольника" +concepts.execution.pipelines.title: "Состояние конвейера" +concepts.execution.queues.description: "{graphicsQueue} обычно подходит для кадра, объединяющего рисование, вычисления и копирование. Размещение зависимых операций в одной очереди упрощает их упорядочивание." +concepts.execution.queues.details: "Отдельные очереди позволяют независимо отправлять разные задачи, но не обязательно соответствуют независимым аппаратным блокам. Дополнительные очереди полезны, если задачи могут выиграть от перекрытия выполнения. Когда одна очередь использует данные другой, между их отправками нужна явная зависимость." +concepts.execution.queues.guidance: "Даже в одной очереди зависимым операциям могут понадобиться барьеры или переходы состояния текстур, чтобы последующие обращения видели результаты предыдущих записей. Эти зависимости по памяти отличаются от порядка отправки команд. Как их задавать, описано в статье «{link}»." concepts.execution.queues.guidance.link: Синхронизация -concepts.execution.queues.table.computeQueue.workToRecord: Вычислительные диспатчи и совместимые операции передачи данных без графических проходов рендеринга. -concepts.execution.queues.table.graphicsQueue.workToRecord: Проходы рендеринга и отрисовка, а также операции вычислений и передачи данных, используемые кадром. +concepts.execution.queues.table.computeQueue.workToRecord: "Запуск вычислений и совместимые операции передачи данных, без графических проходов рендеринга." +concepts.execution.queues.table.graphicsQueue.workToRecord: "Проходы рендеринга, рисование, вычисления и передача данных." concepts.execution.queues.table.headings.queue: Очередь -concepts.execution.queues.table.headings.workToRecord: Записываемая работа -concepts.execution.queues.table.transferQueue.workToRecord: Операции загрузки, скачивания и копирования данных без отрисовки и вычислительных диспатчей. -concepts.execution.queues.title: Выбор очереди для выполняемой работы -concepts.execution.recording.context: Очередь опрашивает статус завершения и повторно использует завершённые командные буферы. Вызывайте {queueCommandBuffer} для каждой новой записи; метод может вернуть повторно используемый экземпляр. Не освобождайте полученный командный буфер вручную, не отправляйте его дважды и не продолжайте запись в него после отправки. Записывайте данный командный буфер только из одного потока одновременно; внутренние блокировки очереди не защищают от одновременных изменений командного буфера. -concepts.execution.recording.description: Метод {queueCommandBuffer} возвращает {commandBuffer} с уже начатой записью. Запишите команды и их зависимости, затем вызовите {submit} один раз. Отправка завершает запись и возвращает {timelineValue}, определяющий точку завершения на этой очереди. -concepts.execution.recording.details: "Например, после записи кадра в {commandBuffer} учебник отправляет его и ожидает завершения следующим образом:" -concepts.execution.recording.guidance: Метод {submit} ставит работу в расписание; {wait} удерживает CPU от продолжения до завершения этой отправки. Запись отрисовки, завершение прохода рендеринга и отправка командного буфера — это независимые операции. Ни запись отрисовки, ни завершение прохода не ожидают GPU. -concepts.execution.recording.title: Запись не выполняет команды +concepts.execution.queues.table.headings.workToRecord: "Поддерживаемые операции" +concepts.execution.queues.table.transferQueue.workToRecord: "Загрузка, считывание и копирование без рисования и вычислительных запусков." +concepts.execution.queues.title: "Выбор очереди" +concepts.execution.recording.context: "Очередь возвращает завершённые командные буферы для повторного использования. Для каждой записи получите буфер через {queueCommandBuffer}, записывайте его только из одного потока одновременно и отправьте один раз. После отправки оставьте управление очереди: не изменяйте буфер, не отправляйте его повторно и не освобождайте самостоятельно." +concepts.execution.recording.description: "{queueCommandBuffer} возвращает {commandBuffer}, уже открытый для записи. Запишите операции и зависимости, затем один раз вызовите {submit}. Вызов завершает запись и возвращает {timelineValue}, обозначающий точку завершения в этой очереди." +concepts.execution.recording.details: "После записи кадра в {commandBuffer} учебный пример отправляет команды и ожидает завершения:" +concepts.execution.recording.guidance: "Запись формирует последовательность команд, а {submit} планирует её выполнение. Последующий вызов {wait} блокирует поток CPU до завершения отправленной работы. Поэтому цикл кадров в уроке легко проследить: каждый кадр заканчивается до начала следующего." +concepts.execution.recording.title: "Запись и отправка команд" concepts.execution.title: Модель выполнения -concepts.platforms.description: Выберите, владеет ли ваше приложение нативным окном и циклом кадров самостоятельно или использует элемент управления рендерингом UI. Этот выбор определяет, кто получает выходную текстуру, отправляет команды и выводит результат на экран. Выходная текстура — это текстура, используемая для вывода текущего кадра. Закадровая графика и вычисления не требуют наличия окна или цепочки обмена. -concepts.platforms.frame.context: Добавьте привязки конвейера и команды отрисовки внутри этого прохода. Завершите проход до возврата управления. Не отправляйте предоставленный командный буфер и не вызывайте презентацию самостоятельно, а также не освобождайте командный буфер или выходную текстуру. Если обработчик использует выходную текстуру в другом layout, верните её в состояние {colorAttachment} перед завершающим переходом элемента управления. -concepts.platforms.frame.description: Интеграции реализуют интерфейс {iZenithView}. Приложение предоставляет свой {graphicsContext}, обновляет данные сцены в {updateRequested} и записывает команды рендеринга в {renderRequested} с использованием {renderEventArgs}. -concepts.platforms.frame.details: "Элемент управления отвечает за полный цикл обработки кадра. Он получает выходную текстуру и командный буфер, переводит текстуру в состояние {colorAttachment}, вызывает обработчики, а затем выполняет отправку команд и презентацию, требуемые фреймворком." -concepts.platforms.frame.guidance: "Для инициализированного представления {iZenithView} с именем {view} и назначенным контекстом данный обработчик записывает полный проход очистки. Для него требуется директива {usingZenithNET}:" -concepts.platforms.frame.notes: Элементы управления выполняют переход из {undefined} в начале каждого кадра, поэтому приложения не могут рассчитывать на сохранение предыдущего содержимого выходной текстуры. Очищайте или заново отрисовывайте требуемое изображение в каждом кадре. Храните постоянные накопленные данные или кэшированный рендеринг в текстуре, принадлежащей приложению, и выводите эту текстуру через элемент управления. -concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat} задаёт формат цвета по умолчанию для интеграций. При согласовании форматов вложений, числа сэмплов и размеров проверяйте фактическую выходную текстуру события." -concepts.platforms.frame.title: Запись команд в кадр, предоставляемый элементом управления UI -concepts.platforms.integration.context: Для WinForms, WPF и варианта WinUI требуется Windows. Приложениям MAUI требуется рабочая нагрузка целевой платформы и регистрация обработчика через {useZenithView}; см. {extensionsCs}. Должны поддерживаться как фреймворк, так и графический бэкенд. -concepts.platforms.integration.description: "Элементы управления используют общий интерфейс событий, но способ вывода изображения у них различается:" -concepts.platforms.integration.details: Считывание растровых изображений (bitmap readback) копирует отрисованные пиксели в память CPU перед их отображением в UI. Взаимодействие через разделяемые текстуры позволяет избежать этого считывания, но всё же может требовать копирования и синхронизации на GPU. Общий интерфейс {renderRequested} не означает одинаковых накладных расходов на презентацию или идентичных требований к взаимодействию. -concepts.platforms.integration.guidance: "Используйте пакет, соответствующий фреймворку приложения, например:" +concepts.platforms.description: "Выводом управляет приложение или элемент интерфейса. От этого зависит, кто получает выходную текстуру кадра, записывает и отправляет команды и выводит результат. Эта выходная текстура называется drawable." +concepts.platforms.frame.context: "Записывайте привязку конвейера и команды рисования внутри прохода и завершайте его до возврата из обработчика. Элемент управления сам отправит команды и выведет результат. Обработчик не должен отправлять командный буфер или освобождать любой из двух предоставленных объектов. Если он меняет состояние выходной текстуры, перед возвратом нужно восстановить {colorAttachment}, чтобы элемент управления выполнил заключительный переход." +concepts.platforms.frame.description: "Элементы реализуют {iZenithView}. Приложение назначает {graphicsContext}, обновляет сцену в {updateRequested} и записывает команды в {renderRequested}, используя переданный {renderEventArgs}." +concepts.platforms.frame.details: "Для каждого кадра элемент управления получает выходную текстуру и командный буфер, переводит текстуру в {colorAttachment} и вызывает обработчики обновления и рендеринга. Затем он отправляет записанные команды и выводит изображение средствами выбранного UI-фреймворка." +concepts.platforms.frame.guidance: "Добавьте {usingZenithNET} в файл. Для инициализированного {iZenithView} с именем {view} и назначенным графическим контекстом зарегистрируйте обработчик, заполняющий выходную текстуру цветом:" +concepts.platforms.frame.notes: "Первый переход использует {undefined}, разрешая отбросить прежнее содержимое изображения. Поэтому каждый кадр должен заново заполнять или отрисовывать всё изображение. Накопленные или кешированные результаты храните в текстуре приложения, а затем рисуйте её в выходную текстуру элемента управления." +concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat} предоставляет цветовой формат, используемый по умолчанию в этих интеграциях." +concepts.platforms.frame.title: "Рендеринг в элементах интерфейса" +concepts.platforms.integration.context: "WinForms, WPF и Windows-интеграция WinUI работают под Windows. Для MAUI установите рабочую нагрузку целевой платформы и зарегистрируйте обработчик элемента управления через {useZenithView}, как показано в {extensionsCs}." +concepts.platforms.integration.description: "Интерфейс событий общий, но механизм вывода зависит от фреймворка:" +concepts.platforms.integration.details: "Реализации различаются тем, как изображение GPU попадает в интерфейс. Считывание в растровое изображение копирует пиксели в память CPU перед показом. Совместное использование текстуры исключает эту копию на CPU, но всё ещё может требовать копирования на GPU и синхронизации. При выборе интеграции учитывайте этот путь вывода наряду с общим событием {renderRequested}." +concepts.platforms.integration.guidance: "Добавьте через NuGet пакет интеграции для вашего UI-фреймворка. Для Avalonia используйте {avaloniaPackage}." concepts.platforms.integration.table.avalonia.integration: Avalonia -concepts.platforms.integration.table.avalonia.presentation: Рендерит в текстуру и считывает пиксели в {writeableBitmap}. См. {zenithViewCs} и {surfaceCs}. +concepts.platforms.integration.table.avalonia.presentation: "Рисует в текстуру и считывает пиксели в {writeableBitmap}. Реализация: {zenithViewCs} и {surfaceCs}." concepts.platforms.integration.table.headings.integration: Интеграция -concepts.platforms.integration.table.headings.presentation: Как изображение передаётся в UI +concepts.platforms.integration.table.headings.presentation: "Механизм вывода" concepts.platforms.integration.table.maui.integration: .NET MAUI concepts.platforms.integration.table.maui.presentation: Использует нативные поверхности в Android, iOS и Mac Catalyst, а в Windows — композицию через разделяемые текстуры. См. {link}. concepts.platforms.integration.table.maui.presentation.link: реализации для платформ @@ -65,28 +65,27 @@ concepts.platforms.integration.table.uno.presentation: Считывает пик concepts.platforms.integration.table.winForms.integration: WinForms concepts.platforms.integration.table.winForms.presentation: Создаёт цепочку обмена Zenith.NET для дескриптора {hWND} элемента управления. См. {zenithViewCs}. concepts.platforms.integration.table.winUI.integration: WinUI в Windows -concepts.platforms.integration.table.winUI.presentation: Рендерит в импортированную разделяемую текстуру Direct3D 11, затем копирует в композиционную цепочку обмена, подключённую к {swapChainPanel}. См. {zenithViewWinUICs}. +concepts.platforms.integration.table.winUI.presentation: "Рисует в импортированную общую текстуру Direct3D 11, затем копирует результат в композиционную цепочку обмена, связанную с {swapChainPanel}. Реализация: {zenithViewWinUICs}." concepts.platforms.integration.table.wpf.integration: WPF -concepts.platforms.integration.table.wpf.presentation: Импортирует разделяемую текстуру Direct3D 11, затем копирует через Direct3D interop в поверхность, отображаемую {d3DImage}. См. {surfaceCs}. -concepts.platforms.integration.title: Выбор пути презентации и фреймворка -concepts.platforms.lifecycle.context: "При создании ресурсов для элемента управления UI используйте значения {descWidth}, {descHeight}, {descFormat} и {descSampleCount} выходной текстуры события. Элемент управления определяет разрешение этой текстуры; не предполагайте, что его логические размеры или масштаб экрана всегда соответствуют размерам текстуры." -concepts.platforms.lifecycle.description: Для нативной цепочки обмена передавайте размеры фреймбуфера в пикселях. Размеры окна в логических единицах могут отличаться при включённом масштабировании экрана. Пропускайте фреймбуферы нулевого размера, изменяйте размер цепочки обмена при изменении её пиксельного размера и получайте {swapChainDrawable} для каждого кадра. Выходная текстура принадлежит цепочке обмена и может меняться после вывода на экран или изменения размера. -concepts.platforms.lifecycle.details: Метод {swapChainResize} изменяет размеры существующей поверхности. Метод {swapChainRefresh} заменяет описание поверхности, включая её нативные дескрипторы. Перед любой из этих операций завершите незавершённые операции с затрагиваемыми ресурсами. Освобождайте цепочку обмена до уничтожения её нативного целевого объекта презентации. -concepts.platforms.lifecycle.guidance: Пересоздавайте принадлежащие приложению текстуры глубины или закадровые текстуры, размер которых привязан к окну, и обновляйте константы, содержащие их дескрипторы. Конвейер может продолжать использоваться после изменения размера, если форматы его вложений и число сэмплов остаются совместимыми. В примере {link} конвейер сохраняется при замене текстуры глубины. -concepts.platforms.lifecycle.guidance.link: рендерера вращающегося куба -concepts.platforms.lifecycle.title: Размеры и время жизни выходной текстуры определяются хостом -concepts.platforms.ownership.description: Приложение владеет назначенным им контекстом и ресурсами, созданными для рендеринга. Элемент управления владеет собственными ресурсами презентации. Изменение свойства {graphicsContext} элемента управления заставляет планировщик пересоздать ресурсы элемента управления; это не пересоздаёт конвейеры, буферы или текстуры приложения для нового контекста. -concepts.platforms.ownership.details: Координируйте замену ресурсов с жизненным циклом кадров элемента управления. Остановите формирование кадров в элементе управления и завершите активные операции на GPU перед освобождением ресурсов приложения или назначенного контекста. Удаление элемента управления не передаёт владение контекстом элементу управления. -concepts.platforms.ownership.guidance: Общий планировщик {frameSchedulerCs} отправляет задачи кадра через UI-диспетчер элемента управления. Обработчики кадров должны быть сфокусированы на обновлении и записи кадра; длительная работа CPU в них также задерживает интерфейс пользователя. -concepts.platforms.ownership.title: Ресурсы приложения не принадлежат элементу управления -concepts.platforms.surface.context: Поддержка операционной системы оконной библиотекой или UI-фреймворком не гарантирует, что выбранный бэкенд GPU доступен на ней. Возможности устройства, драйверы и поддержка нативной поверхности должны совпадать. Проверяйте поддержку трассировки лучей и mesh shading через {contextCapabilities} перед созданием соответствующих нагрузок. -concepts.platforms.surface.description: В примере {link} библиотека Silk.NET используется для создания окна и обработки событий. Zenith.NET подключается к этому окну через описание {surface} и цепочку обмена {swapChain}. Поверхность содержит нативные дескрипторы и размеры; создание этого описания не создаёт и не захватывает во владение окно операционной системы. -concepts.platforms.surface.description.link: треугольника -concepts.platforms.surface.details: "Дескриптор должен соответствовать выбранному бэкенду:" -concepts.platforms.surface.guidance: Файл {appCs} из учебника демонстрирует варианты для Windows, macOS и X11. Его хост для Linux предоставляет дескрипторы Xlib; для работы в сессии Wayland требуется XWayland. Нативное приложение Wayland предоставляло бы другие дескрипторы через {surfaceWayland}. +concepts.platforms.integration.table.wpf.presentation: "Импортирует общую текстуру Direct3D 11 и через взаимодействие с Direct3D копирует её в поверхность, отображаемую {d3DImage}. Реализация: {surfaceCs}." +concepts.platforms.integration.title: "Фреймворк и вывод изображения" +concepts.platforms.lifecycle.context: "При создании соответствующих вложений используйте {descWidth}, {descHeight}, {descFormat} и {descSampleCount} выходной текстуры, переданной событием рендеринга. Эта текстура задаёт реальные размеры цели вывода; их не следует вычислять по размеру элемента интерфейса или масштабу экрана." +concepts.platforms.lifecycle.description: "Цепочка обмена использует ширину и высоту кадрового буфера в пикселях. При масштабировании экрана они могут отличаться от логических размеров окна. Отложите рендеринг и изменение размера цепочки, пока хотя бы один размер равен нулю. Получайте {swapChainDrawable} для каждого кадра: цепочка обмена владеет этой текстурой и может заменить её после вывода или изменения размера." +concepts.platforms.lifecycle.details: "При изменении размеров кадрового буфера дождитесь всех обращений GPU к старым изображениям перед вызовом {swapChainResize}. Чтобы заменить нативную цель вывода, после завершения этих обращений передайте её новое описание и дескрипторы в {swapChainRefresh}. При завершении приложения освободите цепочку обмена до уничтожения её нативной цели вывода." +concepts.platforms.lifecycle.guidance: "Если размеры принадлежащих приложению текстур глубины или внеэкранных текстур следуют за окном, пересоздайте их при изменении размера и обновите константы с их дескрипторами. Конвейер можно использовать дальше, пока форматы вложений и число выборок совпадают. Повторное использование конвейера при замене текстур показано в {link}." +concepts.platforms.lifecycle.guidance.link: "примере вращающегося куба" +concepts.platforms.lifecycle.title: "Размеры и время жизни цепочки обмена" +concepts.platforms.ownership.description: "Приложение владеет назначенным контекстом и своими ресурсами рендеринга, а элемент управления — ресурсами вывода. При изменении {graphicsContext} представления планировщик пересоздаёт ресурсы элемента управления для нового контекста. Приложение также должно пересоздать для этого контекста свои конвейеры, буферы и текстуры." +concepts.platforms.ownership.details: "Перед заменой ресурсов рендеринга остановите обработку кадров представления и дождитесь использующей их работы GPU. Только после этого освобождайте старые ресурсы или контекст. При удалении представления приложение по-прежнему отвечает за освобождение назначенного контекста." +concepts.platforms.ownership.guidance: "Общий {frameSchedulerCs} выполняет обработчики кадров через диспетчер UI представления. Ограничивайте их работу обновлением сцены и записью команд: длительные вычисления на CPU здесь задерживают и отклик интерфейса." +concepts.platforms.ownership.title: "Ресурсы приложения и элемента интерфейса" +concepts.platforms.surface.description: "В {link} Silk.NET создаёт окно и обрабатывает события. Zenith.NET получает нативные дескрипторы окна и его размеры через описание {surface}, по которому создаёт {swapChain}. За само окно операционной системы по-прежнему отвечает приложение." +concepts.platforms.surface.description.link: "уроке с треугольником" +concepts.platforms.surface.details: "Дескрипторы поверхности должны соответствовать бэкенду:" +concepts.platforms.surface.guidance: "Общая оболочка примеров в {appCs} поддерживает Windows, macOS и X11. Под Linux её окно предоставляет дескрипторы Xlib, поэтому в сеансе Wayland для запуска нужен XWayland. Приложение с нативным Wayland передаёт дескрипторы дисплея и поверхности через {surfaceWayland}." concepts.platforms.surface.table.android.backend: Vulkan в Android. concepts.platforms.surface.table.apple.backend: Metal на платформах Apple. -concepts.platforms.surface.table.headings.backend: Бэкенд +concepts.platforms.surface.table.headings.backend: "Бэкенд и платформа" concepts.platforms.surface.table.headings.factory: Фабрика поверхности concepts.platforms.surface.table.headings.handles: Дескрипторы, предоставляемые хостом concepts.platforms.surface.table.wayland.backend: Vulkan с нативным хостом Wayland. @@ -94,43 +93,43 @@ concepts.platforms.surface.table.wayland.handles: Дисплей и поверх concepts.platforms.surface.table.win32.backend: DirectX 12 или Vulkan в Windows. concepts.platforms.surface.table.xlib.backend: Vulkan в Linux с X11 или XWayland. concepts.platforms.surface.table.xlib.handles: Дисплей и окно X11 -concepts.platforms.surface.title: Предоставление нативной поверхности при самостоятельном управлении презентацией +concepts.platforms.surface.title: "Нативные поверхности вывода" concepts.platforms.title: Интеграция с платформами -concepts.resources.allocation.context: "Начните с ресурсов, создаваемых контекстом, если вам не нужен собственный аллокатор. При использовании кучи дождитесь завершения всех задач GPU, обращающихся к её ресурсам. Затем освободите размещённые ресурсы и только после этого саму кучу." -concepts.resources.allocation.description: "Объект {heap} предоставляет память для размещения ресурсов по явно заданным смещениям в байтах. Приложение выбирает эти смещения и отслеживает занятые области." -concepts.resources.allocation.details: "Перед размещением вызовите {contextGetSizeAndAlignment} с точным описанием буфера или текстуры. Выберите смещение, кратное возвращённому выравниванию, зарезервируйте возвращённый размер и убедитесь, что ресурс не выходит за общий размер кучи в байтах. Области действующих выделений памяти не должны пересекаться. Хранилище текстуры может включать заполнение и выравнивание, зависящие от бэкенда, поэтому произведение числа пикселей на число байтов на пиксель не даёт размер выделения." -concepts.resources.allocation.guidance: "Для размещённых буферов резидентность буфера должна соответствовать резидентности кучи. Обычные текстуры GPU, описанные здесь, размещайте в кучах только для GPU. Размер и выравнивание — требования к размещению, а не гарантия того, что любой ресурс можно поместить в любую кучу на каждом бэкенде." -concepts.resources.allocation.title: Размещение ресурсов в куче при необходимости контроля выделения памяти +concepts.resources.allocation.context: "Размещённые в куче ресурсы зависят от её памяти в течение всего своего времени жизни. После последнего использования на GPU освободите сначала ресурсы, затем кучу." +concepts.resources.allocation.description: "Используйте {heap}, если приложение должно самостоятельно управлять выделением памяти. Ресурсы размещаются в куче по явно заданным смещениям в байтах; приложение выбирает эти смещения и учитывает занятые области." +concepts.resources.allocation.details: "Для каждого ресурса вызовите {contextGetSizeAndAlignment} с тем описанием буфера или текстуры, которое будет использовано при создании. Зарезервируйте возвращённый размер по смещению, кратному указанному выравниванию. Вся область должна находиться в пределах кучи и не пересекать другую ещё действующую область. Размер текстуры может включать дополнительные промежутки, зависящие от бэкенда, поэтому вычислить его только по числу пикселей и байтам на пиксель нельзя." +concepts.resources.allocation.guidance: "Резидентность буфера, размещённого в куче, должна совпадать с резидентностью этой кучи. Для текстур используйте кучу, предназначенную только для GPU." +concepts.resources.allocation.title: "Размещение в кучах памяти" concepts.resources.bufferUsages.table.constant.role: Параметры шейдера, считываемые через привязку буфера констант. concepts.resources.bufferUsages.table.headings.role: "Роль" concepts.resources.bufferUsages.table.headings.usage: Назначение -concepts.resources.bufferUsages.table.index.role: Индексы, используемые при индексной отрисовке. -concepts.resources.bufferUsages.table.indirect.role: "Аргументы, считываемые командами косвенной отрисовки или диспатча." +concepts.resources.bufferUsages.table.index.role: "Индексы, используемые при индексированном рисовании." +concepts.resources.bufferUsages.table.indirect.role: "Аргументы, считываемые командами косвенного рисования или косвенного запуска вычислений." concepts.resources.bufferUsages.table.none.role: "Флаги назначения буфера не объявлены." concepts.resources.bufferUsages.table.storageReadOnly.role: "Данные буфера, доступные через привязку шейдера только для чтения." concepts.resources.bufferUsages.table.storageReadWrite.role: "Данные буфера, доступные через привязку шейдера для чтения и записи." concepts.resources.bufferUsages.table.transferDst.role: "Память назначения для копирования на GPU." concepts.resources.bufferUsages.table.transferSrc.role: "Исходные данные для копирования на GPU." -concepts.resources.bufferUsages.table.vertex.role: Вершинные атрибуты, считываемые для отрисовки. +concepts.resources.bufferUsages.table.vertex.role: "Вершинные атрибуты, считываемые для рисования." concepts.resources.bufferUsages.title: Назначения буфера -concepts.resources.description: "Выбирайте описание ресурса исходя из операций, которые будут его использовать. Для текстуры, в которую выполняется рендеринг, из которой делает выборки шейдер и данные которой считываются на CPU, нужно объявить все три назначения и обеспечить синхронизацию между ними. Размещение памяти и время жизни ресурса требуют отдельных решений." -concepts.resources.memory.context: Для буфера, доступного CPU, метод {map} возвращает адрес CPU. Он не ожидает, пока GPU прекратит доступ к тем же байтам. Метод {unmap} аналогично не отправляет задачи и не ожидает завершения. Перед перезаписью данных, доступных для записи CPU, завершите операции чтения GPU, которым всё ещё требуется старое содержимое. -concepts.resources.memory.description: "Структура {bufferDesc} содержит поле {residency}. Выбирайте его в соответствии с тем, как CPU и GPU будут обращаться к данным:" -concepts.resources.memory.details: Резидентность описывает предполагаемый доступ CPU к выделенной памяти. Она не означает, что каждое устройство имеет физически раздельные области памяти CPU и GPU. В треугольнике используется {cpuWriteOnly} для прямой инициализации небольшого буфера вершин. Большой статический меш может получить больше преимуществ от памяти только для GPU с однократной загрузкой. -concepts.resources.memory.guidance: В {textureDesc} нет поля резидентности. Обычные текстуры, создаваемые контекстом, используют память GPU. Их публичный API предоставляет операции загрузки и скачивания для передачи данных CPU без прямого метода отображения. Явные кучи обеспечивают контроль размещения, описанный ниже. -concepts.resources.memory.table.cpuReadOnly.cPUAccess: "Читать отображённую память после завершения копирования на GPU." +concepts.resources.description: "Описание ресурса задаёт допустимые способы использования его памяти. Например, текстуре, которая служит целью рендеринга, читается шейдером и копируется на CPU, нужны флаги назначения для всех трёх операций. Размещение памяти определяет доступ CPU, а синхронизация и управление временем жизни — когда можно обращаться к данным и освобождать память." +concepts.resources.memory.context: "Для доступных CPU буферов {map} возвращает адрес, по которому можно читать или записывать данные. Ни отображение памяти, ни {unmap} не дожидаются GPU. Перед чтением результата приложение должно дождаться его записи на GPU, а перед изменением тех же байтов — всех ещё выполняющихся обращений GPU к ним." +concepts.resources.memory.description: "Поле {residency} в {bufferDesc} задаёт предполагаемый доступ CPU к памяти:" +concepts.resources.memory.details: "Резидентность выражает требования к доступу CPU, в том числе на системах с общей физической памятью CPU и GPU. В примере треугольника {cpuWriteOnly} позволяет напрямую заполнить небольшой вершинный буфер. Для более объёмной статической геометрии может быть предпочтительнее загрузка в память, предназначенную только для GPU." +concepts.resources.memory.guidance: "Текстуры, создаваемые непосредственно через контекст, используют память GPU. Поэтому в {textureDesc} нет поля резидентности: приложение обменивается данными с памятью CPU через загрузку и считывание." +concepts.resources.memory.table.cpuReadOnly.cPUAccess: "Только чтение" concepts.resources.memory.table.cpuReadOnly.typicalRole: "Данные, полученные на GPU для считывания на CPU" -concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "Записывать в отображённую память после завершения предыдущих чтений GPU." +concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "Только запись" concepts.resources.memory.table.cpuWriteOnly.typicalRole: "Данные, предоставляемые или обновляемые CPU" -concepts.resources.memory.table.gpuOnly.cPUAccess: "Передавать байты через буфер загрузки или считывания." +concepts.resources.memory.table.gpuOnly.cPUAccess: "Не предусмотрен" concepts.resources.memory.table.gpuOnly.typicalRole: "Статическая геометрия и рабочие данные GPU" -concepts.resources.memory.table.headings.cPUAccess: Доступ CPU -concepts.resources.memory.table.headings.residency: Резидентность +concepts.resources.memory.table.headings.cPUAccess: "Предусмотренный доступ CPU" +concepts.resources.memory.table.headings.residency: "Режим доступа к памяти" concepts.resources.memory.table.headings.typicalRole: Типичная роль -concepts.resources.memory.title: "Выбор памяти с учётом необходимого доступа CPU" -concepts.resources.textureUsages.description: "Флаги назначения для передачи описывают направление копирования на GPU. Доступ CPU — отдельное решение о размещении памяти, рассмотренное ниже." -concepts.resources.textureUsages.details: "Объединение флагов объявляет несколько ролей, но не выполняет операции и не упорядочивает доступ. Для текстур по-прежнему необходимо правильно выбирать {link}, а их форматы должны поддерживать запрошенные назначения на выбранном устройстве." -concepts.resources.textureUsages.details.link: "состояние доступа и синхронизацию" +concepts.resources.memory.title: "Доступ CPU и размещение памяти" +concepts.resources.textureUsages.description: "Флаги передачи указывают, служит ли ресурс источником или приёмником при копировании на GPU. Прямой доступ CPU к его памяти определяется отдельно, при выборе размещения памяти." +concepts.resources.textureUsages.details: "Флаги назначения объявляют допустимые способы использования текстуры. Переход между ними требует соблюдения правил, описанных в разделе «{link}». Устройство также должно поддерживать выбранные операции для указанного формата текстуры." +concepts.resources.textureUsages.details.link: "состояния доступа и синхронизация" concepts.resources.textureUsages.table.colorAttachment.role: "Цветовое вложение в проходе рендеринга." concepts.resources.textureUsages.table.depthStencilAttachment.role: "Вложение глубины и трафарета в проходе рендеринга." concepts.resources.textureUsages.table.headings.role: "Роль" @@ -142,225 +141,220 @@ concepts.resources.textureUsages.table.transferDst.role: "Память изоб concepts.resources.textureUsages.table.transferSrc.role: "Данные исходного изображения для копирования на GPU." concepts.resources.textureUsages.title: Назначения текстуры concepts.resources.title: Управление ресурсами -concepts.resources.transfers.context: Скачивание данных записывает команду копирования GPU во внутреннее хранилище считывания. Библиотека копирует эти байты в предоставленный буфер CPU при сбросе завершённого командного буфера для повторного использования. Сохраняйте память назначения выделенной, а управляемую память — закреплённой, пока не завершится вызов {wait} для значения отправки. -concepts.resources.transfers.description: "Загрузка копирует данные CPU в ресурс GPU, а считывание возвращает данные ресурса в память CPU. Методы самого ресурса завершают эту передачу до возврата из вызова:" -concepts.resources.transfers.details: "Эти ожидания относятся только к передаче, отправленной данными методами. Они не обнаруживают зависимости от другой очереди, которая уже читала или записывала ресурс. Установите такие зависимости до вызова метода ресурса. При прямом копировании через отображённую память вызывающий код также обязан обеспечить завершение соответствующей работы GPU." -concepts.resources.transfers.guidance: "Используйте {commandBufferUpload} или {commandBufferDownload}, если копирование должно быть записано вместе с другими операциями. Время жизни их указателей различается:" -concepts.resources.transfers.item: "Загрузка во время вызова копирует исходные данные CPU во внутренний буфер загрузки, также называемый промежуточной памятью staging. Исходный указатель должен оставаться действительным только на время этого вызова." -concepts.resources.transfers.notes: "Для текстуры шаг строки — расстояние в байтах между соседними строками данных CPU, а шаг среза — расстояние в байтах между соседними срезами по глубине. Эти значения не описывают внутреннее размещение текстуры в памяти GPU. Различие между завершением GPU и считыванием данных описано в разделе {link}." +concepts.resources.transfers.context: "При считывании данные GPU сначала копируются во внутреннюю промежуточную память. Затем библиотека переносит их в указанную память CPU, когда возвращает завершённый командный буфер для повторного использования. Вызов {wait} для значения отправки, содержащей считывание, завершает оба шага. До возврата из этого вызова память назначения должна оставаться выделенной, а управляемая память — закреплённой." +concepts.resources.transfers.description: "Загрузка копирует данные CPU в ресурс GPU, а считывание — данные ресурса в память CPU. Методы буферов и текстур завершают передачу до возврата управления:" +concepts.resources.transfers.details: "Перед вызовом этих методов устраните конфликтующие обращения из других очередей. Внутреннее ожидание метода относится только к его собственной передаче и не создаёт зависимость от другой очереди. При прямом копировании через отображённую память ожидание конфликтующих обращений GPU полностью возлагается на вызывающий код." +concepts.resources.transfers.guidance: "Чтобы отправить передачу данных вместе с другой работой GPU, запишите её через {commandBufferUpload} или {commandBufferDownload}. Требования ко времени жизни исходной памяти при загрузке и памяти назначения при считывании различаются:" +concepts.resources.transfers.item: "Во время вызова загрузки библиотека копирует исходные данные во временную промежуточную память. Позже GPU читает данные именно из неё, поэтому исходный указатель приложения нужен только до возврата из вызова." +concepts.resources.transfers.notes: "При передаче текстур шаг строки — это расстояние в байтах между соседними строками данных CPU, а шаг среза — расстояние между соседними срезами по глубине. По этим значениям выполняется копирование между памятью CPU и хранилищем текстуры на GPU. Почему завершение GPU и запись в память назначения — разные этапы, объясняется в статье «{link}»." concepts.resources.transfers.notes.link: Синхронизация -concepts.resources.transfers.table.bufferDownload.transfer: Прямое копирование CPU для {cpuReadOnly}; иначе отправляет скачивание в очередь передачи и ожидает. -concepts.resources.transfers.table.bufferUpload.transfer: Прямое копирование CPU для {cpuWriteOnly}; иначе отправляет загрузку в очередь передачи и ожидает. +concepts.resources.transfers.table.bufferDownload.transfer: "Для {cpuReadOnly} копирует непосредственно из отображённой памяти. В остальных случаях отправляет считывание в передающую очередь и дожидается его завершения." +concepts.resources.transfers.table.bufferUpload.transfer: "Для {cpuWriteOnly} копирует непосредственно в отображённую память. В остальных случаях отправляет загрузку в передающую очередь и дожидается её завершения." concepts.resources.transfers.table.headings.method: Метод -concepts.resources.transfers.table.headings.transfer: "Способ передачи данных" +concepts.resources.transfers.table.headings.transfer: "Порядок передачи" concepts.resources.transfers.table.textureTransfers.method: "{textureUpload} / {textureDownload}" -concepts.resources.transfers.table.textureTransfers.transfer: "Использует графическую очередь, переводит выбранный подресурс в состояние для копирования, затем в запрошенное конечное состояние и ожидает завершения передачи." -concepts.resources.transfers.title: "Выбор между немедленной передачей и записью передачи в командный буфер" +concepts.resources.transfers.table.textureTransfers.transfer: "Отправляет копирование и переходы состояния текстуры в графическую очередь, затем ожидает завершения. Выбранный подресурс остаётся в запрошенном конечном состоянии." +concepts.resources.transfers.title: "Немедленная и записываемая передача" concepts.resources.usages.description: "{bufferUsages} и {textureUsages} — флаговые перечисления, объявляющие предполагаемые роли ресурса. Они задаются в полях {bufferDescUsages} и {textureDescUsages} соответственно. Если у ресурса несколько ролей, члены флагового перечисления можно объединить с помощью {value}." -concepts.resources.usages.title: Объявление необходимых назначений перед созданием ресурса -concepts.resources.views.description: Объект {bufferView} описывает область буфера и её интерпретацию. Объект {textureView} выбирает совместимый тип текстуры, формат и диапазон подресурсов. Представление разделяет базовое хранилище; оно не копирует данные и не добавляет назначения, отсутствовавшие при создании ресурса. Его диапазон также не гарантирует переносимую проверку границ в шейдере. -concepts.resources.views.details: "Для представления по умолчанию используйте дескриптор самого ресурса. Если нужна другая область или иная совместимая интерпретация, создайте представление. Сохраняйте ссылки C# на представление и базовый ресурс, пока задачи GPU могут их использовать: один лишь дескриптор ресурса не поддерживает время жизни ни одного из объектов. Освобождайте их только после последнего использования GPU. Заменив любой из объектов, обновите константы, содержащие его прежний {link}." +concepts.resources.usages.title: "Назначения ресурсов" +concepts.resources.views.description: "{bufferView} описывает область буфера и интерпретацию её данных. {textureView} выбирает диапазон подресурсов, совместимые тип и формат текстуры. Оба представления ссылаются на существующую память с назначениями, объявленными при её создании. Диапазоны представлений описывают доступ, но не обеспечивают одинаковую проверку границ в шейдерах на всех бэкендах." +concepts.resources.views.details: "Собственный дескриптор ресурса предоставляет его представление по умолчанию. Для другой области или совместимого способа интерпретации создайте отдельное представление. Сохраняйте и представление, и исходный ресурс до завершения их использования на GPU: дескриптор сам по себе не удерживает ни один из объектов. При замене любого из них обновите константы, содержащие прежний {link}." concepts.resources.views.details.link: "дескриптор ресурса" -concepts.resources.views.guidance: "В {link} показана замена текстуры глубины при изменении размера. В {detail} входная текстура хранится отдельно от доступной для записи выходной. В обоих случаях время жизни ресурса соответствует работе, которая его фактически использует." -concepts.resources.views.guidance.detail: примере вычислений -concepts.resources.views.guidance.link: "примере вращающегося куба" -concepts.resources.views.title: "Сохранение доступности представлений и их базовых ресурсов" -concepts.shaders.binding.context: "В примере вычислений поле {input} заполняется значением {inputTextureSampledHandle}, а {output} — {outputTextureStorageHandle}. Типизированный {descriptorHandle} в Slang указывает шейдеру способ доступа к каждому ресурсу:" -concepts.shaders.binding.description: "Метод {setConstantBuffer} привязывает буфер и байтовое смещение для констант текущего конвейера. Он привязывает существующую видимую для GPU память; он не загружает значение C#. Сначала заполните буфер и убедитесь, что предыдущие читатели GPU завершили работу, прежде чем перезаписывать его байты." -concepts.shaders.binding.details: "Установите конвейер перед его буфером констант. Для вычислительной нагрузки с уже созданными и загруженными ресурсами запись выполняется в следующем порядке:" -concepts.shaders.binding.guidance: Этот фрагмент предполагает записываемый {commandBuffer}, конвейер {computePipeline}, загруженный буфер {constantBuffer} с назначением {bufferUsagesConstant} и количество групп потоков для данной задачи. Смещение 0 привязывает начало буфера. Если несколько записей данных констант делят один буфер, начальное смещение каждой записи должно соответствовать выравниванию привязки бэкенда. Это требование не зависит от разметки полей внутри самой записи. -concepts.shaders.binding.notes: Структура {resourceHandle} хранит два 32-битных поля, но их интерпретация определяется бэкендом. Не рассматривайте её как универсальный индекс дескриптора, адрес или значение, переносимое между контекстами. Дескриптор не создаёт ресурс, не добавляет отсутствующее назначение и не выполняет синхронизацию. -concepts.shaders.binding.reference: "Сохраняйте ссылки на ресурс и любое представление, использованное для получения его дескриптора. Освобождайте их только после завершения последнего использования шейдером. При замене текстуры или представления обновите константы со старым дескриптором. Эта связь времени жизни описана в разделе «{link}»." +concepts.resources.views.title: "Представления и исходные ресурсы" +concepts.shaders.binding.context: "В вычислительном примере {inputTextureSampledHandle} присваивается {input}, а {outputTextureStorageHandle} — {output}. В Slang параметр типа {descriptorHandle} определяет доступ шейдера к ресурсу:" +concepts.shaders.binding.description: "{setConstantBuffer} выбирает существующий буфер и смещение в байтах, с которого текущий конвейер читает константы. Загрузите параметры в эту память до обращения шейдера. Если ранее отправленная работа GPU ещё читает те же байты, дождитесь её завершения перед обновлением." +concepts.shaders.binding.details: "Подготовьте командный буфер, вычислительный конвейер, заполненный константный буфер и число групп потоков. Затем запишите запуск вычислений в следующем порядке. Сначала выберите конвейер, поскольку привязка константного буфера относится именно к нему:" +concepts.shaders.binding.guidance: "Здесь {commandBuffer} записывает запуск {computePipeline} с параметрами из {constantBuffer}. Буферу нужно назначение {bufferUsagesConstant}; смещение 0 выбирает его начало. Если в буфере несколько записей констант, начальное смещение каждой также должно удовлетворять выравниванию привязки, требуемому бэкендом. Это отдельное условие, не зависящее от размещения полей внутри записи." +concepts.shaders.binding.notes: "{resourceHandle} содержит два 32-битных поля, интерпретация которых зависит от бэкенда. Их значения действительны только в контексте, где создан ресурс." +concepts.shaders.binding.reference: "Сохраняйте ресурс и представление, из которого получен дескриптор, до завершения последнего обращения шейдера. При замене обновите константы со старым дескриптором. Правила владения изложены в статье «{link}»." concepts.shaders.binding.reference.link: Управление ресурсами -concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: Чтение структурированных элементов типа шейдера {t}. -concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: Чтение или запись структурированных элементов типа шейдера {t}. +concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: "Чтение структурированных элементов шейдерного типа {t}" +concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: "Чтение и запись структурированных элементов шейдерного типа {t}" concepts.shaders.binding.table.headings.access: Предполагаемый доступ concepts.shaders.binding.table.headings.cHandle: "Дескриптор C#" concepts.shaders.binding.table.headings.slangFieldType: Тип поля Slang -concepts.shaders.binding.table.samplerHandle.access: Предоставление состояния сэмплирования текстуры. -concepts.shaders.binding.table.textureSampledHandle.access: Чтение текстуры. -concepts.shaders.binding.table.textureStorageHandle.access: Чтение или запись текстуры хранения. -concepts.shaders.binding.title: Привязка буфера констант и описываемых им ресурсов -concepts.shaders.compilation.description: "{zenithCompiler} компилирует именованную точку входа Slang и возвращает {shaderDesc}. Используйте свойство контекста {graphicsApi}, чтобы результат предназначался бэкенду, создающему шейдер: DXIL для DirectX 12, библиотека Metal для Metal или SPIR-V для Vulkan." -concepts.shaders.compilation.details: "Например, при наличии {context} и скопированного рядом с исполняемым файлом шейдера треугольника:" -concepts.shaders.compilation.guidance: "Имя {vSMain} должно точно совпадать с именем точки входа в файле шейдера. Сохраняйте объекты шейдеров действительными при создании конвейера и освобождайте их после его создания, как показано в учебнике «{link}». Выполняйте эту инициализацию один раз, а не компилируйте шейдеры заново для каждого кадра." -concepts.shaders.compilation.guidance.link: Первый треугольник -concepts.shaders.compilation.title: Компиляция точки входа для выбранного контекста -concepts.shaders.description: "Шейдер принимает данные, предоставляемые приложением. Вершинные атрибуты описывают отдельные вершины; буферы хранят параметры или массивы; дескрипторы ресурсов идентифицируют другие ресурсы, к которым обращается шейдер. Объявления C# и объявления Slang должны согласовывать смысл этих значений. Простого совпадения имени поля недостаточно: разметка, доступ к ресурсам и привязка должны полностью совпадать." -concepts.shaders.dispatch.description: Метод {dispatch} принимает количество групп потоков. Точка входа {numthreads} в примере вычислений запускает 16 × 16 потоков на группу. Разделите размеры изображения на 16 с округлением вверх, чтобы получить количество групп. Например, изображению 17 × 19 требуется 2 × 2 группы. Шейдер проверяет пиксельные координаты относительно размеров изображения, поскольку последние группы могут содержать потоки за пределами изображения. -concepts.shaders.dispatch.details: Компилятор сохраняет объявленный размер группы точки входа в {shaderDescThreadGroupSize}; он не пересчитывает размеры в пикселях, переданные в {dispatch}, в количество групп. Полный пример привязки и запуска см. в {computeShaderRendererCs} и его шейдере, а перед чтением вывода в другом проходе используйте {link}. +concepts.shaders.binding.table.samplerHandle.access: "Состояние выборки из текстур" +concepts.shaders.binding.table.textureSampledHandle.access: "Чтение текстур" +concepts.shaders.binding.table.textureStorageHandle.access: "Чтение и запись текстур хранения" +concepts.shaders.binding.title: "Буферы констант и дескрипторы ресурсов" +concepts.shaders.compilation.description: "{zenithCompiler} компилирует именованную точку входа Slang в {shaderDesc}. {graphicsApi} контекста определяет результат: DXIL для DirectX 12, библиотеку Metal для Metal или SPIR-V для Vulkan." +concepts.shaders.compilation.details: "Используя уже созданный графический контекст {context}, скомпилируйте шейдер треугольника из копии рядом с исполняемым файлом:" +concepts.shaders.compilation.guidance: "Имя точки входа {vSMain} должно совпадать с её объявлением в файле шейдера. Компилируйте шейдеры и создавайте конвейеры при инициализации, а во время рендеринга используйте готовые конвейеры повторно. После создания конвейера объекты шейдеров можно освободить, как показано в {link}." +concepts.shaders.compilation.guidance.link: "учебном примере треугольника" +concepts.shaders.compilation.title: "Компиляция шейдеров" +concepts.shaders.description: "Объявления C# и Slang должны согласованно определять, где хранится каждое значение и как шейдер к нему обращается. Описания вершинного ввода задают атрибуты вершин, объявления буферов в шейдерах — параметры и массивы, а дескрипторы указывают используемые шейдером ресурсы." +concepts.shaders.dispatch.description: "{dispatch} задаёт число выполняемых групп потоков. В вычислительном примере объявлено {numthreads}, поэтому каждая группа содержит 16 × 16 потоков. Чтобы обработать всё изображение, разделите ширину и высоту на 16 и округлите каждый результат вверх. Для изображения 17 × 19 пикселей нужны 2 × 2 группы. Шейдер проверяет координаты каждого потока и пропускает те, что выходят за границы изображения." +concepts.shaders.dispatch.details: "Объявленный размер группы доступен через {shaderDescThreadGroupSize}. По нему можно рассчитать число групп для {dispatch}; полный расчёт показан в {computeShaderRendererCs}. Последующие обращения к полученному изображению должны соблюдать требования из статьи «{link}»." concepts.shaders.dispatch.details.link: Синхронизация -concepts.shaders.dispatch.title: Запуск групп потоков, а не пикселей -concepts.shaders.layout.context: "В {link} смещения заданы явно. Для этого объявления в области видимости требуются {systemRuntimeInteropServices} и {zenithNET}:" +concepts.shaders.dispatch.title: "Группы потоков" +concepts.shaders.layout.context: "Такая организация показана в {link}: они содержат размеры изображения и два дескриптора текстур. Явные смещения указывают начало каждого поля. Для объявления используются {systemRuntimeInteropServices} и {zenithNET}:" concepts.shaders.layout.context.link: "константах C# примера вычислений" -concepts.shaders.layout.description: "Для вершинного ввода структура {inputLayout} конвейера описывает форматы, смещения, шаг и семантику. Положение {float3} треугольника, за которым следует цвет {float4}, занимает 28 байт, причём цвет находится со смещения 12. Метод {inputLayoutAdd} рассчитывает эту упакованную разметку; он не анализирует структуру C#. Если поля C# содержат выравнивающие байты, предоставьте соответствующую разметку, а не предполагайте плотную упаковку полей." -concepts.shaders.layout.details: "Буферы констант содержат параметры шейдера, а структурированные буферы — массивы элементов объявленного типа. Оба читаются согласно объявлениям Slang и не используют {inputLayout}. Проверяйте смещения полей и размеры элементов для скомпилированного представления шейдера, включая заполняющие байты. Неуправляемый тип C# подходит для побайтового копирования, но сам по себе не гарантирует совпадения с типом шейдера. В частности, не переносите плотную разметку {float3} вершины на каждый буфер шейдера." -concepts.shaders.layout.guidance: Дескриптор ресурса — это небольшое значение, ссылающееся на существующий ресурс. Копирование дескриптора в буфер констант не копирует содержимое самого ресурса. +concepts.shaders.layout.description: "Для вершинного ввода {inputLayout} задаёт формат, смещение и семантику каждого атрибута, а также шаг между вершинами. В треугольнике за позицией {float3} следует цвет {float4}: цвет начинается со смещения 12 байт, а вершина занимает 28 байт. {inputLayoutAdd} рассчитывает эту плотную раскладку по форматам элементов. Если структура C# содержит выравнивающие промежутки, учитывайте их в смещениях и шаге." +concepts.shaders.layout.details: "Константные буферы содержат параметры шейдера, а структурированные — массивы типизированных элементов. Их раскладка определяется объявлениями Slang, а не {inputLayout}. Смещения полей C#, размеры элементов и выравнивающие промежутки должны соответствовать раскладке скомпилированного шейдера. Неуправляемый тип C# можно скопировать как последовательность байтов, но его размещение в памяти не обязательно соответствует раскладке шейдера: плотно упакованный {float3} в вершине может требовать другого выравнивания в буфере шейдера." +concepts.shaders.layout.guidance: "Параметры шейдера могут содержать дескрипторы ресурсов наряду с обычными значениями. Дескриптор указывает на уже существующую память, поэтому его копирование в константный буфер не копирует содержимое ресурса." concepts.shaders.layout.notes: "Соответствующее объявление в {computeShaderSlang}:" -concepts.shaders.layout.reference: "Размеры занимают первые восемь байт, за ними следуют два восьмибайтовых дескриптора ресурсов. Пример на C# резервирует всего 256 байт. Этот размер выбран автором примера, а не является правилом, требующим, чтобы все структуры Slang или блоки констант занимали 256 байт. Дополнение общего размера также не исправляет поле, расположенное с неверным смещением." -concepts.shaders.layout.title: Различные правила разметки для вершинных входов и данных шейдеров -concepts.shaders.matrices.description: "Компилятор запрашивает хранение матриц по строкам (row-major), где элементы каждой строки хранятся последовательно. В примере {link} три значения {matrix4x4} размещаются со смещениями 0, 64 и 128. В {detail} используется {mulVectorMatrix} в порядке умножения: модель, вид, проекция." -concepts.shaders.matrices.description.detail: шейдере -concepts.shaders.matrices.description.link: рендерера вращающегося куба -concepts.shaders.matrices.details: Порядок хранения определяет расположение элементов матрицы в памяти; порядок умножения определяет преобразование. Обе стороны должны быть согласованы. Добавление транспонирования без проверки обоих аспектов может скрыть одно несоответствие, вызвав другое. -concepts.shaders.matrices.title: Согласованность хранения и умножения матриц +concepts.shaders.layout.reference: "Два размера занимают первые восемь байт, за ними следуют два дескриптора по восемь байт каждый. В примере C# под всю запись отведено 256 байт. Размер другой записи следует определять по её собственным полям, требуемой раскладке и выравниванию." +concepts.shaders.layout.title: "Размещение данных" +concepts.shaders.matrices.description: "Компилятор использует построчное хранение матриц: элементы каждой строки расположены подряд. В {link} три значения {matrix4x4} находятся по смещениям 0, 64 и 128 байт. Его {detail} применяет {mulVectorMatrix} в порядке модели, вида и проекции." +concepts.shaders.matrices.description.detail: "шейдер" +concepts.shaders.matrices.description.link: "рендерере вращающегося куба" +concepts.shaders.matrices.details: "Порядок хранения определяет размещение элементов матрицы в памяти; порядок умножения — преобразование. Используйте согласованные соглашения в C# и Slang." +concepts.shaders.matrices.title: "Соглашения о матрицах" concepts.shaders.title: Данные шейдеров и привязка -concepts.synchronization.backends.description: DirectX 12 и Vulkan кодируют переходы текстур с информацией о layout и доступе. В реализации {transition} для Metal в Zenith.NET операций нет. Metal группирует записанную работу в энкодеры рендеринга и вычислений. Бэкенд вставляет барьеры видимости при завершении этих групп, делая предыдущие записи доступными для последующей работы. Явные вызовы {barrier} обрабатывают зависимости, такие как последовательные вычислительные диспатчи внутри одного энкодера. -concepts.synchronization.backends.details: Это различие важно при изменении рабочей нагрузки. В {link} за диспатчем следует графический проход рендеринга, который также создаёт границу энкодера в Metal. Два зависимых вычислительных диспатча не создают такую границу простым изменением объявленного layout текстуры. Сохраняйте переходы, требуемые общим API, и отдельно определяйте зависимость между фактическими командами производства и потребления данных. +concepts.synchronization.backends.description: "DirectX 12 и Vulkan кодируют переходы текстур как изменения состояния и доступа. В реализации {transition} для Metal в Zenith.NET нет эквивалентной операции. Вместо этого бэкенд Metal объединяет команды в графические и вычислительные кодировщики и вставляет барьеры видимости при завершении кодировщика. Для зависимых операций внутри одного кодировщика, например последовательных вычислительных запусков, нужны явные вызовы {barrier}." +concepts.synchronization.backends.details: "В {link} начало графического прохода завершает вычислительный кодировщик и делает его результат видимым графическим командам. Два последовательных вычислительных запуска остаются в одном кодировщике, поэтому их зависимость требует барьера, даже если между ними записан переход состояния текстуры. Переносимая последовательность команд должна учитывать и зависимости обращений, и состояния текстур." concepts.synchronization.backends.details.link: примере вычислений -concepts.synchronization.backends.title: Переход не идентичен на каждом бэкенде -concepts.synchronization.barriers.context: Значение {barrierStagesAll} представляет собой более широкую область видимости, а не автоматический детектор зависимостей. Выбирайте стадии, которые фактически охватывают выполняемую работу, и используйте их только в очереди, поддерживающей эти операции. -concepts.synchronization.barriers.description: "Рассмотрите два вычислительных диспатча: первый записывает данные симуляции, а второй читает их для выполнения следующего шага. Оба используют буферы хранения, поэтому менять layout текстуры не требуется. Вставьте следующую инструкцию между диспатчами в их командном буфере:" -concepts.synchronization.barriers.details: Первый аргумент определяет стадию-производитель, а второй — стадию-потребитель. Барьер устанавливает соответствующую зависимость выполнения и памяти на GPU. Бэкенд транслирует эти стадии в свои правила выполнения и доступа к памяти. Этот барьер не меняет layout текстуры и не ожидает всю работу на устройстве. -concepts.synchronization.barriers.guidance: В примере {link} этот шаблон используется между зависимыми диспатчами. Размещайте барьер в месте возникновения зависимости. Барьер, расположенный после того, как потребитель уже записан, не может упорядочить этого потребителя относительно более раннего производителя. +concepts.synchronization.backends.title: "Поведение бэкендов" +concepts.synchronization.barriers.context: "Выбирайте стадии, которые охватывают нужные обращения и поддерживаются очередью. {barrierStagesAll} включает все поддерживаемые стадии. Если зависимость затрагивает лишь часть из них, можно указать более узкий набор." +concepts.synchronization.barriers.description: "Рассмотрим два запуска вычислений в одном командном буфере: первый записывает данные симуляции, второй их читает. Барьер между ними позволяет второму запуску увидеть результаты завершённых записей. Для буфера хранения он упорядочивает обращения без перехода состояния текстуры:" +concepts.synchronization.barriers.details: "Первый аргумент указывает стадии, которые произвели данные, второй — стадии, которым они понадобятся. Вместе они описывают порядок выполнения и видимость памяти, необходимые между двумя запусками." +concepts.synchronization.barriers.guidance: "Этот порядок используется в {link} между шагами симуляции. Каждый барьер следует за запуском, который производит данные, и предшествует запуску, который их использует." concepts.synchronization.barriers.guidance.link: симуляции FluidTank -concepts.synchronization.barriers.title: Упорядочивание зависимых команд с помощью барьера -concepts.synchronization.dependencies.description: "Для каждого разделяемого ресурса определите первую и следующую операции доступа, а также выполняет ли какая-либо из них запись. Два чтения одних данных не требуют упорядочивания для защиты содержимого, хотя смена layout или презентация могут вводить другие требования. Запись с последующим чтением, чтение с последующей перезаписью или две записи могут требовать зависимости." -concepts.synchronization.dependencies.details: "Затем выберите механизм в зависимости от того, где эти операции выполняются:" -concepts.synchronization.dependencies.guidance: Эти механизмы взаимосвязаны, но не взаимозаменяемы. Отправка команд по порядку не заменяет все зависимости памяти. Ожидание очереди не объявляет новое состояние layout текстуры, а барьер команд не блокирует вызывающий поток CPU. +concepts.synchronization.barriers.title: "Барьеры конвейера" +concepts.synchronization.dependencies.description: "Для каждого ресурса определите обращения к одним и тем же данным. Если хотя бы одно из них записывает, сохраните необходимый порядок. Два чтения не конфликтуют, хотя требования к состоянию текстуры и выводу изображения продолжают действовать. Обновление данных с CPU и освобождение ресурсов тоже должны ждать, пока GPU закончит использовать соответствующую память." +concepts.synchronization.dependencies.details: "Выбор механизма зависит от места выполнения операций:" +concepts.synchronization.dependencies.guidance: "Одной задаче может потребоваться несколько механизмов. Например, текстуре, созданной вычислениями в другой очереди, нужны зависимость между отправками и подходящее состояние для следующего обращения. Блокировать CPU при этом нужно только тогда, когда он сам должен обратиться к данным или освободить их память." concepts.synchronization.dependencies.table.cpuAccess.mechanism: Вызов {wait} для соответствующего значения завершения. -concepts.synchronization.dependencies.table.cpuAccess.situation: CPU должен подождать перед доступом к данным или их освобождением -concepts.synchronization.dependencies.table.crossQueue.mechanism: Передача {timelineValue} в метод {submit} командного буфера-потребителя. -concepts.synchronization.dependencies.table.crossQueue.situation: Отправка в другой очереди создаёт данные +concepts.synchronization.dependencies.table.cpuAccess.situation: "Доступ CPU или освобождение ресурса требует завершения работы GPU" +concepts.synchronization.dependencies.table.crossQueue.mechanism: "Передайте {timelineValue} производителя в вызов {submit} потребителя." +concepts.synchronization.dependencies.table.crossQueue.situation: "Одна очередь использует данные, полученные в другой" concepts.synchronization.dependencies.table.headings.mechanism: Механизм concepts.synchronization.dependencies.table.headings.situation: Ситуация -concepts.synchronization.dependencies.table.layoutChange.mechanism: Вызов {commandBufferTransition} с предыдущим и следующим layout. +concepts.synchronization.dependencies.table.layoutChange.mechanism: "{commandBufferTransition} с предыдущим и следующим состоянием текстуры." concepts.synchronization.dependencies.table.layoutChange.situation: Изменение способа использования подресурса текстуры concepts.synchronization.dependencies.table.pipelineStages.mechanism: Вызов {commandBufferBarrier} с указанием стадий производителя и потребителя. concepts.synchronization.dependencies.table.pipelineStages.situation: Зависимые стадии GPU в потоке команд -concepts.synchronization.dependencies.title: Анализ производителей и потребителей -concepts.synchronization.description: Команда, считывающая данные, записанные предыдущей командой, зависит от завершения этих записей и их видимости для неё. Записывающая сторона — это производитель (producer); считывающая — потребитель (consumer). Процессору (CPU) также требуется точка завершения перед чтением, перезаписью или освобождением разделяемых данных. Zenith.NET предоставляет барьеры, переходы текстур и временные шкалы для управления этими зависимостями. -concepts.synchronization.layouts.context: Значение {undefined} означает, что предыдущее содержимое сохранять не требуется. Оно подходит для нового изображения или вложения, которое будет полностью очищено. Это не способ избежать отслеживания layout для изображения, содержимое которого будет загружаться, сэмплироваться или накапливаться. -concepts.synchronization.layouts.description: "Флаги назначения описывают поддерживаемые роли текстуры. {textureLayout} описывает, как конкретный подресурс будет использоваться в операции. Подресурс — выбранный уровень mip и слой массива. Изменение layout подготавливает доступ, но не преобразует формат пикселей. Например, вычислительный пример записывает выходную текстуру в layout {storage}, а затем сэмплирует её в графическом проходе. Между этими операциями записывается:" -concepts.synchronization.layouts.details: Этот фрагмент предполагает, что текстура {outputTexture} была создана с назначением {sampledStorage}, а её выбранный подресурс находится в состоянии {storage}. Значение {default} выбирает уровень mip 0 и слой массива 0. Операция не переводит каждый mip или слой текстуры. -concepts.synchronization.layouts.guidance: Приложение предоставляет предыдущий layout. Метод {transition} не ведёт видимый для приложения трекер состояний и не вычисляет это значение из предыдущих команд. Отслеживайте layout везде, где ресурс передаётся между стадиями рендеринга. -concepts.synchronization.layouts.title: Отслеживание layout каждого подресурса текстуры -concepts.synchronization.readback.description: Свойство {isCompleted} лишь опрашивает, достигла ли временная шкала GPU определённого значения. Оно само по себе не возвращает командные буферы и не копирует промежуточные скачанные данные по целевому указателю приложения. -concepts.synchronization.readback.details: "{commandBufferDownload} сначала записывает копирование во внутреннее хранилище считывания. При сбросе завершённого командного буфера для повторного использования CPU копирует данные по предоставленному указателю. Сохраняйте целевую память выделенной, а управляемую память закреплённой до возврата из {wait} для этой отправки считывания. Читать данные или освобождать память можно только после этого. Ожидание более поздней отправки другой очереди само по себе не опрашивает очередь, управляющую считыванием." -concepts.synchronization.readback.guidance: "Поэтому недостаточно опрашивать {isCompleted} и сразу читать данные по адресу назначения асинхронного считывания. В разделе «{link}» рассматриваются прямое копирование и передача через промежуточное хранилище." +concepts.synchronization.dependencies.title: "Зависимости обращений" +concepts.synchronization.description: "Синхронизация задаёт порядок обращений к общим данным и обеспечивает доступ последующих операций к нужным результатам. В зависимости между записью и чтением записывающая операция производит данные, а читающая их потребляет. Барьеры и переходы состояния текстур координируют обращения GPU; временные шкалы связывают отправки и позволяют CPU дождаться завершения работы GPU." +concepts.synchronization.layouts.context: "Указывайте {undefined} как предыдущее состояние, когда существующее содержимое можно отбросить, например для нового изображения или вложения, которое будет заполнено целиком. Если содержимое нужно сохранить для загрузки, выборки или накопления, используйте состояние предыдущего обращения." +concepts.synchronization.layouts.description: "Флаги назначения текстуры объявляют допустимые способы её использования. {textureLayout} описывает доступ к конкретному подресурсу в определённой точке последовательности команд. Подресурс задаётся mip-уровнем и слоем массива. При смене способа доступа запишите переход. Например, вычислительный пример записывает выходную текстуру в состоянии {storage}, затем подготавливает её к выборке в графическом проходе:" +concepts.synchronization.layouts.details: "Здесь {outputTexture} создана с назначением {sampledStorage}, а выбранный подресурс находится в {storage}. {default} выбирает уровень mip 0 и слой 0. Остальные уровни и слои переход не затрагивает." +concepts.synchronization.layouts.guidance: "В {transition} передавайте состояние предыдущего использования подресурса. Приложение отслеживает это состояние при записи команд и передаче текстур между этапами рендеринга." +concepts.synchronization.layouts.title: "Состояния текстур" +concepts.synchronization.readback.description: "{isCompleted} сообщает о завершении работы GPU. У записанного считывания есть ещё один этап: копирование результата из внутренней промежуточной памяти в память назначения приложения." +concepts.synchronization.readback.details: "{commandBufferDownload} записывает копирование на GPU во внутреннюю память. После завершения отправки библиотека выполняет копию на CPU, возвращая командный буфер для повторного использования. Вызов {wait} для значения этой отправки дожидается GPU и обрабатывает завершённые буферы той же очереди, тем самым завершая оба этапа. До возврата память назначения должна оставаться выделенной, а управляемая память — закреплённой." +concepts.synchronization.readback.guidance: "Один лишь опрос {isCompleted} не выполняет заключительную копию на CPU. Ожидание другой очереди тоже не возвращает завершённые буферы очереди считывания. Когда загрузка и считывание используют прямой доступ к памяти, а когда промежуточное хранилище, описано в статье «{link}»." concepts.synchronization.readback.guidance.link: Управление ресурсами -concepts.synchronization.readback.title: Завершение работы GPU и скачанные данные CPU — это разные шаги -concepts.synchronization.reuse.description: Для простого рендерера немедленное ожидание после каждого кадра наиболее прозрачно. Для перекрытия работы выделите для незавершённых кадров раздельные изменяемые данные и сохраняйте значение завершения для последнего использования в каждом кадре. Перед обновлением буфера констант, заменой текстуры или освобождением конвейера завершите все ожидающие обращения к затронутому ресурсу. -concepts.synchronization.reuse.details: При изменении размера или выключении остановите новые операции перед ожиданием старых. Вызовы {swapChainResize}, освобождение ресурсов и освобождение контекста не служат общими операциями ожидания для задач приложения. В учебнике с треугольником размер можно безопасно менять между обратными вызовами, поскольку каждый предыдущий кадр уже завершил свою отправку. -concepts.synchronization.reuse.guidance: Текущий метод {swapChainPresent} также отправляет сигнал и ожидает завершения в графической очереди после операции вывода. Поэтому удаление явного ожидания отправки в примере с треугольником само по себе не создаёт перекрывающийся цикл вывода. Ожидание в очереди графики также ничего не говорит о независимой работе, всё ещё выполняющейся в другой очереди. -concepts.synchronization.reuse.title: Повторное использование данных только после последнего обращения -concepts.synchronization.timelines.context: "Перед тем как CPU прочитает, перезапишет или освободит эти ресурсы, дождитесь их окончательного использования:" -concepts.synchronization.timelines.description: Временная шкала отслеживает завершение операций в очереди с помощью монотонно возрастающих значений. Метод {submit} возвращает {timelineValue}, содержащий эту шкалу и значение, связанное с отправкой. Значения завершения из разных временных шкал нельзя сравнивать только по их числовому полю {value}. -concepts.synchronization.timelines.details: "Предположим, что {producer} и {consumer} — это уже записанные командные буферы из двух очередей одного контекста. Производитель записывает данные, которые использует потребитель. Отправьте их следующим образом:" -concepts.synchronization.timelines.guidance: Передача полученного значения заставляет очередь-потребитель ожидать его на GPU. Процессор в данном случае не вызывает {producedWait}. Поддерживайте разделяемые ресурсы активными до завершения {consumed} и записывайте любые изменения layout текстуры, требуемые потребителем. -concepts.synchronization.timelines.notes: Метод {wait} ожидает достижения этого значения временной шкалы, а затем проверяет завершённые отправки в ответственной очереди. Завершённые командные буферы сбрасываются для повторного использования, а их промежуточные скачанные данные копируются в предоставленные буферы CPU. Метод {queueTimelineSignal} также может поставить в очередь точку завершения после задач, уже отправленных в эту очередь. Вызов {signal} не означает, что GPU уже достиг этой точки. -concepts.synchronization.timelines.title: Использование временной шкалы для завершения и передачи между очередями +concepts.synchronization.readback.title: "Готовность данных к чтению" +concepts.synchronization.reuse.description: "Треугольник дожидается завершения каждого кадра перед повторным использованием данных. Чтобы выполнение кадров перекрывалось, выделите каждому ещё выполняющемуся кадру собственную изменяемую память и отслеживайте, когда она снова станет доступной. Перед изменением данных дождитесь обращений GPU к тем же байтам, а перед освобождением ресурса — всех его незавершённых использований." +concepts.synchronization.reuse.details: "Изменение размера и завершение приложения подчиняются тому же правилу: прекратить новые обращения, дождаться текущих, затем заменить или освободить ресурсы. Соблюдайте этот порядок перед {swapChainResize} и перед освобождением ресурсов или контекста. Треугольник уже ждёт каждый кадр, поэтому может менять размер между вызовами обработчиков." +concepts.synchronization.reuse.guidance: "После вывода изображения {swapChainPresent} устанавливает точку завершения в графической очереди и ожидает её. Поэтому треугольник всё равно ждёт при выводе, даже если удалить явное ожидание после отправки команд. Работа, независимо отправленная в другие очереди, требует отдельного отслеживания завершения." +concepts.synchronization.reuse.title: "Повторное использование ресурсов" +concepts.synchronization.timelines.context: "Если после потребителя CPU должен прочитать результат, перезаписать общие данные или освободить ресурсы, дождитесь этой отправки:" +concepts.synchronization.timelines.description: "Временная шкала отмечает завершение в очереди возрастающими значениями. {submit} возвращает {timelineValue} со шкалой и значением отправки. Числовые поля {value} разных шкал нельзя сравнивать напрямую." +concepts.synchronization.timelines.details: "Пусть {producer} и {consumer} — записанные буферы двух очередей одного контекста, причём потребитель читает результат производителя. Отправьте их с такой зависимостью:" +concepts.synchronization.timelines.guidance: "Очередь-потребитель ждёт указанного значения завершения перед выполнением своих команд. CPU может продолжать работу без вызова {producedWait}. Сохраняйте общие ресурсы до завершения {consumed} и записывайте переходы состояния текстур, необходимые для доступа потребителя." +concepts.synchronization.timelines.notes: "Значение, возвращённое {queueTimelineSignal}, также можно ожидать через {wait} или передать как зависимость другой очереди. {signal} помещает точку завершения после ранее отправленной работы; GPU достигает её, когда эта работа закончена." +concepts.synchronization.timelines.title: "Временные шкалы и зависимости очередей" concepts.synchronization.title: Синхронизация home.actions.reference: Справочник API home.actions.tutorial: Начать с треугольника -home.entries.description: Первый кадр. Наглядный пример. Подробный обзор API. -home.entries.label: Обзор документации +home.entries.description: "Учебные материалы, примеры и справочник API" +home.entries.label: "Разделы документации" home.entries.reference.action: Изучить API home.entries.reference.category: Справочник -home.entries.reference.description: Найдите типы, сигнатуры и члены, на которых строится ваше приложение. +home.entries.reference.description: "Справка по типам, членам и объявлениям API" home.entries.reference.title: Справочник API home.entries.samples.action: Обзор примеров home.entries.samples.category: Примеры -home.entries.samples.description: Изучите специализированные методы рендеринга и вычислений на примерах исходного кода. +home.entries.samples.description: "Рабочие примеры графических и вычислительных методов" home.entries.samples.title: Примеры -home.entries.title: Начните разработку. -home.entries.tutorial.action: Начать учебник -home.entries.tutorial.category: Учебник -home.entries.tutorial.description: "Создайте полноценное приложение рендеринга: от настройки проекта до первого кадра." +home.entries.title: "Документация" +home.entries.tutorial.action: "Начать урок" +home.entries.tutorial.category: "Урок" +home.entries.tutorial.description: "От пустого проекта до первого треугольника на экране" home.entries.tutorial.title: Первый треугольник -home.introduction.accent: "На C#." -home.introduction.description: Создавайте ресурсы, записывайте команды и отправляйте задачи графики и вычислений через единый .NET API. -home.introduction.title: Создайте свой рендерер. -home.meta.description: "Единый C# API для графики и вычислений на DirectX, Metal и Vulkan." -home.scene.description: Демонстрация вращающейся геометрии. Перетаскивайте мышью или используйте клавиши со стрелками для изменения ракурса. +home.introduction.accent: "на разных платформах" +home.introduction.description: "Zenith.NET объединяет работу с DirectX, Metal и Vulkan в одном API для графики и вычислений" +home.introduction.title: "Графика для .NET{lineBreak}{accent}" +home.meta.description: "Кроссплатформенная графика и вычисления в .NET с единым API для DirectX, Metal и Vulkan" +home.scene.description: "Интерактивная вращающаяся геометрия. Перетаскивайте изображение или используйте клавиши со стрелками для изменения ракурса." home.scene.label: Отображение геометрии home.scene.surface: Поверхность home.scene.wireframe: Каркас -home.title: Современный RHI для .NET -learning.concepts.description: Поймите, как взаимодействуют команды, ресурсы, данные шейдеров и синхронизация, прежде чем объединять проходы рендеринга. -learning.concepts.execution.description: Записывайте задачи для GPU, отправляйте их и поддерживайте ресурсы активными. -learning.concepts.platforms.description: Подключите нативное окно или элемент управления рендерингом интерфейса. -learning.concepts.resources.description: Выбирайте назначение ресурсов, размещение в памяти и представления. -learning.concepts.shaders.description: "Согласуйте структуру данных C# и дескрипторы ресурсов с кодом на Slang." -learning.concepts.synchronization.description: Упорядочивайте зависимые обращения и отслеживайте завершение операций. +home.title: "Графический API для .NET" +learning.concepts.description: "Выбор назначений ресурсов, описание данных шейдеров и координация работы GPU" +learning.concepts.execution.description: "Запись команд, отправка и время жизни ресурсов" +learning.concepts.platforms.description: "Нативный вывод и графические элементы интерфейса" +learning.concepts.resources.description: "Назначения ресурсов, размещение памяти и представления" +learning.concepts.shaders.description: "Соглашения о размещении и привязке данных C# и Slang" +learning.concepts.synchronization.description: "Зависимости, видимость и завершение" learning.concepts.title: Основные концепции -learning.description: Начните с пошагового учебника по отрисовке треугольника. Затем используйте наглядные примеры и руководства по концепциям, чтобы освоить ресурсы, структуры данных и зависимости более сложного рендерера. +learning.description: "Начните с урока о треугольнике и создайте первое приложение. Затем изучите управление ресурсами, данные шейдеров и синхронизацию в статьях об основных понятиях или выберите пример нужного графического метода." learning.entries.samples.action: Обзор примеров -learning.entries.samples.description: "Примеры на C# и Slang для геометрии, вычислений, запросов лучей и mesh shading." -learning.entries.tutorial.action: Открыть учебник -learning.entries.tutorial.description: Создайте консольное приложение, откройте окно и нарисуйте треугольник. -learning.meta.description: Начало работы с Zenith.NET и знакомство с моделью программирования. +learning.entries.samples.description: "Примеры на C# и Slang: геометрия, вычисления, запросы лучей и меш-шейдинг" +learning.entries.tutorial.action: "Открыть урок" +learning.entries.tutorial.description: "Консольное приложение, которое открывает окно и рисует треугольник" +learning.meta.description: "Учебные материалы и основы модели программирования Zenith.NET" learning.title: Обучение -reference.description: Справочник по типам ресурсов, сигнатурам команд и интеграции с платформами. -reference.entries.commands.description: Записывайте команды графики, вычислений и передачи данных. +reference.description: "Справочник ресурсов, команд и платформенных интеграций" +reference.entries.commands.description: "Графические, вычислительные и передающие команды" reference.entries.commands.label: Запись команд -reference.entries.context.description: Создавайте ресурсы GPU для выбранного бэкенда. +reference.entries.context.description: "Создание ресурсов GPU для выбранного бэкенда" reference.entries.context.label: Начало работы -reference.meta.description: Изучите типы и члены библиотеки Zenith.NET. -reference.navigation.core: Обзор основного API. +reference.meta.description: "Пространства имён, типы и члены Zenith.NET" +reference.navigation.core: "Справочник основного API" reference.title: Справочник API -samples.computeShader.description: "Преобразует изображение в оттенки серого с помощью вычислительного диспатча и отображает полученную текстуру. Демонстрирует дескрипторы ресурсов для сэмплируемой входной текстуры и записываемой выходной текстуры, округление количества групп потоков в большую сторону и проверку границ в шейдере. Сохраняйте включённый ресурс {assetsTexturesShokoPng}: рендерер обрабатывает его один раз и выводит результат в последующих кадрах." +samples.computeShader.description: "Пример загружает {assetsTexturesShokoPng}, преобразует изображение в оттенки серого на GPU и показывает выходную текстуру. Преобразование выполняется один раз; следующие кадры показывают тот же результат. Рендерер демонстрирует привязку текстур для выборки и записи, округление числа групп потоков вверх для обработки всего изображения и проверку его границ в шейдере." samples.computeShader.details: "{computeShaderRendererCs} · {computeShaderSlang}" samples.computeShader.title: Вычислительный шейдер -samples.cube.description: Добавляет индексную отрисовку, матрицы модели, вида и проекции в буфере констант, а также тест глубины. Текстура глубины пересоздаётся при изменении размера. Используйте этот пример при переходе от геометрии в пространстве отсечения к трансформированному объекту; рендерер использует вложение глубины и трафарета формата {d32FloatS8UInt}. +samples.cube.description: "Куб добавляет индексированное рисование, матрицы модели, вида и проекции в буфере констант и проверку глубины. Текстура глубины и трафарета {d32FloatS8UInt} пересоздаётся при изменении размера." samples.cube.details: "{spinningCubeRendererCs} · {spinningCubeSlang}" samples.cube.title: Вращающийся куб -samples.description: "Выберите пример для интересующей вас возможности. Каждый пример содержит ссылки на рендерер C# и его шейдер Slang. Если нужно пошаговое объяснение приложения с пустого проекта, начните с учебника «{link}»." +samples.description: "Каждый пример объединяет рендерер C# и шейдер Slang для определённого метода. Полную настройку приложения и порядок рендеринга разбирает урок «{link}»." samples.description.link: Первый треугольник -samples.execution.description: "{link} содержит шесть независимых рендереров в одном настольном приложении. Используйте .NET 10 SDK и поддерживаемый бэкенд для настольных систем, как описано ниже. Соберите и запустите приложение, затем выберите пример в меню консоли:" +samples.execution.description: "Запустите проект {link} и выберите пример в меню консоли." samples.execution.description.link: ZenithTutorials -samples.execution.details: "Хост выбирает DirectX 12 в Windows, Metal в macOS и Vulkan в Linux. Используйте устройство, драйвер и среду компиляции шейдеров, поддерживаемые выбранным бэкендом. Оконному пути Linux требуется X11 или XWayland. {link} объявляет зависимости пакетов и копирует шейдеры и текстуры, необходимые во время выполнения." -samples.execution.details.link: "Файл проекта" -samples.execution.guidance: Примеры используют общий код создания окна и вывода на экран. Вы можете изучать любой пример независимо в зависимости от интересующей вас темы. -samples.execution.title: Запуск примеров из учебника -samples.host.description: "{appCs} создаёт контекст, окно и цепочку обмена. Он получает командный буфер, вызывает выбранный рендерер, отправляет кадр и выводит его. Интерфейс {iRendererCs} определяет методы обновления, рендеринга, изменения размера и освобождения ресурсов." -samples.host.details: Вычисления и трассировка лучей создают закадровые текстуры. {texturePresenterCs} и {presentTextureSlang} отрисовывают эти текстуры в выходную текстуру текущего кадра окна. Хост сохраняет владение отправкой команд и выводом цепочки обмена. -samples.host.title: Общий хост и презентация -samples.indirectDrawing.description: "Отрисовывает несколько копий куба с помощью буфера аргументов косвенной индексной отрисовки и данных экземпляров в структурированном буфере. CPU предоставляет аргументы и обновляет преобразования. Пример помогает понять разметку косвенных аргументов и доступ шейдера к данным экземпляров перед добавлением аргументов, создаваемых GPU." +samples.execution.title: "Запуск примеров" +samples.host.description: "{appCs} инициализирует контекст, окно и цепочку обмена. На каждом кадре он получает буфер команд, вызывает выбранный рендерер, отправляет команды и выводит изображение. {iRendererCs} задаёт операции обновления, рисования, изменения размера и освобождения ресурсов." +samples.host.details: "Вычислительный рендерер и рендерер трассировки лучей создают внеэкранные текстуры. {texturePresenterCs} и {presentTextureSlang} рисуют их в текущую выходную текстуру, после чего общая оболочка отправляет команды и выводит кадр." +samples.host.title: "Оболочка приложения и вывод" +samples.indirectDrawing.description: "Косвенное рисование выводит несколько экземпляров куба по буферу аргументов индексированного рисования и структурированному буферу данных экземпляров. CPU задаёт аргументы и обновляет преобразования." samples.indirectDrawing.details: "{indirectDrawingRendererCs} · {indirectDrawingSlang}" -samples.indirectDrawing.title: Косвенная отрисовка -samples.meshShading.description: Использует task-шейдер для отсечения экземпляров сфер и передачи их индексов в mesh-шейдер, который генерирует геометрию. Рендерер проверяет {contextCapabilitiesMeshShadingSupported} перед созданием конвейера. Используйте для изучения передачи дескрипторов ресурсов и полезной нагрузки между стадиями задач и мешей. +samples.indirectDrawing.title: "Косвенное рисование" +samples.meshShading.description: "Шейдер задач отбрасывает невидимые экземпляры сфер и передаёт оставшиеся индексы меш-шейдеру, который создаёт геометрию. До создания конвейера рендерер проверяет {contextCapabilitiesMeshShadingSupported}." samples.meshShading.details: "{meshShadingRendererCs} · {meshShadingSlang}" -samples.meshShading.title: Mesh Shading -samples.rayTracing.description: Строит структуры ускорения нижнего и верхнего уровней для плоскости и процедурных сфер, а затем выполняет встроенные inline-запросы лучей в вычислительном шейдере. Рендерер проверяет {contextCapabilitiesRayTracingSupported} перед формированием рабочей нагрузки. Используйте для изучения структур ускорения и обхода лучей на стороне шейдера. +samples.meshShading.title: "Меш-шейдинг" +samples.rayTracing.description: "Пример строит структуры ускорения нижнего и верхнего уровней для пола и процедурных сфер, затем выполняет встроенные запросы лучей в вычислительном шейдере. До инициализации проверяется {contextCapabilitiesRayTracingSupported}." samples.rayTracing.details: "{rayTracingRendererCs} · {rayTracingSlang}" samples.rayTracing.title: Трассировка лучей samples.title: Примеры -samples.triangle.description: Создаёт буфер вершин и соответствующую разметку входных данных, затем отрисовывает три вершины через графический конвейер. Используйте для понимания связи между созданием ресурсов и командами прохода рендеринга. +samples.triangle.description: "Треугольник связывает буфер вершин с соответствующим описанием входа и рисует три вершины через графический конвейер." samples.triangle.details: "{helloTriangleRendererCs} · {helloTriangleSlang} · {link}" -samples.triangle.details.link: Полный учебник -samples.triangle.title: Привет, треугольник -samples.workloads.description: "{link} основного репозитория содержит приложения, сочетающие несколько возможностей. Их проекты ссылаются на исходный код библиотеки. Из локальной копии Zenith.NET запустите выбранный проект, например:" -samples.workloads.description.link: "Каталог Experiments" -samples.workloads.details: Оконные эксперименты используют те же варианты хоста для Windows, macOS и Linux/X11. Сведения об отрисовке внутри Avalonia, WinForms, WPF, WinUI/Uno или MAUI, жизненном цикле кадров элемента управления и ссылки на реализации см. в разделе {link}. +samples.triangle.details.link: "Полный урок" +samples.triangle.title: "Треугольник" +samples.workloads.description: "Каталог {link} основного репозитория содержит более сложные приложения, использующие исходный код библиотеки." +samples.workloads.description.link: "Experiments" +samples.workloads.details: "Оконные эксперименты используют те же пути вывода для Windows, macOS и Linux/X11. Интеграции Avalonia, WinForms, WPF, WinUI/Uno и MAUI, их цикл кадров и исходный код описаны в статье «{link}»." samples.workloads.details.link: Интеграция с платформами samples.workloads.table.cornellBox.example: "{link}" samples.workloads.table.cornellBox.example.link: CornellBox -samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: Трассировка путей, шумоподавление, тональная компрессия, апскейлинг и элементы управления ImGui. Требуется поддержка трассировки лучей и среда компиляции шейдеров для бэкенда настольной платформы. +samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: "Трассировка путей, шумоподавление, тональная компрессия, увеличение разрешения и элементы управления ImGui. Требуется поддержка трассировки лучей." samples.workloads.table.fluidTank.example: "{link}" samples.workloads.table.fluidTank.example.link: FluidTank -samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: Вычислительное моделирование жидкости, зависимости между стадиями симуляции и многопроходный рендеринг поверхности. Требуется бэкенд настольной платформы и среда компиляции шейдеров. +samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: "Вычислительное моделирование жидкости, зависимости между стадиями симуляции и многопроходный рендеринг поверхности." samples.workloads.table.headings.example: Пример -samples.workloads.table.headings.whatItDemonstratesAndRequires: Что демонстрирует и требования +samples.workloads.table.headings.whatItDemonstratesAndRequires: "Методы и требования" samples.workloads.table.inkCanvas.example: "{link}" samples.workloads.table.inkCanvas.example.link: InkCanvas samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: Отрисовка с помощью Skia и обработка ввода в нативном окне. Требуется бэкенд и нативная библиотека Skia для целевой платформы. samples.workloads.table.platformDetection.example: "{link}" samples.workloads.table.platformDetection.example.link: PlatformDetection -samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: "Пытается создать контекст для каждого бэкенда и сообщает о возможностях устройства. Ошибка создания контекста отображается как отсутствие поддержки; такой результат может также указывать на отсутствующий драйвер или зависимость среды выполнения." -samples.workloads.title: Изучение более сложных нагрузок -tutorial.context.description: Теперь окно открывается, но мы ещё не создали объекты GPU, которые будут выполнять в него рендеринг. {graphicsContext} обеспечивает доступ к выбранному графическому бэкенду и его очередям команд. -tutorial.context.details: "Вставьте этот блок {emphasis}:" +samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: "Пытается создать контекст для каждого бэкенда и сообщает возможности устройства. Неудачная попытка отмечается как отсутствие поддержки; причиной может быть устройство, драйвер или недостающая зависимость среды выполнения." +samples.workloads.title: "Более сложные приложения" +tutorial.context.description: "{graphicsContext} связывает приложение с GPU через выбранный бэкенд и предоставляет методы создания ресурсов для рендеринга." +tutorial.context.details: "Вставьте инициализацию контекста {emphasis}:" tutorial.context.details.emphasis: после директив using, перед {iWindowWindow} -tutorial.context.guidance: Ветвления выбирают DirectX 12 в Windows, Metal в macOS и Vulkan в Linux. Последующий код рендеринга использует общий API Zenith.NET. Во время разработки мы запрашиваем валидацию и выводим сообщения, передаваемые через {validationMessage}. Диагностика зависит от бэкенда и компонентов валидации, доступных в системе. -tutorial.context.title: Создание графического контекста -tutorial.description: Создайте консольное приложение .NET, которое открывает окно и отрисовывает треугольник с плавным градиентным переходом цветов. Вы узнаете, как взаимодействуют данные вершин, шейдеры и состояние конвейера, а затем запишете и отправите команды, формирующие изображение. -tutorial.details: Выполняйте разделы по порядку. Сначала вы откроете пустое окно, затем отобразите цвет фона и, наконец, нарисуете треугольник. Каждый контрольный этап подтверждает правильность работы одной части приложения перед добавлением следующей. Инициализация выполняется один раз, а обратный вызов рендеринга записывает новый кадр при каждом вызове. +tutorial.context.guidance: "Каждая ветвь выбирает бэкенд текущей платформы и запрашивает валидацию. Сообщения {validationMessage} выводятся в консоль." +tutorial.context.imports: "Добавьте следующие директивы using в начало {programCs}:" +tutorial.context.title: "Графический контекст" +tutorial.description: "В этом уроке из пустого консольного проекта .NET получится приложение, которое открывает окно и рисует цветной треугольник." +tutorial.details: "В уроке три проверочных этапа: пустое окно, однотонный фон и цветной треугольник. Запускайте приложение после каждого этапа, прежде чем добавлять следующую часть." tutorial.draw.context: "Аргументы метода {draw}:" -tutorial.draw.description: "В обратном вызове {windowRender} замените комментарий {addTheTriangleDrawCommandsHereLater} следующими тремя командами между {beginRenderPass} и {endRenderPass}:" -tutorial.draw.details: "Команда {setPipeline} выбирает созданные шейдеры и состояние конвейера. Установите её перед привязкой данных вершин: бэкенд использует разметку входных данных конвейера для интерпретации привязки." -tutorial.draw.guidance: Команда {setVertexBufferVertexBuffer} привязывает буфер, начиная с байтового смещения 0, к входному слоту 0. Этот слот соответствует единственной записи в {inputLayouts}. Она не копирует и не загружает данные повторно. -tutorial.draw.notes: На этом этапе команды всё ещё только записаны. Вызовы {submitWait} и {present}, уже находящиеся в конце обратного вызова рендеринга, выполняют работу и выводят результат. Очистка остаётся необходимой, так как треугольник покрывает лишь часть изображения; фон также должен получать определённый цвет в каждом кадре. +tutorial.draw.description: "В обработчике {windowRender} замените {addTheTriangleDrawCommandsHereLater} следующими командами между {beginRenderPass} и {endRenderPass}:" +tutorial.draw.details: "{setPipeline} выбирает шейдеры и состояние рендеринга. Этот вызов должен предшествовать привязке вершинного буфера, поскольку бэкенд интерпретирует его данные по описанию вершинного ввода выбранного конвейера." +tutorial.draw.guidance: "{setVertexBufferVertexBuffer} привязывает загруженные вершинные данные со смещения 0 байт к входному слоту 0, соответствующему единственной записи {inputLayouts}." +tutorial.draw.notes: "Эти вызовы записывают команды рисования. Уже добавленный вызов {submitWait} отправляет их и дожидается завершения на GPU; затем {present} запрашивает вывод готового изображения. Сохраните заполнение фоном в начале прохода, чтобы область за пределами треугольника тоже имела определённый цвет." tutorial.draw.table.firstInstance.meaning: Начать нумерацию экземпляров с нуля. tutorial.draw.table.firstVertex.meaning: Начать с первой вершины в буфере. tutorial.draw.table.headings.argument: Аргумент @@ -368,45 +362,47 @@ tutorial.draw.table.headings.description: Значение tutorial.draw.table.headings.meaning: Назначение tutorial.draw.table.instanceCount.meaning: Нарисовать одну копию треугольника. tutorial.draw.table.vertexCount.meaning: Считать три вершины. -tutorial.draw.title: Отрисовка треугольника внутри прохода -tutorial.execution.description: "Соберите и запустите приложение из каталога {firstTriangle}:" -tutorial.execution.details: В окне должен появиться треугольник с красным верхним углом, зелёным правым нижним углом и синим левым нижним углом на тёмном фоне. Внутри треугольника должен быть плавный градиент между этими цветами. -tutorial.execution.guidance: "Измените размер окна. Обратный вызов изменения размера обновляет размеры фреймбуфера и изменяет размер цепочки обмена. Проход рендеринга задаёт область просмотра для этого изображения. Позиции вершин остаются нормализованными, поэтому треугольник занимает ту же долю ширины и высоты окна; смена соотношения сторон может растянуть его форму. Для сохранения пропорций объекта нужна стратегия проекции или области просмотра, что выходит за рамки первой отрисовки." -tutorial.execution.title: Запуск, изменение размера и закрытие -tutorial.frame.commands.context: После {endRenderPass} второй переход подготавливает изображение к презентации. Метод {submit} завершает запись и отправляет командный буфер; {wait} ожидает завершения этой отправки на GPU. Затем {present} запрашивает отображение отрисованного изображения. -tutorial.frame.commands.description: Проход рендеринга группирует операции отрисовки, использующие одни и те же вложения. Здесь цветовым вложением выступает выходная текстура цепочки обмена — изображение, принимающее нашу отрисовку. Метод {colorAttachmentClear} создаёт описание, предписывающее проходу выполнить очистку заданным цветом RGBA и сохранить результат по завершении прохода. Метод {beginRenderPass} записывает эти инструкции; GPU выполняет очистку после отправки команд. -tutorial.frame.commands.details: В квадратных скобках указано наше единственное цветовое вложение. Аргумент {null} означает отсутствие вложения глубины/трафарета, которое хранило бы значения глубины и маски трафарета для соответствующих тестов. -tutorial.frame.commands.guidance: Метод {beginRenderPass} задаёт область просмотра (viewport) и область отсечения (scissor), покрывающие вложение. Область просмотра преобразует координаты рендеринга в пиксели, а область отсечения ограничивает пиксели, доступные для записи. Эти значения по умолчанию покрывают всю выходную текстуру, что и требуется для нашего треугольника. -tutorial.frame.commands.title: Очистка, отправка и презентация -tutorial.frame.description: Сначала заполните изображение одним цветом фона. Эта операция называется очисткой (clear). Если этот цвет появится в окне, значит поверхность, отправка команд и путь вывода работают корректно. Этот контрольный этап позволяет проверить цикл кадров перед добавлением геометрии и шейдеров. -tutorial.frame.details: "Обратный вызов рендеринга — это код, который Silk.NET вызывает, когда наступает время отрисовки кадра. Этому вызову не требуется аргумент прошедшего времени события, поэтому он обозначен как {value}. Зарегистрируйте его {emphasis}:" +tutorial.draw.title: "Команды рисования" +tutorial.execution.description: "Соберите и запустите проект {firstTriangle}." +tutorial.execution.details: "На тёмном фоне должен появиться треугольник: красный сверху, зелёный справа внизу и синий слева внизу. Интерполяция цветов вершин создаёт плавные переходы внутри треугольника." +tutorial.execution.guidance: "При изменении размера окна меняются размеры изображения в пикселях, но координаты вершин остаются прежними. Область вывода преобразует эти координаты с учётом новой ширины и высоты. Поэтому изменение соотношения сторон окна растягивает треугольник." +tutorial.execution.title: "Запуск приложения" +tutorial.frame.commands.context: "После {endRenderPass} второй переход подготавливает выходную текстуру к выводу. {submit} завершает запись и отправляет командный буфер; {wait} блокирует поток до завершения этой работы. Затем {present} запрашивает отображение готового изображения." +tutorial.frame.commands.description: "Проход рендеринга объединяет команды рисования, которые записывают результаты в одни и те же вложения. В этом проходе цвет записывается в выходную текстуру цепочки обмена. {colorAttachmentClear} задаёт её начальное заполнение цветом RGBA и сохранение содержимого после прохода. {beginRenderPass} записывает начало прохода с этими настройками." +tutorial.frame.commands.details: "Коллекция содержит одно цветовое вложение. {null} означает, что у прохода нет вложения глубины и трафарета." +tutorial.frame.commands.guidance: "{beginRenderPass} задаёт область вывода и прямоугольник отсечения по размеру всего вложения. Область вывода преобразует координаты рендеринга в позиции пикселей, а прямоугольник отсечения ограничивает область, в которую разрешена запись." +tutorial.frame.commands.title: "Очистка, отправка и вывод" +tutorial.frame.description: "Для начала заполните окно одним цветом фона. Эта операция называется очисткой. Когда фон появился, поверхность, отправка команд и вывод уже работают вместе — можно добавлять вершины и шейдеры треугольника." +tutorial.frame.details: "Silk.NET вызывает обработчик, когда нужно отрисовать кадр. Пример не использует аргумент прошедшего времени, поэтому параметр назван {value}. Зарегистрируйте обработчик {emphasis}:" tutorial.frame.details.emphasis: перед {windowRun} -tutorial.frame.target.description: Метод {graphicsQueueCommandBuffer} возвращает командный буфер с уже начатой записью. Запись описывает работу для GPU, но не выполняет её немедленно. -tutorial.frame.target.details: Первый переход {transition} подготавливает выходную текстуру для доступа в качестве цветового вложения. Значение {default} выбирает уровень mip 0 и слой массива 0. Мы используем {undefined} в качестве предыдущего layout, поскольку мы очистим всё изображение и отбросим его прежнее содержимое. Проход, которому необходимо сохранить существующее содержимое, должен использовать своё реальное предыдущее состояние layout. -tutorial.frame.target.guidance: В каждом кадре используйте актуальную выходную текстуру цепочки обмена. Презентация может изменить доступное изображение, поэтому текстура, сохранённая из предыдущего кадра, не является постоянной целью рендеринга окна. -tutorial.frame.target.title: Подготовка выходной текстуры -tutorial.frame.title: Отображение цвета фона -tutorial.geometry.data.description: Добавьте этот массив {emphasis}. Последующие шаги создания ресурсов также размещаются перед этим обратным вызовом в указанном порядке. +tutorial.frame.target.description: "{graphicsQueueCommandBuffer} возвращает буфер, готовый к записи. Запись определяет работу GPU; выполнение начинается только после отправки." +tutorial.frame.target.details: "Состояние доступа к текстуре определяет, как операция будет её использовать. Первый вызов {transition} подготавливает выходную текстуру к записи цвета. Значение {default} выбирает mip-уровень 0 и слой массива 0 — базовое изображение этой текстуры. Поскольку проход заполняет всё изображение цветом фона, {undefined} разрешает отбросить прежнее содержимое." +tutorial.frame.target.guidance: "Для каждого кадра используйте текущую выходную текстуру: при выводе изображения цепочка обмена может перейти к следующей." +tutorial.frame.target.title: "Подготовка выходной текстуры" +tutorial.frame.title: "Первый кадр" +tutorial.geometry.data.description: "Добавьте массив вершин {emphasis}. Последующую инициализацию ресурсов также размещайте перед этим обработчиком в указанном порядке." tutorial.geometry.data.description.emphasis: перед {windowRender} -tutorial.geometry.data.details: "Каждый элемент массива создаёт структуру {vertex}. Два внутренних выражения {new} задают координаты {vector3} и цвет {vector4}. Вершины описывают верхний, правый нижний и левый нижний углы. Вершинный шейдер предоставит четвёртую координату положения, {w}. При w = 1 координаты x и y напрямую соответствуют нормализованным координатам устройства: -1 и +1 соответствуют краям изображения, а 0 — центру. Эти координаты не зависят от размеров окна в пикселях." -tutorial.geometry.data.guidance: "Каждый цвет содержит компоненты: красный, зелёный, синий и альфа. Альфа-канал равен 1 во всех трёх вершинах. Все три положения имеют z = 0, располагаясь в одной плоскости. Для этих координат не требуются камера или матрица преобразования, поскольку они уже заданы в системе координат вывода. Для этого плоского треугольника мы также отключим смешивание цветов и тест глубины, отказавшись от буфера глубины." -tutorial.geometry.data.title: Выбор координат углов -tutorial.geometry.description: Вершина — это точка вместе с данными, необходимыми для её отрисовки. У нашего треугольника три вершины, по одной на каждый угол. Каждая содержит положение и цвет. GPU интерполирует цвета, вычисляя промежуточные значения по всей площади треугольника. -tutorial.geometry.format.description: "Добавьте это объявление {emphasis}:" -tutorial.geometry.format.description.emphasis: в конце {programCs}, после инструкций очистки -tutorial.geometry.format.details: "Модификатор {file} ограничивает тип файлом {programCs}, а конструктор инициализирует поля положения и цвета. {layoutKindSequential} сохраняет порядок объявления полей. {position} содержит три 32-битных числа с плавающей запятой, а {color} — четыре. Положение начинается с байта 0, цвет — с байта 12, и вся вершина занимает 28 байт. Эту же разметку мы зададим графическому конвейеру." -tutorial.geometry.format.title: Определение вершины -tutorial.geometry.title: Передача трёх вершин в GPU -tutorial.geometry.upload.context: Ключевое слово {fixed} предотвращает перемещение массива сборщиком мусора во время использования его адреса. Для этого буфера с возможностью записи CPU метод {upload} отображает, копирует и отменяет отображение памяти до возврата управления, поэтому массив не нужно удерживать закреплённым в дальнейшем. Буфер должен оставаться активным на протяжении всего рендеринга, а загрузку достаточно выполнить один раз, поскольку вершины не меняются. -tutorial.geometry.upload.description: "Управляемый массив — это данные в памяти CPU. Объект {buffer} предоставляет GPU память, из которой можно читать вершины. После массива добавьте:" -tutorial.geometry.upload.details: "Общий размер — {sizeofVertexVerticesLength}: 28 байт на вершину, три вершины, всего 84 байта. {bufferUsagesVertex} разрешает доступ для вершинного ввода. Режим {cpuWriteOnly} позволяет CPU напрямую инициализировать этот небольшой буфер. Шаг в описании буфера задаёт размер элемента; разметка входных данных ниже объяснит механизму выборки вершин, как читать отдельные атрибуты." -tutorial.geometry.upload.guidance: Создание буфера не заполняет его данными. Метод {upload} копирует массив в выделенную память, начиная с байтового смещения 0 в целевом буфере. Его описание источника предоставляет указатель и количество копируемых байт. -tutorial.geometry.upload.notes: Добавьте вызов {vertexBufferDispose} непосредственно перед {swapChainDispose} в блоке очистки в конце {programCs}. Для больших объёмов статической геометрии в руководстве {link} объясняется, когда следует выбирать память только для GPU и передачу данных через промежуточные буферы. +tutorial.geometry.data.details: "Каждая запись создаёт {vertex}; два внутренних выражения {new} задают позицию {vector3} и цвет {vector4}. Позиции соответствуют верхней, нижней правой и нижней левой вершинам. Вершинный шейдер добавляет четвёртую координату {w}. При w = 1 значения x и y также являются нормализованными координатами устройства: -1 и +1 обозначают края изображения, а 0 — центр. Эти координаты не зависят от числа пикселей." +tutorial.geometry.data.guidance: "Цвет задаётся красной, зелёной, синей и альфа-компонентами; альфа равна 1. Все три вершины находятся в одной плоскости при z = 0." +tutorial.geometry.data.title: "Позиции и цвета вершин" +tutorial.geometry.description: "У каждой из трёх вершин есть позиция и цвет. По позициям GPU определяет форму треугольника, а его внутренние цвета получает интерполяцией цветов вершин." +tutorial.geometry.format.description: "Добавьте объявление вершины {emphasis}:" +tutorial.geometry.format.description.emphasis: "в конце {programCs}, после кода освобождения ресурсов" +tutorial.geometry.format.details: "{file} ограничивает использование типа файлом {programCs}, а {layoutKindSequential} сохраняет порядок объявления полей. Поле {position} содержит три 32-битных числа с плавающей точкой и начинается со смещения 0 байт; поле {color} содержит четыре таких числа и начинается со смещения 12 байт. Одна вершина занимает 28 байт. Далее описание входных данных укажет GPU, как читать эти поля." +tutorial.geometry.format.imports: "Добавьте в начало {programCs} следующие директивы using для векторных типов и атрибута размещения полей структуры:" +tutorial.geometry.format.title: "Представление вершины" +tutorial.geometry.title: "Вершинные данные" +tutorial.geometry.upload.context: "{fixed} не позволяет сборщику мусора перемещать массив, пока используется его адрес. Для этого буфера с доступом CPU на запись метод {upload} отображает память, копирует данные и отменяет отображение до возврата. Поэтому массив достаточно закрепить на время вызова. Загрузите вершины один раз при инициализации и сохраняйте буфер до завершения рендеринга." +tutorial.geometry.upload.description: "Поместите вершины в {buffer}, чтобы GPU мог читать их при рисовании. Добавьте выделение памяти и загрузку данных сразу после массива:" +tutorial.geometry.upload.details: "Размер выделения — {sizeofVertexVerticesLength}: три вершины по 28 байт, всего 84 байта. {bufferUsagesVertex} объявляет вершинный ввод, {cpuWriteOnly} разрешает начальное заполнение с CPU. Шаг в описании буфера фиксирует размер элемента. Описание входа ниже определит интерпретацию каждого атрибута." +tutorial.geometry.upload.guidance: "Выделение памяти не заполняет буфер. {upload} копирует массив в начало буфера, используя исходный указатель и число байтов из описания данных." +tutorial.geometry.upload.imports: "В {programCs} добавьте {bufferAlias} к директивам using, чтобы отличить тип буфера Zenith.NET от {systemBuffer}." +tutorial.geometry.upload.notes: "В коде освобождения в конце {programCs} вставьте {vertexBufferDispose} непосредственно перед {swapChainDispose}. Память только для GPU и загрузка крупной статической геометрии рассмотрены в статье «{link}»." tutorial.geometry.upload.notes.link: Управление ресурсами -tutorial.geometry.upload.title: Выделение буфера и загрузка массива -tutorial.input.description: "Байты вершин и шейдеры готовы. Теперь опишите, как GPU должен считывать каждую вершину. Атрибут — это отдельное значение, например положение или цвет. Разметка входных данных задаёт формат и байтовое смещение каждого атрибута; шаг (stride) задаёт расстояние в байтах от одной вершины до следующей. Добавьте этот блок инициализации после создания шейдеров:" -tutorial.input.details: "Метод {inputLayoutAdd} добавляет элемент с текущим смещением шага и увеличивает шаг на размер этого элемента. Он не анализирует структуру C#. В данном случае формируется следующее соответствие между памятью CPU и входами шейдера:" -tutorial.input.guidance: "Изменение порядка полей C# или выравнивания без обновления этого описания приведёт к тому, что GPU прочитает неверные байты. Значение {semanticIndex} по умолчанию равно нулю, что соответствует {pOSITION0} и {cOLOR0}. Оба элемента принадлежат одному буферу, поэтому конвейер будет содержать одну входную разметку, и мы привяжем этот буфер к слоту 0." +tutorial.geometry.upload.title: "Создание и заполнение буфера" +tutorial.input.description: "GPU нужно знать, где хранятся атрибуты вершины, например позиция и цвет. Описание входа задаёт их формат и смещение, а также шаг — расстояние в байтах до следующей вершины. Добавьте этот код после создания шейдеров:" +tutorial.input.details: "{inputLayoutAdd} размещает каждый атрибут сразу после предыдущего и увеличивает шаг между вершинами на размер добавленного атрибута. Смещения рассчитываются по указанным форматам, без анализа структуры C#. Для этих двух полей получается следующая раскладка:" +tutorial.input.guidance: "Значение {semanticIndex} по умолчанию равно нулю и соответствует {pOSITION0} и {cOLOR0} в шейдере. Позиция и цвет хранятся вместе в одном вершинном буфере, поэтому конвейер использует одно описание входных данных в слоте 0. Если порядок полей или выравнивающие промежутки в структуре C# изменятся, измените и это описание." tutorial.input.table.headings.byteOffset: Байтовое смещение tutorial.input.table.headings.cField: "Поле C#" tutorial.input.table.headings.format: Формат @@ -416,94 +412,87 @@ tutorial.input.table.nextVertex.format: "Полный шаг: 28 байт" tutorial.input.table.nextVertex.shaderInput: Следующая входная запись tutorial.input.table.vertexColor.format: "{float4} (16 байт)" tutorial.input.table.vertexPosition.format: "{float3} (12 байт)" -tutorial.input.title: Описание разметки входных вершинных данных -tutorial.lifecycle.description: "Готовое приложение повторяет следующую последовательность:" -tutorial.lifecycle.details: "Закрытие окна приводит к выходу из метода {run}. Каждый отрисованный кадр уже дождался завершения работы на GPU, поэтому мы можем освободить использованные ресурсы. Блок очистки после {windowRun} должен выглядеть так:" -tutorial.lifecycle.guidance: "Освобождайте цепочку обмена до её нативного окна, а контекст — после всех его ресурсов. Очередь владеет отправленными командными буферами и повторно использует их; выходной текстурой владеет цепочка обмена. Поэтому для этих командных буферов и выходной текстуры в данном приложении не нужен отдельный вызов {dispose}." -tutorial.lifecycle.title: Жизненный цикл одного кадра -tutorial.pipeline.behavior: "После разметки входных данных добавьте:" -tutorial.pipeline.context: "{cullNone} задаёт заполнение треугольника без отсечения по ориентации грани. Порядок вершин определяет направление обхода, поэтому отключение отсечения не позволит этому порядку скрыть наш первый треугольник." -tutorial.pipeline.description: Теперь у нас есть данные вершин, разметка входных данных и два шейдера. Объект {graphicsPipeline} объединяет их и определяет, как GPU собирает вершины в примитивы и записывает результат во вложение. -tutorial.pipeline.details: "Конвейер объединяет программируемые стадии шейдеров с настройками фиксированных функций, которые управляют такими операциями GPU, как сборка треугольников, отсечение граней и смешивание цветов. Для этого треугольника выберите следующие параметры:" -tutorial.pipeline.guidance: Формат цвета берётся из {swapChainDescFormat}. Он должен совпадать с изображением, используемым проходом рендеринга. Значение {count1} означает один сэмпл на пиксель. -tutorial.pipeline.item: "{triangleList} собирает каждую последовательную тройку вершин в один треугольник. Мы передадим три вершины и выполним одну отрисовку, поэтому индексный буфер не нужен." -tutorial.pipeline.notes: "{depthNone} отключает проверку и запись глубины, что соответствует проходу без вложения глубины." -tutorial.pipeline.reference: "{opaque} отключает смешивание, поэтому цвет фрагментного шейдера заменяет фон внутри треугольника." -tutorial.pipeline.title: Связывание шейдеров и разметки вершин -tutorial.pipeline.usage: Объекты шейдеров можно освободить после создания конвейера, как это сделано в демонстрационном рендерере. Сам конвейер должен оставаться активным для каждого кадра, где он используется для отрисовки. Добавьте {pipelineDispose} перед {vertexBufferDispose} в блоке очистки. Создание конвейера — последний шаг инициализации перед обратным вызовом рендеринга. -tutorial.pipeline.validation: Описание конвейера объявляет конфигурацию вложений; оно не создаёт дополнительного изображения. Массив {inputLayouts} содержит одну запись, так как положение и цвет хранятся вместе в одном буфере. -tutorial.presentation.title: Подключение GPU к окну -tutorial.project.context: Включите {emphasis} ({allowUnsafeBlocks}) в настройках сборки проекта. Это необходимо для передачи данных вершин в GPU и для нативных вызовов вспомогательного класса окна. +tutorial.input.title: "Описание вершинного входа" +tutorial.lifecycle.description: "Каждый кадр выполняется в таком порядке:" +tutorial.lifecycle.details: "После закрытия окна {run} возвращает управление, и выполнение продолжается в коде освобождения ресурсов. Каждый кадр уже дождался завершения своих команд, поэтому использованные ими ресурсы можно освободить. Полный код после {windowRun} выглядит так:" +tutorial.lifecycle.guidance: "Освободите цепочку обмена перед уничтожением её окна, а контекст — после его ресурсов. Очередь повторно использует отправленные командные буферы, а цепочка обмена управляет своей выходной текстурой. Отдельный вызов {dispose} для этих объектов не нужен." +tutorial.lifecycle.title: "Цикл кадра и освобождение ресурсов" +tutorial.pipeline.behavior: "После описания входа создайте конвейер:" +tutorial.pipeline.context: "{cullNone} отключает отбрасывание граней. Треугольник будет нарисован независимо от того, расположены ли его вершины на экране по часовой стрелке или против неё." +tutorial.pipeline.description: "{graphicsPipeline} объединяет описание вершин, два шейдера и настройки сборки примитивов и записи во вложения." +tutorial.pipeline.details: "Шейдеры обрабатывают вершины и фрагменты. Остальные настройки конвейера управляют сборкой примитивов, отбрасыванием граней, проверкой глубины и смешиванием цветов:" +tutorial.pipeline.guidance: "Цветовой формат конвейера должен совпадать с вложением прохода, поэтому берётся из {swapChainDescFormat}. {count1} задаёт одну выборку на пиксель." +tutorial.pipeline.item: "{triangleList} собирает каждую последовательную тройку вершин в треугольник." +tutorial.pipeline.notes: "{depthNone} отключает проверку и запись глубины, что соответствует отсутствию вложения глубины." +tutorial.pipeline.reference: "{opaque} отключает смешивание. Поэтому результат фрагментного шейдера заменяет фон внутри треугольника." +tutorial.pipeline.title: "Графический конвейер" +tutorial.pipeline.usage: "Объекты шейдеров можно освободить после создания конвейера. Сам конвейер сохраняйте на время рендеринга; в коде освобождения добавьте {pipelineDispose} перед {vertexBufferDispose}." +tutorial.presentation.title: "Графический контекст и вывод" +tutorial.project.context: "В настройках сборки включите «{emphasis}» ({allowUnsafeBlocks}). Небезопасный код нужен для нативных вызовов вспомогательного оконного кода и загрузки вершин." tutorial.project.context.emphasis: Разрешить небезопасный код -tutorial.project.description: "Создайте проект и перейдите в его каталог:" -tutorial.project.details: "Установите пакеты:" -tutorial.project.guidance: Пакет {zenithNET} предоставляет общий API рендеринга. Три пакета бэкендов позволяют одной и той же программе выбирать реализацию для своей платформы. {zenithNETCompiler} компилирует шейдеры Slang — небольшие программы GPU, которые мы напишем позже, — для этой реализации. Silk.NET предоставляет окно и цикл обработки событий. -tutorial.project.title: Создание консольного проекта -tutorial.requirements.context: Вы можете следовать инструкциям на этой странице с чистого проекта. Пример {link} и его {detail} доступны в качестве справочника по используемым здесь API рендеринга и окон. -tutorial.requirements.context.detail: общий хост -tutorial.requirements.context.link: Hello Triangle -tutorial.requirements.description: "Вам понадобятся {emphasis}, редактор кода или IDE, а также компьютер с GPU и драйвером, поддерживаемыми бэкендом Zenith.NET. Достаточно базовых знаний C#; графические концепции вводятся по мере их использования. Это обычный консольный проект {net10}. Бэкенд преобразует операции Zenith.NET в вызовы графического API, такого как DirectX 12, Metal или Vulkan. Приложение выбирает один из них при запуске:" +tutorial.project.description: "Создайте консольный проект C# с именем {firstTriangle} для .NET 10." +tutorial.project.details: "Добавьте в проект следующие пакеты NuGet:" +tutorial.project.guidance: "{zenithNET} предоставляет общий API рендеринга, а три пакета бэкендов — его платформенные реализации. {zenithNETCompiler} компилирует шейдеры Slang для выбранного бэкенда. Silk.NET создаёт окно и обрабатывает события." +tutorial.project.title: "Настройка проекта" +tutorial.requirements.context: "Образцы кода для этого урока — {link} и его {detail}." +tutorial.requirements.context.detail: "общая оболочка" +tutorial.requirements.context.link: "пример Hello Triangle" +tutorial.requirements.description: "Нужны {emphasis} и базовое знание C#. Приложение предназначено для {net10}. GPU и драйвер должны поддерживать бэкенд, выбранный для вашей платформы:" tutorial.requirements.description.emphasis: .NET 10 SDK -tutorial.requirements.details: Для Linux требуется сессия оконного менеджера, совместимая с X11, для используемого здесь оконного пути. Дополнительные возможности трассировки лучей и mesh shading для этого треугольника не требуются. -tutorial.requirements.guidance: Zenith.NET выполняет рендеринг в поверхность, предоставляемую приложением. Silk.NET.Windowing создаёт окно рабочего стола и обрабатывает его события. В macOS целевым объектом вывода является слой Metal ({cAMetalLayerCs}); вспомогательный класс окна из учебника подключает этот слой автоматически. +tutorial.requirements.guidance: "Zenith.NET выполняет рендеринг на нативной поверхности, предоставленной приложением. Silk.NET.Windowing создаёт окно и обрабатывает его события. На macOS для вывода используется слой Metal, представленный в {cAMetalLayerCs}; вспомогательный код связывает его с окном." tutorial.requirements.table.headings.graphicsBackend: Графический бэкенд tutorial.requirements.table.headings.platform: Платформа -tutorial.requirements.table.headings.windowSurface: Оконная поверхность tutorial.requirements.table.linux.graphicsBackend: Vulkan 1.4 -tutorial.requirements.table.linux.platform: Linux -tutorial.requirements.table.linux.windowSurface: Окно и дисплей X11; XWayland также подходит +tutorial.requirements.table.linux.platform: "Linux (X11 или XWayland)" tutorial.requirements.table.macOS.graphicsBackend: Metal 4 tutorial.requirements.table.macOS.platform: macOS -tutorial.requirements.table.macOS.windowSurface: Слой Metal, подключённый к окну tutorial.requirements.table.windows.graphicsBackend: DirectX 12 tutorial.requirements.table.windows.platform: Windows -tutorial.requirements.table.windows.windowSurface: Дескриптор окна Win32 -tutorial.requirements.title: Перед началом работы -tutorial.resize.context: "Снова запустите {dotnetRun}. Теперь окно должно иметь равномерный тёмный фон, который сохраняется и при изменении размеров окна. Оставьте этот обратный вызов: треугольник будет отрисован внутри его существующего прохода рендеринга." -tutorial.resize.description: "Изображения цепочки обмена должны соответствовать размерам фреймбуфера. Используйте {framebufferResize} для реагирования на изменения размера в пикселях, включая изменения из-за масштабирования экрана. После обратного вызова рендеринга, перед {windowRun}, добавьте:" -tutorial.resize.details: Silk.NET различает изменение размера окна и {link}. Нам требуется последнее, поскольку цепочка обмена хранит пиксели. У свёрнутого окна фреймбуфер может иметь нулевой размер. В этом случае оба обратных вызова пропускают работу с GPU. После изменения размера проход рендеринга будет использовать новые размеры вложения для области просмотра и отсечения. -tutorial.resize.details.link: изменение размера фреймбуфера -tutorial.resize.guidance: Мы выполняем ожидание после каждой отправки, поэтому ни один из предыдущих кадров не использует изображения в момент, когда обработчик изменения размера заменяет их. Текущая реализация {present} также ожидает завершения в очереди графики. Этот простой цикл гарантирует, что работа одного кадра завершена до начала следующего; в разделе {link} рассматривается более сложное планирование. +tutorial.requirements.title: "Необходимые условия" +tutorial.resize.context: "Снова соберите и запустите приложение. Фон должен заполнять всё окно и после изменения его размера: каждый новый проход задаёт область вывода и прямоугольник отсечения по размерам вложения. Сохраните обработчик рендеринга — в его проход будет добавлено рисование треугольника." +tutorial.resize.description: "Размер изображений цепочки обмена должен соответствовать кадровому буферу. Зарегистрируйте обработчик {framebufferResize} после обработчика рендеринга и перед {windowRun}:" +tutorial.resize.details: "Отслеживайте {link}, измеряемые в пикселях, а не изменения логических размеров окна. Если при сворачивании окна ширина или высота кадрового буфера становится нулевой, обработчик изменения размера оставляет цепочку обмена без изменений. Обработчик рендеринга тоже сразу возвращается, пока хотя бы один размер равен нулю. Рендеринг возобновляется, когда размеры снова позволяют вывести изображение." +tutorial.resize.details.link: "изменения размера кадрового буфера" +tutorial.resize.guidance: "Перед вызовом {present} обработчик рендеринга дожидается завершения команд текущего кадра. Поэтому обработчик изменения размера может заменить изображения цепочки обмена, не прерывая работу предыдущего кадра. Связь завершения команд со временем жизни ресурсов подробнее описана в статье «{link}»." tutorial.resize.guidance.link: Синхронизация -tutorial.resize.title: Реакция на изменение размера -tutorial.shaders.compilation.context: Компиляция выполняется один раз во время инициализации. Свойство {appContextBaseDirectory} находит скопированный шейдер рядом с исполняемым файлом независимо от текущего рабочего каталога. Эти шейдеры используют только вершинный ввод, поэтому привязывать буферы констант, текстуры или дескрипторы ресурсов пока не требуется. -tutorial.shaders.compilation.description: В свойствах файла {triangleSlang} установите параметр {emphasis} в значение {detail}. Благодаря этому шейдер будет скопирован рядом с исполняемым файлом. +tutorial.resize.title: "Изменение размера" +tutorial.shaders.compilation.context: "{appContextBaseDirectory} позволяет загрузить копию шейдера из выходного каталога приложения. Поэтому запуск из другого рабочего каталога не меняет место поиска файла." +tutorial.shaders.compilation.description: "В свойствах {triangleSlang} задайте параметру «{emphasis}» значение «{detail}». При сборке шейдер будет скопирован рядом с исполняемым файлом." tutorial.shaders.compilation.description.detail: Копировать более позднюю версию tutorial.shaders.compilation.description.emphasis: Копировать в выходной каталог -tutorial.shaders.compilation.details: "Вернитесь в {programCs}. После загрузки вершин добавьте эти инструкции инициализации перед обратным вызовом рендеринга:" -tutorial.shaders.compilation.guidance: "{zenithCompiler} возвращает описание шейдера с кодом для запрошенного графического API. {createShader} создаёт соответствующий объект бэкенда. Важны и графический API, и имена точек входа: используйте {contextGraphicsApi} и пишите {vSMain} и {fSMain} точно как в файле Slang." -tutorial.shaders.compilation.title: Компиляция для выбранного бэкенда -tutorial.shaders.context: Структура {fSInput} связывает выход вершинного шейдера со входом фрагментного шейдера. При записи вершинным шейдером семантика {sVPOSITION} задаёт координаты в пространстве отсечения — четыре координаты, по которым GPU определяет, что попадает в видимую область изображения. Семантика {cOLOR0} передаёт цвет для интерполяции между вершинами. Обе стадии должны согласовывать его тип и семантику. -tutorial.shaders.description: Шейдер — это программа, выполняемая на GPU. Для этой отрисовки требуются вершинный шейдер для позиционирования вершин и фрагментный шейдер для формирования цветов внутри треугольника. Мы напишем их на языке шейдеров Slang и скомпилируем две точки входа из одного файла. Точка входа — это функция, с которой начинается выполнение стадии шейдера. -tutorial.shaders.details: "Создайте файл {triangleSlang}, начав со следующих двух структур:" -tutorial.shaders.fragment.description: "Добавьте точку входа фрагментного шейдера в тот же файл:" -tutorial.shaders.fragment.details: Растеризация определяет, какие пиксели изображения покрывает треугольник. Она генерирует фрагменты — данные, обрабатываемые фрагментным шейдером, с цветами вершин, интерполированными по покрытой области. Функция {fSMain} возвращает этот интерполированный цвет через семантику {sVTARGET}, которая идентифицирует первое цветовое вложение. -tutorial.shaders.fragment.guidance: Интерполяция цвета вершин происходит отдельно от смешивания во вложении. Смешивание (blending) комбинирует вывод фрагмента с цветом, уже сохранённым во вложении. Наше непрозрачное состояние смешивания отключает эту комбинацию, поэтому интерполированный цвет заменяет фон внутри треугольника. -tutorial.shaders.fragment.title: Окрашивание фрагментов -tutorial.shaders.guidance: "Структура {vSInput} описывает, что вершинный шейдер получает из буфера вершин. Семантики {pOSITION0} и {cOLOR0} идентифицируют входные данные; одни лишь имена полей C# не задают это сопоставление." -tutorial.shaders.title: Написание двух стадий шейдера -tutorial.shaders.vertex.description: "Добавьте точку входа вершинного шейдера в {triangleSlang}:" -tutorial.shaders.vertex.details: GPU вызывает эту точку входа для каждой входной вершины. Она добавляет однородную координату {w} к положению и передаёт цвет дальше. После стадии вершин координаты делятся на w; в данном случае это деление оставляет x, y и z без изменений. Именно поэтому выбранные выше координаты можно трактовать непосредственно как нормализованные координаты устройства. -tutorial.shaders.vertex.title: Позиционирование каждой вершины -tutorial.surface.description: "Контексту также необходимо знать, куда выводить изображение. Добавьте следующий код {emphasis}:" +tutorial.shaders.compilation.details: "В {programCs} добавьте инициализацию шейдеров после загрузки вершин и до обработчика рендеринга:" +tutorial.shaders.compilation.guidance: "{zenithCompiler} компилирует исходный код для {contextGraphicsApi}, а {createShader} создаёт объект шейдера из полученного описания. Имена точек входа {vSMain} и {fSMain} выбирают две функции, определённые в файле Slang." +tutorial.shaders.compilation.title: "Компиляция шейдеров" +tutorial.shaders.context: "{fSInput} связывает две шейдерные стадии. Вершинный шейдер записывает в {sVPOSITION} позицию в пространстве отсечения; по ней GPU определяет видимую часть треугольника. Поле {cOLOR0} передаёт цвет вершины, который интерполируется по треугольнику перед поступлением во фрагментный шейдер. Тип и семантика этого поля должны совпадать между стадиями." +tutorial.shaders.description: "Шейдеры — программы, выполняемые на GPU. Вершинный шейдер определяет положение каждой вершины, а фрагментный — цвет в точках изображения, покрытых треугольником. Обе стадии будут записаны в одном файле Slang. Для каждой задаётся отдельная точка входа — функция, с которой начинается выполнение." +tutorial.shaders.details: "Создайте {triangleSlang} с этими структурами входа и выхода:" +tutorial.shaders.fragment.description: "Добавьте в тот же файл точку входа фрагментного шейдера:" +tutorial.shaders.fragment.details: "Растеризация определяет, какие точки изображения покрывает треугольник, и создаёт для них фрагменты. Каждый фрагмент получает цвет, интерполированный из цветов трёх вершин. {fSMain} возвращает этот цвет, а {sVTARGET} направляет результат в первое цветовое вложение." +tutorial.shaders.fragment.title: "Фрагментный шейдер" +tutorial.shaders.guidance: "{vSInput} задаёт вход вершинного шейдера. {pOSITION0} и {cOLOR0} связывают атрибуты по семантикам; одних имён полей C# для этого недостаточно." +tutorial.shaders.title: "Стадии шейдеров" +tutorial.shaders.vertex.description: "Добавьте в {triangleSlang} точку входа вершинного шейдера:" +tutorial.shaders.vertex.details: "GPU вызывает её для каждой входной вершины. Функция добавляет однородную координату {w} и передаёт цвет. После обработки вершин позиция делится на w. Здесь w = 1, поэтому x, y и z не меняются и непосредственно задают нормализованные координаты устройства." +tutorial.shaders.vertex.title: "Вершинный шейдер" +tutorial.surface.description: "Задайте нативную поверхность вывода {emphasis}:" tutorial.surface.description.emphasis: после {windowCenter} и перед {windowRun} -tutorial.surface.details: Структура {surface} описывает нативный целевой объект презентации и его размеры в пикселях. Фреймбуфер — это пиксельное изображение, связанное с окном. Свойство {framebufferSize} задаёт его размеры в пикселях; логические размеры окна могут отличаться при включённом масштабировании экрана. -tutorial.surface.guidance: Поверхность соответствует бэкенду, выбранному ранее. Windows предоставляет дескриптор окна, Linux — дисплей и окно X11, а вспомогательный класс macOS — подключённый слой Metal. Это единственная платформа-зависимая часть подключения окна к рендерингу. -tutorial.surface.title: Описание нативной поверхности -tutorial.swapChain.context: "Цепочка обмена использует как контекст, так и нативное окно. Замените строку {windowDispose} в конце {programCs} следующим порядком освобождения ресурсов:" -tutorial.swapChain.description: "Используйте описание поверхности для создания изображений, которые будут выводиться на экран. Сразу после блока поверхности добавьте:" -tutorial.swapChain.details: Объект {swapChain} управляет изображениями, отображаемыми в окне. В каждом кадре {drawable} предоставляет текущее изображение как {texture} — тип API для данных изображений. После отрисовки метод {present} запрашивает отображение результата и переходит к следующему drawable. -tutorial.swapChain.guidance: "Формат {b8G8R8A8UNorm} хранит четыре 8-битных цветовых канала в порядке: синий, зелёный, красный и альфа. Значение {uNorm} означает, что целые числа от 0 до 255 представляют значения от 0 до 1. Шейдер по-прежнему будет возвращать логическое значение RGBA; этот формат определяет, как каналы сохраняются в изображении. Позже графический конвейер использует {swapChainDescFormat} для сопоставления с этим вложением." -tutorial.swapChain.title: Создание цепочки обмена +tutorial.surface.details: "Кадровый буфер — изображение окна в пикселях. {surface} описывает нативный объект вывода и его размеры; {framebufferSize} сообщает размер в пикселях. При масштабировании экрана он может отличаться от логического размера окна." +tutorial.surface.guidance: "Поверхность предоставляет нативные дескрипторы выбранного бэкенда: окно Win32 в Windows, дисплей и окно X11 в Linux или прикреплённый слой Metal в macOS." +tutorial.surface.title: "Нативная поверхность" +tutorial.swapChain.context: "Цепочка обмена зависит от контекста и окна. Замените {windowDispose} в конце {programCs} следующим порядком освобождения:" +tutorial.swapChain.description: "Создайте цепочку обмена сразу после описания поверхности:" +tutorial.swapChain.details: "{swapChain} управляет изображениями, выводимыми в окно. {drawable} предоставляет текущее изображение в виде {texture} — ресурса для хранения изображения в API. После рендеринга {present} запрашивает его вывод и переходит к следующей выходной текстуре." +tutorial.swapChain.guidance: "{b8G8R8A8UNorm} хранит четыре 8-битных канала в порядке синий, зелёный, красный, альфа. {uNorm} отображает целые 0–255 в значения 0–1. Выход шейдера остаётся логическим RGBA; формат задаёт представление в памяти. Конвейер использует {swapChainDescFormat} для соответствия вложению." +tutorial.swapChain.title: "Цепочка обмена" tutorial.title: Первый треугольник -tutorial.troubleshooting.description: "Сначала проверьте ошибки в консоли, а затем используйте контрольные точки, чтобы определить, на каком этапе произошёл сбой:" -tutorial.troubleshooting.details: Используйте {link} и {detail} для сравнения данных вершин, входной разметки и операций отрисовки. В том примере оконная система и отправка команд вынесены в общий хост, тогда как в этом учебнике логика приложения сохранена в {programCs}. Переходите к разделу {context}, чтобы изучить индексную отрисовку, трансформации и тест глубины. +tutorial.troubleshooting.description: "Используйте сообщения консоли и три контрольных результата, чтобы определить этап ошибки:" +tutorial.troubleshooting.details: "{link} и {detail} служат образцами для проверки данных вершин, описания вершинного ввода и команд рисования. В этом примере создание окна и отправка команд вынесены в общую оболочку; в уроке весь порядок работы приложения остаётся в {programCs}. Пример «{context}» знакомит с индексированным рисованием, преобразованиями и проверкой глубины." tutorial.troubleshooting.details.context: Вращающийся куб tutorial.troubleshooting.details.detail: шейдер Slang -tutorial.troubleshooting.details.link: демонстрационный рендерер +tutorial.troubleshooting.details.link: "Демонстрационный рендерер" tutorial.troubleshooting.table.backend.check: Убедитесь, что выбранный бэкенд поддерживается устройством и установленным графическим драйвером. tutorial.troubleshooting.table.backend.symptom: Сбой создания бэкенда -tutorial.troubleshooting.table.drawing.check: Проверьте размер загрузки данных, разметку входа, выбор конвейера и размещение команд отрисовки внутри прохода рендеринга. +tutorial.troubleshooting.table.drawing.check: "Проверьте размер загрузки, описание вершинного входа, выбор конвейера и расположение команд рисования внутри прохода." tutorial.troubleshooting.table.drawing.symptom: Фон отображается, но треугольника нет tutorial.troubleshooting.table.headings.check: Что проверить tutorial.troubleshooting.table.headings.symptom: Симптом @@ -513,13 +502,12 @@ tutorial.troubleshooting.table.shaders.check: Проверьте скопиро tutorial.troubleshooting.table.shaders.symptom: Очистка цветом работает, но загрузка шейдеров завершается ошибкой tutorial.troubleshooting.table.window.check: Убедитесь, что проект .NET собирается и шаг с простым окном выполняется в сессии рабочего стола. В Linux проверьте доступность X11 или XWayland. tutorial.troubleshooting.table.window.symptom: Окно не открывается -tutorial.troubleshooting.title: Поиск и устранение неполадок -tutorial.window.context: "Директива {usingZenithTutorials} импортирует пространство имён вспомогательного класса. Каждый файл C# использует свои обычные директивы using, поэтому импорт взаимодействия требуется в обоих файлах. Псевдоним {buffer} указывает на тип буфера Zenith.NET и отличает его от {systemBuffer}." -tutorial.window.description: Добавьте файл {cocoaHelperCs} в проект, сохранив его пространство имён. Добавьте директиву {interopUsing} в верхней части этого файла перед объявлением пространства имён. Вспомогательный класс подключает слой Metal к окну в macOS; ветки для других платформ его не вызывают. -tutorial.window.details: "Замените сгенерированный файл {programCs} следующим кодом. В нём используются операторы верхнего уровня, которые выполняются по порядку без явного метода {main}. В последующих разделах будет указано, куда добавлять код в этот файл:" -tutorial.window.guidance: "Значение {graphicsAPINone} указывает Silk.NET создать окно без собственного графического контекста. Мы создадим контекст через Zenith.NET. {initialize} создаёт нативное окно и делает его дескрипторы доступными. Дескриптор — идентификатор оконной системы. {center} центрирует окно, а {run} обрабатывает события до его закрытия. Затем выполнение переходит к {dispose}, освобождающему окно." -tutorial.window.notes: Запустите команду {dotnetRun}. Должно открыться пустое окно, реагирующее на перемещение, изменение размера и закрытие. Его содержимое пока не определено, поскольку мы ещё не отправляли команд рендеринга. Закройте его перед продолжением. -tutorial.window.title: Открытие окна +tutorial.troubleshooting.title: "Диагностика ошибок" +tutorial.window.description: "Скачайте {cocoaHelperCs} в проект. Этот вспомогательный класс связывает слой Metal с окном macOS." +tutorial.window.details: "Замените сгенерированный код {programCs} следующим. Операторы верхнего уровня выполняются по порядку без явно объявленного метода {main}. В следующих разделах будет указано, куда добавлять каждый фрагмент:" +tutorial.window.guidance: "{graphicsAPINone} оставляет создание графического контекста за Zenith.NET. {initialize} создаёт нативное окно и открывает доступ к дескрипторам оконной системы. {center} размещает окно по центру экрана. {run} обрабатывает события до закрытия окна, после чего {dispose} освобождает его." +tutorial.window.notes: "Соберите и запустите приложение. Убедитесь, что окно открывается и закрывается, его можно перемещать и менять его размер. Содержимое пока не определено, поскольку команды рендеринга ещё не отправлены. Закройте окно перед продолжением." +tutorial.window.title: "Создание окна" ui.action.copy: Копировать ui.action.navigate: Перейти ui.action.open: Открыть @@ -538,11 +526,11 @@ ui.api.noTypes: Совпадающих типов не найдено. ui.api.types: Типы ui.content.reference: Справочник ui.content.source: Исходный код -ui.content.tutorial: Учебник +ui.content.tutorial: "Урок" ui.contents.close: Закрыть оглавление ui.contents.open: Открыть оглавление ui.contents.title: Содержание -ui.footer.caption: Современный RHI для .NET. +ui.footer.caption: "Графический API для .NET" ui.footer.label: Нижний колонтитул ui.language.label: Язык ui.language.unavailable: Не переведено @@ -555,7 +543,7 @@ ui.members.search: Поиск членов ui.members.title: Найти член ui.members.undeclared: У этого типа нет объявленных членов. ui.navigation.api: API -ui.navigation.concepts: Концепции +ui.navigation.concepts: "Основные понятия" ui.navigation.home: Главная ui.navigation.label: Основная навигация ui.navigation.toggle: Переключить навигацию @@ -594,7 +582,7 @@ ui.reference.value: Значение ui.reference.values: Значения ui.search.close: Закрыть поиск ui.search.empty: По запросу «{query}» ничего не найдено. -ui.search.hint: Поиск по учебникам, концепциям, примерам и справочнику API. +ui.search.hint: "Поиск по урокам, основным понятиям, примерам и справочнику API." ui.search.loading: Загрузка поиска… ui.search.more: Показать больше результатов ui.search.pending: Поиск… diff --git a/documents/locales/ru-RU/translation.md b/documents/locales/ru-RU/translation.md index 691d7166..e8afe164 100644 --- a/documents/locales/ru-RU/translation.md +++ b/documents/locales/ru-RU/translation.md @@ -8,6 +8,16 @@ При переводе меняйте только значения в `strings.yml` этого языка. Набор ключей должен точно совпадать с английским. Не добавляйте, не удаляйте и не переименовывайте ключи по собственной инициативе, даже если тексты похожи или ещё не встретились в интерфейсе. Об ошибке в оригинале сообщите сопровождающим проект, указав ключ и суть проблемы. Сначала исправляются английский текст и общие страницы, затем переводы. +## Стиль и контекст + +Используйте стиль технического учебного пособия: точный, сдержанный и понятный. Сначала объясняйте связь операций, затем условия и ограничения. В уроках сохраняйте конкретные действия и проверяемые результаты. Научная точность не требует тяжёлых пассивных конструкций или длинных фраз. + +Редактируйте статью в порядке чтения, учитывая соседние абзацы, таблицы и код. Ключ — граница хранения, а не самостоятельная единица перевода. Проверяйте падежи, предлоги и согласование ссылок и выделенных фрагментов в полном предложении. + +В заголовках, подписях элементов интерфейса, коротких видимых текстах главной страницы и подписи подвала не ставьте конечную точку. В абзацах, диагностике и инструкциях доступности сохраняйте обычную пунктуацию. Для каждого понятия используйте один принятый термин; не добавляйте выборочно английские пояснения в скобках. Идентификаторы API, файлов и настроек сохраняйте. + +Сохраняйте предложение, если оно объясняет текущую операцию, проектное решение, проверяемый результат или необходимое условие. Удаляйте перечни неиспользуемых возможностей, общие оговорки и повторные требования. Заголовки и фразы, разделённые оформлением, переводите целиком, с естественным русским порядком слов. Позиции `{accent}` и `{lineBreak}` в заголовке главной страницы можно менять: оформление не должно закреплять английский синтаксис. Удаление абзаца и его ключей сопровождающий согласованно выполняет в оригинале, общей разметке и словарях всех языков. + ## Текст и заполнители Переводите предложения или абзацы целиком ясным и естественным техническим русским языком. Сохраняйте условия, отрицания, единицы измерения, порядок действий и ограничения времени жизни. Не добавляйте технических гарантий, требований к платформе, версий пакетов или примечаний к выпускам, которых нет в оригинале. Названия продуктов, пакетов и файлов, а также идентификаторы C# и Slang сохраняйте без изменений, включая регистр. diff --git a/documents/locales/zh-CN/strings.yml b/documents/locales/zh-CN/strings.yml index 703cfe08..562c2cba 100644 --- a/documents/locales/zh-CN/strings.yml +++ b/documents/locales/zh-CN/strings.yml @@ -1,604 +1,592 @@ ### YamlMime:Resources -concepts.execution.context.description: "{graphicsContext} 代表一个后端设备,并提供其图形、计算和传输队列。同一工作负载所需的缓冲区、纹理、着色器和管线应通过同一个图形上下文创建。由另一个图形上下文创建的资源或句柄不能简单地绑定到该上下文的命令缓冲区中。" -concepts.execution.context.details: 根据平台和呈现表面选择后端。API 保持统一共享,但设备支持仍然至关重要。{capabilities} 公开了设备名称以及 {rayTracingSupported} 和 {meshShadingSupported} 标志。在创建可选工作负载之前,请像 {link} 和 {detail} 示例那样先检查对应的标志。这些标志并不构成格式、内存或平台限制的完整清单。 -concepts.execution.context.details.detail: 网格着色(mesh shading) -concepts.execution.context.details.link: 光线追踪 -concepts.execution.context.title: 图形上下文连接资源与队列 -concepts.execution.description: Zenith.NET 应用程序创建 GPU 资源,录制使用这些资源的命令,并将这些命令提交给队列。在 GPU 执行提交的工作时,CPU 可以继续运行。即便录制命令的调用已返回,也必须保持资源有效,直到该工作完成。 -concepts.execution.ownership.description: "在这里,所有权意味着释放资源的责任。C# 引用可以保持托管对象处于可达状态;但它无法阻止显式调用 {dispose} 销毁底层原生资源。同样,提交使用缓冲区的命令并不会将该缓冲区的所有权转移给队列。" -concepts.execution.ownership.details: "关闭时,停止提交新工作,等待涉及的每个队列完成对资源的最后一次使用,再释放应用程序创建的资源,最后释放图形上下文。释放上下文会释放它自身的队列和内部辅助对象;它不会等待所有应用程序工作,也不会释放应用程序创建的全部资源。" -concepts.execution.ownership.guidance: "渲染过程中也要遵循相同的生命周期规则。保留资源最后一次使用的完成值,以便判断何时可以覆盖其数据或替换资源。关于视图及其底层资源的生命周期,请参阅{link}。" -concepts.execution.ownership.guidance.link: 资源管理 -concepts.execution.ownership.table.applicationResources.object: 应用程序创建的资源 -concepts.execution.ownership.table.applicationResources.ownership: 应用程序在其最后一次 GPU 使用后释放它们。 -concepts.execution.ownership.table.commandBuffers.object: 借用的命令缓冲区 -concepts.execution.ownership.table.commandBuffers.ownership: 队列对其进行管理和回收。 -concepts.execution.ownership.table.headings.object: 对象 -concepts.execution.ownership.table.headings.ownership: 谁负责释放? -concepts.execution.ownership.table.queues.object: 图形上下文的队列及其时间线 -concepts.execution.ownership.table.queues.ownership: 图形上下文与队列对其进行管理。 -concepts.execution.ownership.table.swapChainDrawable.ownership: 交换链对其进行管理。 -concepts.execution.ownership.title: 将所有权与 GPU 完成区分开来 -concepts.execution.pipelines.description: 图形管线结合了着色器、顶点输入布局、将顶点组装为图元的规则、附件格式和渲染状态。在绑定顶点、索引或常量数据以及发出绘制命令之前设置它。其附件格式和采样数必须与渲染通道的附件匹配。 -concepts.execution.pipelines.details: 计算管线为分派提供着色器入口点,以启动 GPU 线程组。在分派之前设置它及其常量。计算分派属于图形渲染通道之外。更改管线意味着后续命令解释其输入的方式发生变化;在使用所选管线之前,请先绑定该管线所需的数据。 -concepts.execution.pipelines.guidance: "{link}展示了完整的图形执行序列。{detail}录制了一次分派,随后通过图形通道显示其结果。" -concepts.execution.pipelines.guidance.detail: 计算示例 -concepts.execution.pipelines.guidance.link: 三角形的渲染回调 -concepts.execution.pipelines.title: 管线决定了命令如何解释数据 -concepts.execution.queues.description: 当一个帧结合了绘制、计算和复制时,请从 {graphicsQueue} 开始。将存在依赖关系的工作保持在单个队列上可以让其执行顺序更容易理清。 -concepts.execution.queues.details: 队列接收成批的命令以供执行。独立的队列并不一定对应独立的硬件引擎,因此它们的工作可能无法同时并行运行。当工作负载可以从重叠执行中获益时使用其他队列,并在一个队列消费另一个队列的结果时添加显式依赖关系。 -concepts.execution.queues.guidance: 当后续命令依赖于先前的写入时,应用程序还必须确保这些写入对后续命令可见可用。将两个命令缓冲区提交到同一个队列并不会自动建立所有此类依赖。命令可以使用不同的 GPU 阶段,后续访问可能需要屏障或纹理布局转换。{link}解释了提交顺序与资源可见性之间的区别。 -concepts.execution.queues.guidance.link: 同步 -concepts.execution.queues.table.computeQueue.workToRecord: 计算分派以及兼容的传输工作,不含图形渲染通道。 -concepts.execution.queues.table.graphicsQueue.workToRecord: 渲染通道与绘制,以及帧所使用的计算和传输操作。 -concepts.execution.queues.table.headings.queue: 队列 -concepts.execution.queues.table.headings.workToRecord: 录制的工作 -concepts.execution.queues.table.transferQueue.workToRecord: 上传、回读与复制工作,不含绘制或计算分派。 -concepts.execution.queues.title: 根据所要执行的工作选择队列 -concepts.execution.recording.context: 队列会轮询完成状态并回收已完成的命令缓冲区。为每次新录制调用 {queueCommandBuffer};它可能会返回回收的实例。请勿释放借用的命令缓冲区、请勿重复提交两次,也不要在提交后继续向其中录制。一次仅从一个线程录制给定的命令缓冲区;队列的内部锁无法保护对命令缓冲区的并发修改。 -concepts.execution.recording.description: "{queueCommandBuffer} 返回一个已开始录制的 {commandBuffer}。录制命令及其依赖关系,然后调用一次 {submit}。提交操作结束录制,并返回一个标识该队列上完成点的 {timelineValue}。" -concepts.execution.recording.details: 例如,在将一帧录制到 {commandBuffer} 之后,三角形示例提交它并等待完成: -concepts.execution.recording.guidance: "{submit} 调度工作;{wait} 阻止 CPU 继续向下执行,直到该提交操作完成。录制绘制、结束渲染通道与提交命令缓冲区是互不相同的独立操作。录制绘制和结束渲染通道均不会等待 GPU。" -concepts.execution.recording.title: 录制命令并不等于执行命令 -concepts.execution.title: 执行模型 -concepts.platforms.description: 选择您的应用程序是自行拥有原生窗口和帧循环,还是使用 UI 渲染控件。该选择决定了谁来获取输出纹理、提交命令并呈现结果。输出纹理是用作当前帧输出的纹理。离屏图形和计算工作不需要窗口或交换链。 -concepts.platforms.frame.context: 在该通道内部添加您的管线绑定和绘制命令。在返回之前结束通道。不要独立提交所提供的命令缓冲区或自行呈现,也不要释放命令缓冲区或输出纹理。如果您的处理程序在其他布局中使用了输出纹理,请将其恢复为 {colorAttachment} 以供控件进行最终转换。 -concepts.platforms.frame.description: 这些集成实现了 {iZenithView}。应用程序提供其 {graphicsContext},在 {updateRequested} 中更新场景数据,并在 {renderRequested} 中使用 {renderEventArgs} 录制渲染命令。 -concepts.platforms.frame.details: "控件负责每帧的完整流程:获取输出纹理和命令缓冲区,将输出纹理转换为 {colorAttachment},调用处理程序,然后执行该框架所需的提交和呈现步骤。" -concepts.platforms.frame.guidance: 对于名为 {view} 且已分配上下文的已初始化 {iZenithView},此处理程序录制一个完整的清除通道。它需要 {usingZenithNET}: -concepts.platforms.frame.notes: 控件在每帧开始时均从 {undefined} 转换而来,因此应用程序不能依赖于输出纹理先前内容的保留。每帧都要清除或渲染所需的图像。将持久累积或缓存的渲染内容保存在应用程序自有的纹理中,然后通过视图显示该纹理。 -concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat} 提供集成的默认颜色格式。在匹配附件格式、采样数和尺寸时,请检查实际事件中的输出纹理。" -concepts.platforms.frame.title: 录制到 UI 控件提供的帧中 -concepts.platforms.integration.context: WinForms、WPF 和 Windows 的 WinUI 路径需要 Windows。MAUI 应用程序需要其目标平台的工作负载,并且必须使用 {useZenithView} 注册控件处理程序;参见 {extensionsCs}。框架支持和后端支持都必须满足。 -concepts.platforms.integration.description: 控件共享事件接口,但呈现方式并非全都相同: -concepts.platforms.integration.details: 位图回读在 UI 显示之前将渲染的像素复制到 CPU 内存中。共享纹理互操作避免了这种回读,但仍可能需要 GPU 复制和同步。因此,共享的 {renderRequested} 接口并不意味着相同的呈现开销或原生互操作要求。 -concepts.platforms.integration.guidance: 使用对应于应用程序框架的包;例如: -concepts.platforms.integration.table.avalonia.integration: Avalonia -concepts.platforms.integration.table.avalonia.presentation: "渲染到纹理,再将像素回读到 {writeableBitmap}。参见 {zenithViewCs} 和 {surfaceCs}。" -concepts.platforms.integration.table.headings.integration: 集成 -concepts.platforms.integration.table.headings.presentation: 图像如何到达 UI -concepts.platforms.integration.table.maui.integration: .NET MAUI -concepts.platforms.integration.table.maui.presentation: 在 Android、iOS 和 Mac Catalyst 上使用原生呈现目标,在 Windows 上使用共享纹理合成。参见{link}。 -concepts.platforms.integration.table.maui.presentation.link: 平台实现 -concepts.platforms.integration.table.uno.integration: Uno 路径 -concepts.platforms.integration.table.uno.presentation: "将像素回读到 {writeableBitmap}。参见 {zenithViewUnoCs}。" -concepts.platforms.integration.table.winForms.integration: WinForms -concepts.platforms.integration.table.winForms.presentation: 为控件的 {hWND} 创建 Zenith.NET 交换链。参见 {zenithViewCs}。 -concepts.platforms.integration.table.winUI.integration: Windows 上的 WinUI -concepts.platforms.integration.table.winUI.presentation: 渲染到导入的共享 Direct3D 11 纹理中,然后复制到连接至 {swapChainPanel} 的合成交换链。参见 {zenithViewWinUICs}。 -concepts.platforms.integration.table.wpf.integration: WPF -concepts.platforms.integration.table.wpf.presentation: 导入共享 Direct3D 11 纹理,然后通过 Direct3D 互操作复制到由 {d3DImage} 显示的表面。参见 {surfaceCs}。 -concepts.platforms.integration.title: 选择呈现路径以及框架 -concepts.platforms.lifecycle.context: 对于 UI 视图,在创建匹配的渲染资源时,使用事件输出纹理的 {descWidth}、{descHeight}、{descFormat} 和 {descSampleCount}。控件决定该输出纹理的分辨率;不要假定其逻辑尺寸或显示缩放比例始终等于纹理尺寸。 -concepts.platforms.lifecycle.description: 对于原生交换链,请以像素为单位传递帧缓冲区尺寸。启用显示缩放时,以逻辑单位表示的窗口大小可能会有所不同。跳过零尺寸的帧缓冲区,在像素大小变化时调整交换链大小,并为每帧获取 {swapChainDrawable}。输出纹理归交换链所有,并可能在呈现或调整大小后发生改变。 -concepts.platforms.lifecycle.details: "{swapChainResize} 更改现有呈现目标的尺寸。{swapChainRefresh} 替换呈现目标描述,包括原生句柄。在执行任一操作前,应先完成对受影响资源的所有未完成访问。销毁原生呈现目标前,应先释放交换链。" -concepts.platforms.lifecycle.guidance: 重新创建尺寸跟随窗口变化的应用程序自有深度或离屏纹理,并更新包含其句柄的常量。当附件格式和采样数保持兼容时,管线可以在尺寸变化后继续使用。{link}在替换深度纹理的同时保留了其管线。 -concepts.platforms.lifecycle.guidance.link: 旋转立方体渲染器 -concepts.platforms.lifecycle.title: 输出纹理的尺寸和生命周期由宿主决定 -concepts.platforms.ownership.description: 应用程序拥有其分配的图形上下文以及为渲染创建的资源。控件拥有其自身的呈现资源。更改视图的 {graphicsContext} 属性会使调度程序重新创建控件的资源;它不会为新上下文重新创建应用程序的管线、缓冲区或纹理。 -concepts.platforms.ownership.details: 将资源替换与视图的帧生命周期协调一致。在释放应用程序资源或分配的上下文之前,停止视图的帧活动并完成未决的 GPU 使用。移除视图不会将上下文所有权转移给控件。 -concepts.platforms.ownership.guidance: 共享的 {frameSchedulerCs} 通过视图的 UI 调度程序调度帧工作。使帧处理程序集中于更新和录制帧;在那里进行冗长的 CPU 任务也会使 UI 卡顿。 -concepts.platforms.ownership.title: 将应用程序资源保留在控件所有权之外 -concepts.platforms.surface.context: 窗口库或 UI 框架支持某种操作系统并不保证所选的 GPU 后端在其中可用。设备特性、驱动程序和原生呈现目标支持仍需匹配。在创建这些工作负载之前,通过 {contextCapabilities} 检查可选的光线追踪和网格着色(mesh shading)。 -concepts.platforms.surface.description: "{link}使用 Silk.NET 创建窗口并处理事件。Zenith.NET 通过 {surface} 描述和交换链 {swapChain} 连接到该窗口。原生呈现目标包含原生句柄和尺寸;构造该描述不会创建或拥有操作系统窗口。" -concepts.platforms.surface.description.link: 三角形教程 -concepts.platforms.surface.details: 句柄必须与所选后端匹配: -concepts.platforms.surface.guidance: 教程中的 {appCs} 显示了 Windows、macOS 和 X11 的选择。其 Linux 宿主提供 Xlib 句柄;在 Wayland 会话中使用它需要 XWayland。原生 Wayland 应用程序将通过 {surfaceWayland} 提供不同的句柄。 -concepts.platforms.surface.table.android.backend: Android 上的 Vulkan。 -concepts.platforms.surface.table.apple.backend: Apple 平台上的 Metal。 -concepts.platforms.surface.table.headings.backend: 后端路径 -concepts.platforms.surface.table.headings.factory: 呈现目标工厂 -concepts.platforms.surface.table.headings.handles: 宿主提供的句柄 -concepts.platforms.surface.table.wayland.backend: 带有原生 Wayland 宿主的 Vulkan。 -concepts.platforms.surface.table.wayland.handles: Wayland 显示与表面 -concepts.platforms.surface.table.win32.backend: Windows 上的 DirectX 12 或 Vulkan。 -concepts.platforms.surface.table.xlib.backend: Linux 上带有 X11 或 XWayland 的 Vulkan。 -concepts.platforms.surface.table.xlib.handles: X11 显示与窗口 -concepts.platforms.surface.title: 当应用程序拥有呈现所有权时提供原生呈现目标 -concepts.platforms.title: 平台集成 -concepts.resources.allocation.context: "除非需要自行实现内存分配器,否则先使用图形上下文创建的资源。使用堆时,应先等待所有使用这些资源的 GPU 工作完成,再释放堆中放置的资源,最后释放堆本身。" -concepts.resources.allocation.description: "{heap} 提供内存,供您在指定的字节偏移量处放置资源。应用程序负责选择这些偏移量,并跟踪哪些区域正在使用。" -concepts.resources.allocation.details: "放置资源前,使用准确的缓冲区或纹理描述调用 {contextGetSizeAndAlignment}。所选偏移量必须是返回的对齐值的整数倍,预留空间必须满足返回的大小,资源也必须位于堆的总字节范围内。仍在使用的分配区域不得重叠。纹理存储可能包含后端特有的填充和对齐,因此不能用像素数量乘以每像素字节数来计算分配大小。" -concepts.resources.allocation.guidance: "对于放置在堆中的缓冲区,其内存驻留设置应与堆一致。这里介绍的常规 GPU 纹理应使用仅 GPU 堆。大小和对齐是放置资源的要求,并不保证所有后端都能将任意资源放入任意堆。" -concepts.resources.allocation.title: 在需要分配控制时将资源放置在堆中 -concepts.resources.bufferUsages.table.constant.role: 通过常量缓冲区绑定读取的着色器参数。 +concepts.execution.context.description: "{graphicsContext} 通过特定后端连接应用程序与 GPU 设备,并提供图形、计算和传输队列。配合使用的资源必须属于同一上下文;缓冲区、纹理、着色器、管线及其句柄不能跨上下文绑定。" +concepts.execution.context.details: "{capabilities} 提供设备名称与支持的功能。创建光线追踪或网格着色所需的资源前,分别通过 {rayTracingSupported} 和 {meshShadingSupported} 检查支持情况。{link}与{detail}示例展示了初始化时的检查方式。" +concepts.execution.context.details.detail: "网格着色" +concepts.execution.context.details.link: "光线追踪" +concepts.execution.context.title: "图形上下文" +concepts.execution.description: "GPU 工作从 CPU 端开始:应用程序创建资源,录制使用这些资源的命令,再将命令提交到队列。提交之后,CPU 可以继续处理其他任务,同时由 GPU 执行命令。相关资源必须保留到执行结束。" +concepts.execution.ownership.description: "所有权决定由谁释放对象,GPU 完成状态决定何时可以释放。即使仍保留对象的 C# 引用,调用 {dispose} 也会释放其原生资源。提交命令不会将资源所有权转交给队列。" +concepts.execution.ownership.details: "关闭程序时,先停止提交新工作,并等待所有相关队列完成最后一次资源访问。随后释放应用程序资源,最后释放上下文。上下文会释放自身的队列和内部辅助对象,因此这一步应在应用程序工作全部完成后进行。" +concepts.execution.ownership.guidance: "渲染期间,若准备覆盖数据或替换资源,应跟踪仍在使用它们的工作。等待这些访问完成后,再修改数据或释放存储。视图与底层资源如何遵循这一生命周期规则,见{link}。" +concepts.execution.ownership.guidance.link: "资源管理" +concepts.execution.ownership.table.applicationResources.object: "应用程序创建的资源" +concepts.execution.ownership.table.applicationResources.ownership: "最后一次 GPU 使用完成后,由应用程序释放。" +concepts.execution.ownership.table.commandBuffers.object: "借用的命令缓冲区" +concepts.execution.ownership.table.commandBuffers.ownership: "由队列管理和回收。" +concepts.execution.ownership.table.headings.object: "对象" +concepts.execution.ownership.table.headings.ownership: "释放责任" +concepts.execution.ownership.table.queues.object: "图形上下文的队列及其时间线" +concepts.execution.ownership.table.queues.ownership: "由上下文和队列管理。" +concepts.execution.ownership.table.swapChainDrawable.ownership: "由交换链管理。" +concepts.execution.ownership.title: "所有权与生命周期" +concepts.execution.pipelines.description: "图形管线规定绘制所用的着色器、顶点输入布局、图元组装方式、附件格式和渲染状态。绑定顶点、索引或常量数据之前,须先选择管线;管线声明的附件格式与采样数也必须与渲染通道一致。" +concepts.execution.pipelines.details: "计算管线选择分派所执行的着色器入口点。在图形渲染通道之外,先绑定管线及其常量,再执行分派。" +concepts.execution.pipelines.guidance: "{link}给出了完整的图形命令顺序。{detail}则先执行计算分派,再通过图形通道显示结果。" +concepts.execution.pipelines.guidance.detail: "计算示例" +concepts.execution.pipelines.guidance.link: "三角形的渲染回调" +concepts.execution.pipelines.title: "管线状态" +concepts.execution.queues.description: "一帧同时包含绘制、计算和复制时,通常从 {graphicsQueue} 开始。将有依赖的操作放在同一队列,有助于明确执行顺序。" +concepts.execution.queues.details: "不同队列可以分别接收独立的工作负载,但未必对应独立的硬件引擎。若工作能够从重叠执行中受益,再考虑增加队列。当一个队列使用另一个队列生成的数据时,需要在两次提交之间建立显式依赖。" +concepts.execution.queues.guidance: "即使位于同一队列,有依赖的操作也可能需要屏障或纹理转换,才能让后续访问读到此前写入的结果。这种内存依赖与提交顺序不同,具体表达方式见{link}。" +concepts.execution.queues.guidance.link: "同步" +concepts.execution.queues.table.computeQueue.workToRecord: "计算分派以及兼容的传输工作,不含图形渲染通道。" +concepts.execution.queues.table.graphicsQueue.workToRecord: "渲染通道、绘制、计算与传输操作。" +concepts.execution.queues.table.headings.queue: "队列" +concepts.execution.queues.table.headings.workToRecord: "支持的工作" +concepts.execution.queues.table.transferQueue.workToRecord: "上传、回读与复制工作,不含绘制或计算分派。" +concepts.execution.queues.title: "队列选择" +concepts.execution.recording.context: "队列会回收已完成的命令缓冲区以供复用。每次录制时,通过 {queueCommandBuffer} 获取缓冲区,同一时间只由一个线程录制,并且只提交一次。提交后,将缓冲区交由队列管理,不再修改、重复提交或自行释放。" +concepts.execution.recording.description: "{queueCommandBuffer} 返回的 {commandBuffer} 已处于录制状态。录制完操作及其依赖后,调用一次 {submit}。提交会结束录制,并返回标识该队列完成点的 {timelineValue}。" +concepts.execution.recording.details: "三角形教程将一帧录制到 {commandBuffer} 后,按如下方式提交并等待完成:" +concepts.execution.recording.guidance: "录制构造命令序列,{submit} 安排该序列执行。随后调用 {wait},CPU 线程会等待本次提交完成。教程因此采用逐帧执行的流程:当前帧完成后,才开始下一帧。" +concepts.execution.recording.title: "录制与提交" +concepts.execution.title: "执行模型" +concepts.platforms.description: "呈现流程可以由应用程序管理,也可以交给 UI 渲染控件。这决定了谁来获取当前帧的输出纹理、录制和提交命令,以及显示渲染结果。" +concepts.platforms.frame.context: "在通道内绑定管线并录制绘制命令,处理程序返回前须结束通道。控件负责提交命令并呈现结果;处理程序不得自行提交命令缓冲区,也不得释放传入的命令缓冲区或输出纹理。若改变了输出纹理的布局,返回前须恢复为 {colorAttachment},以便控件完成最后的转换。" +concepts.platforms.frame.description: "各控件实现 {iZenithView} 接口。应用程序设置 {graphicsContext},在 {updateRequested} 中更新场景,并在 {renderRequested} 中通过传入的 {renderEventArgs} 录制命令。" +concepts.platforms.frame.details: "每帧,控件获取输出纹理与命令缓冲区,将输出纹理转换为 {colorAttachment},再调用更新和渲染处理程序。之后,控件提交录制的工作,并通过对应框架的呈现机制显示图像。" +concepts.platforms.frame.guidance: "先在文件中添加 {usingZenithNET}。假定名为 {view} 的 {iZenithView} 实例已初始化并设置图形上下文,可注册以下处理程序清除其输出纹理:" +concepts.platforms.frame.notes: "初始转换使用 {undefined},允许丢弃先前图像的内容。因此,每帧都应重新绘制或清除整张图像。需要累积或缓存的渲染结果,可保存在应用程序拥有的纹理中,再将该纹理绘制到控件的输出纹理上。" +concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat} 提供这些集成使用的默认颜色格式。" +concepts.platforms.frame.title: "通过 UI 控件渲染" +concepts.platforms.integration.context: "WinForms、WPF 和 Windows 版 WinUI 集成运行于 Windows。使用 MAUI 时,安装目标平台的工作负载,并通过 {useZenithView} 注册控件处理程序,具体见 {extensionsCs}。" +concepts.platforms.integration.description: "控件共享事件接口,但呈现机制因框架而异:" +concepts.platforms.integration.details: "各实现将 GPU 图像送到 UI 的方式不同。位图回读先将像素复制到 CPU 内存,再显示图像;共享纹理互操作可以省去这次 CPU 复制,但仍可能需要 GPU 复制与同步。选择集成方式时,除了共用的 {renderRequested} 事件接口,也应考虑其呈现路径。" +concepts.platforms.integration.guidance: "通过 NuGet 添加所用 UI 框架的集成包。Avalonia 对应的包为 {avaloniaPackage}。" +concepts.platforms.integration.table.avalonia.integration: "Avalonia" +concepts.platforms.integration.table.avalonia.presentation: "渲染到纹理后,将像素回读到 {writeableBitmap},实现见 {zenithViewCs} 和 {surfaceCs}。" +concepts.platforms.integration.table.headings.integration: "集成" +concepts.platforms.integration.table.headings.presentation: "呈现机制" +concepts.platforms.integration.table.maui.integration: ".NET MAUI" +concepts.platforms.integration.table.maui.presentation: "Android、iOS 和 Mac Catalyst 使用原生呈现目标;Windows 使用共享纹理合成,具体见{link}。" +concepts.platforms.integration.table.maui.presentation.link: "平台实现" +concepts.platforms.integration.table.uno.integration: "Uno 路径" +concepts.platforms.integration.table.uno.presentation: "将像素回读到 {writeableBitmap},实现见 {zenithViewUnoCs}。" +concepts.platforms.integration.table.winForms.integration: "WinForms" +concepts.platforms.integration.table.winForms.presentation: "为控件的 {hWND} 创建 Zenith.NET 交换链,实现见 {zenithViewCs}。" +concepts.platforms.integration.table.winUI.integration: "Windows 上的 WinUI" +concepts.platforms.integration.table.winUI.presentation: "渲染到导入的共享 Direct3D 11 纹理,再复制到与 {swapChainPanel} 连接的合成交换链,具体见 {zenithViewWinUICs}。" +concepts.platforms.integration.table.wpf.integration: "WPF" +concepts.platforms.integration.table.wpf.presentation: "导入共享 Direct3D 11 纹理,再经 Direct3D 互操作复制到由 {d3DImage} 显示的表面,具体见 {surfaceCs}。" +concepts.platforms.integration.title: "框架与呈现路径" +concepts.platforms.lifecycle.context: "创建配套附件时,使用渲染事件传入的输出纹理的 {descWidth}、{descHeight}、{descFormat} 和 {descSampleCount}。该纹理给出了渲染目标的实际尺寸,不应根据控件的布局尺寸或显示缩放比例推算。" +concepts.platforms.lifecycle.description: "交换链使用以像素计量的帧缓冲区宽度和高度。启用显示缩放时,这些值可能不同于窗口的逻辑尺寸。任一尺寸为零时,暂停渲染和交换链尺寸调整。每帧重新获取 {swapChainDrawable}:这张纹理由交换链管理,可能在呈现或调整大小后被替换。" +concepts.platforms.lifecycle.details: "帧缓冲区尺寸变化时,先等待 GPU 完成对旧图像的访问,再调用 {swapChainResize}。替换原生呈现目标时,也应先等待这些访问结束,再将新的呈现目标描述与句柄传给 {swapChainRefresh}。关闭程序时,先释放交换链,再销毁其原生呈现目标。" +concepts.platforms.lifecycle.guidance: "应用程序的深度纹理或离屏纹理若随窗口尺寸变化,就需要在调整大小时重建,并更新包含其句柄的常量。只要附件格式与采样数仍然匹配,管线就可以复用。{link}展示了如何调整纹理尺寸并保留管线。" +concepts.platforms.lifecycle.guidance.link: "旋转立方体渲染器" +concepts.platforms.lifecycle.title: "交换链尺寸与生命周期" +concepts.platforms.ownership.description: "应用程序拥有所设置的上下文及其渲染资源,控件拥有呈现资源。视图的 {graphicsContext} 变化后,调度程序会为新上下文重建控件资源。应用程序也须为该上下文重建自己的管线、缓冲区和纹理。" +concepts.platforms.ownership.details: "替换渲染资源前,先停止视图的帧活动,并等待使用这些资源的 GPU 工作完成,再释放旧资源或上下文。移除视图后,所设置的上下文仍由应用程序负责释放。" +concepts.platforms.ownership.guidance: "共享的 {frameSchedulerCs} 通过视图的 UI 调度器运行帧处理程序。处理程序应集中于场景数据更新和命令录制,其中耗时的 CPU 工作也会延迟界面响应。" +concepts.platforms.ownership.title: "应用程序与控件的责任" +concepts.platforms.surface.description: "{link}使用 Silk.NET 创建窗口并处理事件。Zenith.NET 通过 {surface} 描述获取原生窗口句柄与尺寸,再据此创建 {swapChain}。操作系统窗口仍由应用程序负责管理。" +concepts.platforms.surface.description.link: "三角形教程" +concepts.platforms.surface.details: "原生句柄必须与所选后端匹配:" +concepts.platforms.surface.guidance: "{appCs} 中的示例宿主支持 Windows、macOS 和 X11。Linux 窗口提供 Xlib 句柄,因此在 Wayland 会话中需要 XWayland。原生 Wayland 应用程序则通过 {surfaceWayland} 提供显示与表面句柄。" +concepts.platforms.surface.table.android.backend: "Android 上的 Vulkan。" +concepts.platforms.surface.table.apple.backend: "Apple 平台上的 Metal。" +concepts.platforms.surface.table.headings.backend: "后端与平台" +concepts.platforms.surface.table.headings.factory: "呈现目标工厂方法" +concepts.platforms.surface.table.headings.handles: "宿主提供的句柄" +concepts.platforms.surface.table.wayland.backend: "带有原生 Wayland 宿主的 Vulkan。" +concepts.platforms.surface.table.wayland.handles: "Wayland 显示与表面" +concepts.platforms.surface.table.win32.backend: "Windows 上的 DirectX 12 或 Vulkan。" +concepts.platforms.surface.table.xlib.backend: "Linux 上带有 X11 或 XWayland 的 Vulkan。" +concepts.platforms.surface.table.xlib.handles: "X11 显示与窗口" +concepts.platforms.surface.title: "原生呈现目标" +concepts.platforms.title: "平台集成" +concepts.resources.allocation.context: "放置在堆中的资源在整个生命周期内都依赖堆的存储。最后一次 GPU 使用完成后,应先释放资源,再释放堆。" +concepts.resources.allocation.description: "应用程序需要自行管理内存分配时,可以使用 {heap}。堆为资源提供存储,应用程序选择明确的字节偏移量来放置资源,并记录各区域的占用情况。" +concepts.resources.allocation.details: "对每个资源,使用创建时所需的缓冲区或纹理描述调用 {contextGetSizeAndAlignment}。按返回的大小预留空间,起始偏移量须为返回对齐值的整数倍,且整个区域位于堆内,不与其他仍有效的分配重叠。纹理可能包含后端特有的填充,因此不能仅根据像素数量和每像素字节数计算分配大小。" +concepts.resources.allocation.guidance: "放置在堆中的缓冲区必须使用与堆相同的驻留设置。纹理存储使用 GPU 专用堆。" +concepts.resources.allocation.title: "堆分配" +concepts.resources.bufferUsages.table.constant.role: "通过常量缓冲区绑定读取的着色器参数。" concepts.resources.bufferUsages.table.headings.role: "作用" -concepts.resources.bufferUsages.table.headings.usage: 用途 -concepts.resources.bufferUsages.table.index.role: 索引绘制所使用的索引。 +concepts.resources.bufferUsages.table.headings.usage: "用途" +concepts.resources.bufferUsages.table.index.role: "索引绘制所使用的索引。" concepts.resources.bufferUsages.table.indirect.role: "间接绘制或分派命令读取的参数。" concepts.resources.bufferUsages.table.none.role: "未声明任何缓冲区用途标志。" concepts.resources.bufferUsages.table.storageReadOnly.role: "通过只读着色器绑定访问的缓冲区数据。" concepts.resources.bufferUsages.table.storageReadWrite.role: "通过读写着色器绑定访问的缓冲区数据。" concepts.resources.bufferUsages.table.transferDst.role: "GPU 复制操作的目标存储。" concepts.resources.bufferUsages.table.transferSrc.role: "GPU 复制操作的源数据。" -concepts.resources.bufferUsages.table.vertex.role: 为绘制提取的顶点属性。 -concepts.resources.bufferUsages.title: 缓冲区用途 -concepts.resources.description: "根据将要使用资源的操作选择资源描述。如果一个纹理既要接收渲染结果,又要被着色器采样,还要回读到 CPU,就需要声明这三种用途,并处理这些操作之间的同步。内存放置位置和资源生命周期则是另外需要考虑的问题。" -concepts.resources.memory.context: 对于 CPU 可访问的缓冲区,{map} 为 CPU 提供内存地址。它不会等待 GPU 停止访问相同的字节。{unmap} 同样不会提交工作或等待完成。在覆盖 CPU 可写数据之前,请先完成仍需要其旧内容的 GPU 读取。 -concepts.resources.memory.description: "{bufferDesc} 具有 {residency} 字段。请根据 CPU 和 GPU 访问数据的方式进行选择:" -concepts.resources.memory.details: 内存驻留描述了 CPU 对所分配内存的预期访问方式。它并不意味着每个设备都具有物理分离的 CPU 和 GPU 内存。三角形示例使用 {cpuWriteOnly} 直接初始化较小的顶点缓冲区。大型静态网格则可以从单次上传的仅 GPU 存储中获益。 -concepts.resources.memory.guidance: "{textureDesc} 没有内存驻留字段。由图形上下文创建的常规纹理使用 GPU 存储。其公共 API 提供上传和回读操作来传输 CPU 数据,但不提供直接映射方法。显式堆提供内存放置控制,下文将介绍。" -concepts.resources.memory.table.cpuReadOnly.cPUAccess: "在 GPU 复制完成后读取映射的内存。" +concepts.resources.bufferUsages.table.vertex.role: "供绘制命令读取的顶点属性。" +concepts.resources.bufferUsages.title: "缓冲区用途" +concepts.resources.description: "资源描述规定应用程序如何使用其存储。例如,一张纹理若要作为渲染目标、供着色器采样,并将内容复制回 CPU,就需要声明这三种操作对应的用途。内存放置决定 CPU 的访问方式,同步与生命周期管理则决定何时可以访问数据或释放存储。" +concepts.resources.memory.context: "对于 CPU 可访问的缓冲区,{map} 提供 CPU 读写数据所用的地址。映射和 {unmap} 都不会等待 GPU 工作。CPU 读取 GPU 写入的结果前,应用程序须先等待写入完成;修改同一块内存前,也须等待 GPU 对这些字节的访问结束。" +concepts.resources.memory.description: "{bufferDesc} 的 {residency} 字段指定了 CPU 对分配内存的预期访问方式:" +concepts.resources.memory.details: "驻留设置表达 CPU 的访问需求,即使 CPU 与 GPU 共享物理内存也同样适用。三角形教程使用 {cpuWriteOnly} 直接初始化小型顶点缓冲区。对于较大的静态几何数据,上传到 GPU 专用存储可能更合适。" +concepts.resources.memory.guidance: "通过上下文直接创建的纹理使用 GPU 存储,因此 {textureDesc} 没有驻留字段。应用程序通过上传和回读,在纹理与 CPU 内存之间交换数据。" +concepts.resources.memory.table.cpuReadOnly.cPUAccess: "只读" concepts.resources.memory.table.cpuReadOnly.typicalRole: "GPU 生成的回读数据" -concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "在先前的 GPU 读取完成后写入映射的内存。" +concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "只写" concepts.resources.memory.table.cpuWriteOnly.typicalRole: "CPU 提供或更新的数据" -concepts.resources.memory.table.gpuOnly.cPUAccess: "通过上传缓冲区或回读缓冲区传输字节。" +concepts.resources.memory.table.gpuOnly.cPUAccess: "无" concepts.resources.memory.table.gpuOnly.typicalRole: "静态几何体和 GPU 工作数据" -concepts.resources.memory.table.headings.cPUAccess: CPU 访问 -concepts.resources.memory.table.headings.residency: 内存驻留 +concepts.resources.memory.table.headings.cPUAccess: "预期 CPU 访问" +concepts.resources.memory.table.headings.residency: "内存驻留" concepts.resources.memory.table.headings.typicalRole: "典型用途" -concepts.resources.memory.title: "根据所需的 CPU 访问方式选择内存" -concepts.resources.textureUsages.description: "传输用途标志描述 GPU 复制的方向。CPU 访问则是另一项内存放置选择,下文将介绍。" -concepts.resources.textureUsages.details: "组合用途标志只是声明多个作用,不会执行相应操作,也不会安排访问顺序。纹理仍然需要适当的{link},而且其格式必须在所选设备上支持请求的用途。" +concepts.resources.memory.title: "CPU 访问与内存放置" +concepts.resources.textureUsages.description: "传输标志声明资源在 GPU 复制中用作源还是目标。CPU 能否直接访问这块存储,则由内存放置方式决定。" +concepts.resources.textureUsages.details: "用途标志声明纹理可以承担的作用。在这些作用之间切换时,需要相应的{link};所选设备也必须支持以该纹理格式执行所声明的操作。" concepts.resources.textureUsages.details.link: "布局与同步" concepts.resources.textureUsages.table.colorAttachment.role: "渲染通道中的颜色附件。" concepts.resources.textureUsages.table.depthStencilAttachment.role: "渲染通道中的深度/模板附件。" concepts.resources.textureUsages.table.headings.role: "作用" -concepts.resources.textureUsages.table.headings.usage: 用途 +concepts.resources.textureUsages.table.headings.usage: "用途" concepts.resources.textureUsages.table.none.role: "未声明任何纹理用途标志。" concepts.resources.textureUsages.table.sampled.role: "通过采样纹理绑定读取的纹理数据。" concepts.resources.textureUsages.table.storage.role: "通过存储纹理绑定供着色器读取或写入的纹理数据。" concepts.resources.textureUsages.table.transferDst.role: "GPU 复制操作的目标图像存储。" concepts.resources.textureUsages.table.transferSrc.role: "GPU 复制操作的源图像数据。" -concepts.resources.textureUsages.title: 纹理用途 -concepts.resources.title: 资源管理 -concepts.resources.transfers.context: "回读操作会录制一条将 GPU 数据复制到内部回读存储的命令。当库重置已完成的命令缓冲区以供复用时,才会将这些字节复制到提供的 CPU 目标中。在该提交完成值的 {wait} 返回之前,目标内存必须保持已分配状态,托管内存也必须保持固定。" -concepts.resources.transfers.description: "上传将 CPU 数据复制到 GPU 资源,回读将资源数据复制回 CPU 内存。资源自身提供的方法会在返回前完成该次传输:" -concepts.resources.transfers.details: "这些等待只涵盖方法自身提交的传输。它们不会发现另一个队列上已有读写操作对该资源的依赖关系。调用资源自身的传输方法前,应先建立这些依赖。直接通过映射内存复制数据时,也需要调用方确保相关 GPU 工作已经完成。" -concepts.resources.transfers.guidance: 当复制操作需要与其他工作一起录制时,请使用 {commandBufferUpload} 或 {commandBufferDownload}。它们的指针生命周期有所不同: -concepts.resources.transfers.item: "上传会在调用期间将 CPU 源数据复制到内部上传缓冲区,也称暂存内存。源指针只需在该次调用期间保持有效。" -concepts.resources.transfers.notes: "对于纹理,行步幅是 CPU 数据相邻两行之间的字节距离,切片步幅是相邻深度切片之间的字节距离。它们并不代表纹理内部的 GPU 内存布局。有关工作完成与数据回读的区别,请参阅{link}。" -concepts.resources.transfers.notes.link: 同步 -concepts.resources.transfers.table.bufferDownload.transfer: 对 {cpuReadOnly} 进行直接 CPU 复制;否则在传输队列上提交下载并等待。 -concepts.resources.transfers.table.bufferUpload.transfer: 对 {cpuWriteOnly} 进行直接 CPU 复制;否则在传输队列上提交上传并等待。 -concepts.resources.transfers.table.headings.method: 方法 -concepts.resources.transfers.table.headings.transfer: "数据传输方式" +concepts.resources.textureUsages.title: "纹理用途" +concepts.resources.title: "资源管理" +concepts.resources.transfers.context: "回读先将 GPU 数据复制到内部回读存储。库回收已完成的命令缓冲区时,再将数据复制到指定的 CPU 目标。对本次回读提交的完成值调用 {wait},可以完成这两个步骤。在调用返回前,目标内存须保持已分配状态,托管内存须保持固定。" +concepts.resources.transfers.description: "上传将 CPU 数据复制到 GPU 资源,回读则将资源数据复制到 CPU 内存。缓冲区和纹理上的这些方法会在传输完成后返回:" +concepts.resources.transfers.details: "调用这些方法前,先处理与其他队列访问之间的冲突。方法内部的等待只覆盖其自身的传输,不会建立与其他队列的依赖。直接通过映射内存复制时,则完全由调用方负责等待存在冲突的 GPU 访问。" +concepts.resources.transfers.guidance: "要将传输与其他 GPU 工作一同提交,可通过 {commandBufferUpload} 或 {commandBufferDownload} 录制。上传源与回读目标的内存生命周期要求不同:" +concepts.resources.transfers.item: "上传调用期间,库会将源数据复制到内部的临时上传存储,即暂存内存。GPU 随后从这块存储读取,因此应用程序的源指针只需保持有效到调用返回。" +concepts.resources.transfers.notes: "纹理传输中的行步幅是 CPU 数据相邻两行之间的字节距离;切片步幅则是相邻深度切片之间的字节距离。传输操作根据这些值,在 CPU 数据与纹理的 GPU 存储之间复制内容。GPU 完成与数据送达回读目标为何是两个步骤,见{link}。" +concepts.resources.transfers.notes.link: "同步" +concepts.resources.transfers.table.bufferDownload.transfer: "对于 {cpuReadOnly},直接从映射内存复制;否则向传输队列提交回读,并等待完成。" +concepts.resources.transfers.table.bufferUpload.transfer: "对于 {cpuWriteOnly},直接复制到映射内存;否则向传输队列提交上传,并等待完成。" +concepts.resources.transfers.table.headings.method: "方法" +concepts.resources.transfers.table.headings.transfer: "传输行为" concepts.resources.transfers.table.textureTransfers.method: "{textureUpload} / {textureDownload}" -concepts.resources.transfers.table.textureTransfers.transfer: "使用图形队列,将所选子资源转换为复制所需的布局,完成复制后转换为请求的最终布局,并等待传输完成。" -concepts.resources.transfers.title: "选择立即完成的传输或随命令录制的传输" -concepts.resources.usages.description: "{bufferUsages} 和 {textureUsages} 是声明资源预期角色的标志枚举。它们分别分配给 {bufferDescUsages} 和 {textureDescUsages}。当资源具有多个角色时,标志枚举允许使用 {value} 组合多个成员。" -concepts.resources.usages.title: 在创建资源之前声明所需的用途 -concepts.resources.views.description: "{bufferView} 描述缓冲区区域及其解释方式。{textureView} 选择兼容的纹理类型、格式和子资源范围。视图共享底层存储,不会复制数据,也不会添加创建资源时遗漏的用途。指定视图范围也不意味着各后端都会进行着色器边界检查。" -concepts.resources.views.details: "默认视图可以直接使用资源自身的句柄;如果需要不同区域或兼容的解释方式,则创建视图。在 GPU 工作可能使用视图及其底层资源期间,应保留二者的 C# 引用;仅有资源句柄并不能保持任一对象存活。只有在最后一次 GPU 使用完成后才能释放它们。替换其中任一对象后,还应更新包含其旧{link}的常量。" +concepts.resources.transfers.table.textureTransfers.transfer: "将复制及其纹理转换提交到图形队列,并等待完成。操作结束后,所选子资源处于指定的最终布局。" +concepts.resources.transfers.title: "立即传输与命令录制" +concepts.resources.usages.description: "{bufferUsages} 和 {textureUsages} 是用于声明资源用途的标志枚举,分别设置在 {bufferDescUsages} 和 {textureDescUsages} 中。资源需要承担多种用途时,可通过 {value} 组合相应成员。" +concepts.resources.usages.title: "资源用途" +concepts.resources.views.description: "{bufferView} 描述缓冲区的一块区域及其数据解释方式。{textureView} 选择子资源范围,以及兼容的纹理类型和格式。二者都引用已有存储,并遵循创建该存储时声明的用途。视图范围用于描述访问范围,各后端并不因此提供一致的着色器边界检查。" +concepts.resources.views.details: "资源自身的句柄提供默认视图。需要其他区域或兼容的解释方式时,再创建独立视图。视图及其底层资源都必须保留到 GPU 使用结束;仅持有资源句柄不能使任一对象保持存活。替换其中任一对象时,还须更新包含旧{link}的常量。" concepts.resources.views.details.link: "资源句柄" -concepts.resources.views.guidance: "{link}展示了在调整大小时替换深度纹理。{detail}展示了输入纹理与其可写输出保持分离。两者都让资源的生命周期跟随实际使用它的工作。" -concepts.resources.views.guidance.detail: 计算示例 -concepts.resources.views.guidance.link: 旋转立方体渲染器 -concepts.resources.views.title: "让视图及其底层资源在使用期间保持有效" -concepts.shaders.binding.context: 在计算示例中,{input} 填充为 {inputTextureSampledHandle},{output} 填充为 {outputTextureStorageHandle}。Slang 的类型化 {descriptorHandle} 告知着色器如何访问每个资源: -concepts.shaders.binding.description: "{setConstantBuffer} 为当前管线的常量数据绑定缓冲区和字节偏移量。它绑定现有的 GPU 可见存储;它不会上传 C# 值。请先填充缓冲区,并确保先前的 GPU 读取操作已完成,然后再覆盖其字节。" -concepts.shaders.binding.details: 在设置常量缓冲区之前先设置管线。对于已创建并上传资源的计算工作负载,录制使用以下顺序: -concepts.shaders.binding.guidance: 此代码片段假定存在正在录制的 {commandBuffer}、{computePipeline}、具有 {bufferUsagesConstant} 用途的已上传 {constantBuffer},以及工作负载的线程组计数。偏移量 0 绑定缓冲区的起始位置。如果多个常量数据记录共享一个缓冲区,则每个记录的起始偏移量必须满足后端的绑定对齐要求。该要求与记录内部的字段布局相互独立。 -concepts.shaders.binding.notes: "{resourceHandle} 存储两个 32 位字段,但其解释归后端所有。不要将其视为可在上下文之间转移的通用描述符索引、地址或值。句柄不会创建资源,不会添加缺失的用途,也不会执行同步。" -concepts.shaders.binding.reference: 保留对资源及用于获取其句柄的任何视图的引用,并在着色器的最后一次使用完成后再释放它们。在替换纹理或视图时,更新包含其旧句柄的常量。{link}解释了这种生命周期关系。 -concepts.shaders.binding.reference.link: 资源管理 -concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: 读取着色器类型 {t} 的结构化元素。 -concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: 读取或写入着色器类型 {t} 的结构化元素。 -concepts.shaders.binding.table.headings.access: 预期访问 +concepts.resources.views.title: "视图与底层资源" +concepts.shaders.binding.context: "计算示例将 {inputTextureSampledHandle} 写入 {input},将 {outputTextureStorageHandle} 写入 {output}。在 Slang 中,{descriptorHandle} 的类型参数规定了着色器访问资源的方式:" +concepts.shaders.binding.description: "{setConstantBuffer} 选择已有缓冲区及字节偏移量,当前管线从该位置读取常量。着色器使用这些参数前,先将数据上传到相应存储。如果此前提交的 GPU 工作仍在读取同一批字节,须等待该工作完成后再更新。" +concepts.shaders.binding.details: "准备好命令缓冲区、计算管线、已填入数据的常量缓冲区和线程组数量后,按以下顺序录制分派。常量缓冲区的绑定作用于当前管线,因此必须先选择管线:" +concepts.shaders.binding.guidance: "这里,{commandBuffer} 使用 {computePipeline} 及 {constantBuffer} 中的参数录制分派。缓冲区需要声明 {bufferUsagesConstant} 用途,偏移量 0 选择其起始位置。如果多条常量记录共用缓冲区,每条记录的起始偏移量还须满足后端绑定的对齐要求,这与记录内部的字段布局是两项独立要求。" +concepts.shaders.binding.notes: "{resourceHandle} 包含两个 32 位字段,含义由后端解释,其值仅在创建资源的上下文中有效。" +concepts.shaders.binding.reference: "保留资源及用于获取句柄的视图,直到着色器完成最后一次访问。替换纹理或视图后,应更新仍含旧句柄的常量。相关所有权规则见{link}。" +concepts.shaders.binding.reference.link: "资源管理" +concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: "读取着色器类型 {t} 的结构化元素" +concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: "读写着色器类型 {t} 的结构化元素" +concepts.shaders.binding.table.headings.access: "预期访问" concepts.shaders.binding.table.headings.cHandle: "C# 句柄" -concepts.shaders.binding.table.headings.slangFieldType: Slang 字段类型 -concepts.shaders.binding.table.samplerHandle.access: 提供纹理采样状态。 -concepts.shaders.binding.table.textureSampledHandle.access: 读取纹理。 -concepts.shaders.binding.table.textureStorageHandle.access: 读取或写入存储纹理。 -concepts.shaders.binding.title: 绑定常量缓冲区及其描述的资源 -concepts.shaders.compilation.description: "{zenithCompiler} 编译具名的 Slang 入口点并返回 {shaderDesc}。使用上下文的 {graphicsApi},以便编译结果针对将创建着色器的后端:针对 DirectX 12 的 DXIL、针对 Metal 的 Metal 库,或针对 Vulkan 的 SPIR-V。" -concepts.shaders.compilation.details: 例如,在已有 {context} 且三角形着色器已复制到可执行文件旁的情况下: -concepts.shaders.compilation.guidance: "{vSMain} 必须与着色器文件中的入口点名称完全匹配。在创建管线期间保持着色器对象有效,然后在管线创建完成后将其释放,如{link}所示。执行一次此初始化,而不是在每帧中重新编译。" -concepts.shaders.compilation.guidance.link: 第一个三角形 -concepts.shaders.compilation.title: 为所选上下文编译入口点 -concepts.shaders.description: "着色器接收由应用程序提供的数据。顶点属性描述单个顶点;缓冲区保存参数或数组;资源句柄标识着色器将访问的其他资源。C# 声明与 Slang 声明必须在这些值的含义上达成一致。仅仅匹配字段名是不够的:内存布局、资源访问和绑定方式都必须匹配。" -concepts.shaders.dispatch.description: "{dispatch} 接收线程组的数量。计算示例的 {numthreads} 入口点每组运行 16 × 16 个线程。将图像尺寸除以 16 并向上取整以求得组数。例如,17 × 19 的图像需要 2 × 2 组。着色器会根据图像尺寸检查其像素坐标,因为最后一组可能包含位于图像外部的线程。" -concepts.shaders.dispatch.details: 编译器将入口点声明的组大小保存在 {shaderDescThreadGroupSize} 中;它不会将提供给 {dispatch} 的像素尺寸自动转换为组数。完整的绑定和分派示例请结合使用 {computeShaderRendererCs} 及其着色器,并在另一个通道消费输出之前参阅{link}。 -concepts.shaders.dispatch.details.link: 同步 -concepts.shaders.dispatch.title: 分派线程组,而非像素 -concepts.shaders.layout.context: "{link}显式指定了它们的偏移量。此声明的作用域需要 {systemRuntimeInteropServices} 和 {zenithNET}:" +concepts.shaders.binding.table.headings.slangFieldType: "Slang 字段类型" +concepts.shaders.binding.table.samplerHandle.access: "纹理采样状态" +concepts.shaders.binding.table.textureSampledHandle.access: "纹理读取" +concepts.shaders.binding.table.textureStorageHandle.access: "存储纹理的读写" +concepts.shaders.binding.title: "常量缓冲区与资源句柄" +concepts.shaders.compilation.description: "{zenithCompiler} 将指定的 Slang 入口点编译为 {shaderDesc}。上下文的 {graphicsApi} 决定目标格式:DirectX 12 使用 DXIL,Metal 使用 Metal 库,Vulkan 使用 SPIR-V。" +concepts.shaders.compilation.details: "创建名为 {context} 的图形上下文后,可以编译已复制到可执行文件所在目录的三角形着色器:" +concepts.shaders.compilation.guidance: "入口点名称 {vSMain} 必须与着色器文件中的函数声明一致。在初始化阶段编译着色器并创建管线,渲染期间复用管线。管线创建完成后即可释放着色器对象,具体见{link}。" +concepts.shaders.compilation.guidance.link: "第一个三角形" +concepts.shaders.compilation.title: "着色器编译" +concepts.shaders.description: "C# 与 Slang 声明必须约定一致的数据位置和访问方式。顶点输入布局描述顶点属性,着色器缓冲区声明描述参数与数组,资源句柄则标识着色器使用的资源。" +concepts.shaders.dispatch.description: "{dispatch} 指定执行多少个线程组。计算示例声明 {numthreads},每组因此包含 16 × 16 个线程。将图像的宽和高分别除以 16 并向上取整,即可覆盖整张图像:17 × 19 的图像需要 2 × 2 组。着色器检查每个线程的坐标,并跳过位于图像范围以外的线程。" +concepts.shaders.dispatch.details: "{shaderDescThreadGroupSize} 提供声明的组大小,可用于计算传给 {dispatch} 的线程组数量。完整计算过程见 {computeShaderRendererCs}。分派完成后,访问输出图像时还须满足{link}中说明的要求。" +concepts.shaders.dispatch.details.link: "同步" +concepts.shaders.dispatch.title: "线程组" +concepts.shaders.layout.context: "{link}通过图像尺寸与两个纹理句柄展示了这种排列。各字段的起始位置由显式偏移量指定。以下声明使用 {systemRuntimeInteropServices} 和 {zenithNET} 命名空间:" concepts.shaders.layout.context.link: "计算示例的 C# 常量" -concepts.shaders.layout.description: "对于顶点输入,管线的 {inputLayout} 描述了格式、偏移量、步幅和语义。三角形的 {float3} 位置后跟 {float4} 颜色占用 28 字节,颜色位于字节 12 处。{inputLayoutAdd} 计算这个紧凑布局;它不会检查 C# 结构体。如果 C# 字段包含填充,请提供匹配的布局,而不要假定字段是紧凑排列的。" -concepts.shaders.layout.details: "常量缓冲区保存着色器参数,而结构化缓冲区保存声明类型的元素数组。两者都根据其 Slang 声明进行读取。它们不使用 {inputLayout}。请核实编译后着色器表示形式的字段偏移量和元素大小(包括填充)。非托管 C# 类型适合按字节复制,但这本身并不能证明它与着色器类型匹配。特别是,不要将顶点的紧凑 {float3} 布局应用于每个着色器缓冲区。" -concepts.shaders.layout.guidance: 资源句柄是引用现有资源的一个较小数值。将句柄复制到常量缓冲区中并不会复制该资源的内容。 -concepts.shaders.layout.notes: "{computeShaderSlang} 中的相应声明为:" -concepts.shaders.layout.reference: "尺寸占用前 8 个字节,后跟两个 8 字节的资源句柄。C# 示例总共保留了 256 字节。该大小是示例选择的存储大小,并非所有 Slang 结构体或常量有效负载都占用 256 字节的规则。填充总大小也不会修正处于错误偏移量处的字段。" -concepts.shaders.layout.title: 顶点输入与着色器数据具有不同的布局规则 -concepts.shaders.matrices.description: 编译器请求行优先(row-major)矩阵存储,该存储将每行的元素保存在一起。{link}将三个 {matrix4x4} 值放置在偏移量 0、64 和 128 处。其{detail}按模型、视图和投影的顺序使用 {mulVectorMatrix}。 -concepts.shaders.matrices.description.detail: 着色器 -concepts.shaders.matrices.description.link: 旋转立方体渲染器 -concepts.shaders.matrices.details: 存储顺序决定了矩阵元素如何占用内存;乘法顺序决定了变换。请保持两端一致。在不检查这两个选择的情况下添加转置可能会掩盖一个不匹配,同时引入另一个不匹配。 -concepts.shaders.matrices.title: 保持矩阵存储与乘法顺序一致 -concepts.shaders.title: 着色器数据与绑定 -concepts.synchronization.backends.description: DirectX 12 和 Vulkan 对带有布局和访问信息的纹理转换进行编码。Metal 在 Zenith.NET 的 {transition} 实现中没有对应的显式操作。Metal 将录制的工作分组到渲染和计算编码器中。后端在结束这些组时插入可见性屏障,使先前的写入可供后续工作使用。显式的 {barrier} 调用处理诸如同一个编码器内连续计算分派等依赖关系。 -concepts.synchronization.backends.details: 在更改工作负载时,这种区别非常重要。在{link}中,分派之后是图形渲染通道,这在 Metal 上也会创建编码器边界。仅仅更改纹理声明的布局并不能为两个依赖的计算分派创建该边界。保持共享 API 所需的转换,并单独识别实际生产命令与消费命令之间的依赖关系。 -concepts.synchronization.backends.details.link: 计算示例 -concepts.synchronization.backends.title: 布局转换在每个后端上并非完全相同 -concepts.synchronization.barriers.context: "{barrierStagesAll} 是一个更宽的范围,而不是自动依赖项检测器。请选择实际覆盖该工作的阶段,并且仅在支持这些操作的队列上使用它们。" -concepts.synchronization.barriers.description: 考虑两个计算分派:第一个写入模拟数据,第二个读取该数据以执行下一步。两者都使用存储缓冲区,因此没有需要更改的纹理布局。在命令缓冲区中的两次分派之间插入以下内容: -concepts.synchronization.barriers.details: 第一个参数标识生产者阶段,第二个参数标识消费者阶段。屏障在 GPU 上建立对应的执行和内存依赖关系。后端将这些阶段转换为其执行和内存访问规则。该屏障不会更改纹理的布局,也不会等待设备上的所有工作。 -concepts.synchronization.barriers.guidance: "{link}在依赖的分派之间使用了这种模式。在发生依赖关系的地方放置屏障。在消费者已经录制之后放置屏障,无法将该消费者排在较早的生产者之后。" -concepts.synchronization.barriers.guidance.link: FluidTank 模拟 -concepts.synchronization.barriers.title: 使用屏障对有依赖关系的命令进行排序 -concepts.synchronization.dependencies.description: 对于每个共享资源,确定首先访问它的操作、随后的操作,以及是否有任一访问执行写入。两次读取相同的数据不需要进行排序以保护其内容,尽管布局更改或呈现可能会施加其他要求。写后读、读后覆写或两次写入可能都需要建立依赖关系。 -concepts.synchronization.dependencies.details: 然后根据这些操作执行的位置选择对应的机制: -concepts.synchronization.dependencies.guidance: 这些机制彼此相关,但不可互换。按顺序提交命令并不能取代所有的内存依赖。队列等待不会声明新的纹理布局,命令屏障也不会等待调用方的 CPU 线程。 -concepts.synchronization.dependencies.table.cpuAccess.mechanism: 对相关的完成值调用 {wait}。 -concepts.synchronization.dependencies.table.cpuAccess.situation: CPU 在访问或释放数据之前必须等待 -concepts.synchronization.dependencies.table.crossQueue.mechanism: 将其 {timelineValue} 传递给消费方命令缓冲区的 {submit}。 -concepts.synchronization.dependencies.table.crossQueue.situation: 另一个队列上的提交操作生成了数据 -concepts.synchronization.dependencies.table.headings.mechanism: 机制 -concepts.synchronization.dependencies.table.headings.situation: 情况 -concepts.synchronization.dependencies.table.layoutChange.mechanism: 带有先前和后续布局的 {commandBufferTransition}。 -concepts.synchronization.dependencies.table.layoutChange.situation: 纹理子资源更改其使用方式 -concepts.synchronization.dependencies.table.pipelineStages.mechanism: 带有生产者和消费者阶段的 {commandBufferBarrier}。 -concepts.synchronization.dependencies.table.pipelineStages.situation: 命令流中存在依赖关系的 GPU 阶段 -concepts.synchronization.dependencies.title: 从生产者和消费者开始分析 -concepts.synchronization.description: 读取先前命令写入数据的命令,依赖于这些写入操作已完成且对其可见。写入方是生产者(producer);读取方是消费者(consumer)。CPU 在读取、覆写或释放共享数据之前也需要一个完成点。Zenith.NET 针对这些不同的依赖关系提供了屏障、纹理布局转换和时间线。 -concepts.synchronization.layouts.context: "{undefined} 意味着不需要保留以前的内容。它适用于新图像或将被完全清除的附件。它不能用作避免跟踪需要加载、采样或累积内容的图像布局的手段。" -concepts.synchronization.layouts.description: 用途标志描述了纹理支持哪些角色。{textureLayout} 描述了某个特定操作将如何访问特定子资源。子资源是选定的 mip 级别和数组层。更改其布局是为此类访问做准备;它不会将纹理转换为不同的像素格式。例如,计算示例在 {storage} 布局中写入输出纹理,然后在图形通道中对其进行采样。在这些使用之间,它录制了: -concepts.synchronization.layouts.details: 此代码片段假定 {outputTexture} 是使用 {sampledStorage} 用途创建的,并且其选定的子资源处于 {storage} 布局中。{default} 选择 mip 级别 0 和数组层 0。该操作不会转换纹理的每个 mip 或层。 -concepts.synchronization.layouts.guidance: 应用程序提供先前的布局。{transition} 不会维护应用程序可见的布局跟踪器,也不会从较早的命令推断该值。只要资源在渲染阶段之间传递,就应该显式跟踪布局。 -concepts.synchronization.layouts.title: 跟踪每个纹理子资源的布局 -concepts.synchronization.readback.description: "{isCompleted} 仅查询 GPU 时间线是否已达到某个值。它本身不会回收命令缓冲区,也不会将暂存的回读数据复制到应用程序的目标指针所指向的内存中。" -concepts.synchronization.readback.details: "{commandBufferDownload} 首先录制将数据复制到内部回读存储的命令。重置已完成的命令缓冲区以供复用时,才会由 CPU 将数据复制到提供的指针所指向的内存。在该次回读提交的 {wait} 返回之前,目标内存必须保持有效,托管内存必须保持固定;返回后才能读取数据或释放内存。等待另一个队列上的后续提交,本身不会轮询回读操作所属的队列。" -concepts.synchronization.readback.guidance: "因此,仅轮询 {isCompleted} 然后立即读取异步回读的目标内存是不够的。{link}介绍了直接复制与通过暂存内存传输的路径。" -concepts.synchronization.readback.guidance.link: 资源管理 -concepts.synchronization.readback.title: GPU 完成与 CPU 下载数据是不同的步骤 -concepts.synchronization.reuse.description: 对于第一个渲染器,在每帧之后立即等待是最直观的做法。要实现重叠工作,请为未决帧分配单独的可变数据,并保留每个帧最终用途的完成值。在更新常量缓冲区、替换纹理或释放管线之前,请完成对受影响资源的所有未决访问。 -concepts.synchronization.reuse.details: 在调整大小或关闭时,在等待旧工作之前先停止新用途。{swapChainResize}、资源释放和上下文释放不能用作应用程序工作的通用等待机制。三角形示例可以在回调之间安全地调整大小,因为每个先前的帧都已经完成了其提交操作。 -concepts.synchronization.reuse.guidance: 当前的 {swapChainPresent} 在其呈现操作之后也会在图形队列上发出信号并等待。因此,仅仅移除三角形显式的提交等待并不能自动建立起重叠的呈现循环。在图形队列上的等待对于仍在另一个队列上运行的独立工作也不起作用。 -concepts.synchronization.reuse.title: 仅在最后一次访问完成后重用数据 -concepts.synchronization.timelines.context: 在 CPU 读取、覆写或释放这些资源之前,请等待其最终使用: -concepts.synchronization.timelines.description: 时间线使用递增的值跟踪队列上的完成进度。{submit} 返回包含该时间线和与提交关联的值的 {timelineValue}。来自不同时间线的完成值不能仅通过其数字 {value} 字段进行比较。 -concepts.synchronization.timelines.details: 假设 {producer} 和 {consumer} 是来自同一上下文的两个队列中已录制的命令缓冲区。生产者写入消费者使用的数据。像这样提交它们: -concepts.synchronization.timelines.guidance: 传递生成的值会使消费队列在 GPU 上等待该值。CPU 在此处不调用 {producedWait}。在 {consumed} 完成之前保持共享资源有效,并录制消费者所需的任何纹理布局更改。 -concepts.synchronization.timelines.notes: "{wait} 等待该时间线值,然后检查其所属队列中已完成的提交。完成的命令缓冲区会被重置以供复用,其中暂存的回读数据会复制到提供的 CPU 目标中。{queueTimelineSignal} 也可以在已提交到该队列的工作之后排入一个完成点。调用 {signal} 不代表 GPU 已经到达该点。" -concepts.synchronization.timelines.title: 使用时间线进行完成通知与队列交接 -concepts.synchronization.title: 同步 -home.actions.reference: 浏览 API -home.actions.tutorial: 从三角形开始 -home.entries.description: 第一帧画面。针对性的示例。深入了解 API。 -home.entries.label: 浏览文档 -home.entries.reference.action: 探索 API -home.entries.reference.category: 参考 -home.entries.reference.description: 查找支撑您应用程序的类型、签名与成员。 -home.entries.reference.title: API 参考 -home.entries.samples.action: 浏览示例 -home.entries.samples.category: 示例 -home.entries.samples.description: 通过源代码探索针对性的渲染与计算技术。 -home.entries.samples.title: 示例 -home.entries.title: 开始构建。 -home.entries.tutorial.action: 开始教程 -home.entries.tutorial.category: 教程 -home.entries.tutorial.description: 从项目搭建到第一帧画面,构建一个完整的渲染应用程序。 -home.entries.tutorial.title: 第一个三角形 -home.introduction.accent: "基于 C#。" -home.introduction.description: 通过单一的 .NET API 创建资源、录制命令并提交图形或计算工作。 -home.introduction.title: 构建您的渲染器。 -home.meta.description: "一套统一的 C# API,跨越 DirectX、Metal 与 Vulkan 提供图形与计算能力。" -home.scene.description: 旋转几何体研究。拖动或使用方向键调整视角。 -home.scene.label: 几何体显示 -home.scene.surface: 表面 -home.scene.wireframe: 线框 -home.title: 适用于 .NET 的现代 RHI -learning.concepts.description: 在组合渲染通道之前,了解命令、资源、着色器数据和同步是如何相互配合的。 -learning.concepts.execution.description: 录制 GPU 工作,提交该工作,并保持其资源处于有效状态。 -learning.concepts.platforms.description: 连接原生窗口或 UI 渲染控件。 -learning.concepts.resources.description: 选择资源用途、内存分配位置和视图。 -learning.concepts.shaders.description: "使 C# 内存布局与资源句柄同 Slang 保持一致。" -learning.concepts.synchronization.description: 对有依赖关系的访问进行排序,并掌握工作完成的时间点。 -learning.concepts.title: 核心概念 -learning.description: 从完整的三角形教程开始。然后利用针对性的示例和概念指南,理解更大型渲染器背后的资源、数据与依赖关系。 -learning.entries.samples.action: 浏览示例 -learning.entries.samples.description: "查找涵盖几何体、计算、光线查询与网格着色(mesh shading)的 C# 和 Slang 示例。" -learning.entries.tutorial.action: 打开教程 -learning.entries.tutorial.description: 创建控制台应用程序,打开窗口并绘制一个三角形。 -learning.meta.description: 开始使用 Zenith.NET 并探索其编程模型。 -learning.title: 学习 -reference.description: 查询资源类型、命令签名和平台集成。 -reference.entries.commands.description: 录制图形、计算和传输命令。 -reference.entries.commands.label: 录制工作 -reference.entries.context.description: 为所选后端创建 GPU 资源。 -reference.entries.context.label: 从这里开始 -reference.meta.description: 探索 Zenith.NET 中的类型与成员。 -reference.navigation.core: 浏览核心 API。 -reference.title: API 参考 -samples.computeShader.description: 通过计算分派将图像转换为灰度并显示结果纹理。演示了用于采样输入纹理和可写输出纹理的资源句柄、向上取整的线程组计数以及着色器内部的边界检查。请保留包含的 {assetsTexturesShokoPng} 资产;渲染器对其处理一次并在后续帧中呈现结果。 +concepts.shaders.layout.description: "对于顶点输入,{inputLayout} 描述各属性的格式、偏移量和语义,以及相邻顶点之间的步幅。三角形先存放 {float3} 位置,再存放 {float4} 颜色:颜色的字节偏移量为 12,每个顶点占 28 字节。{inputLayoutAdd} 根据元素格式计算这一紧密排列的布局。如果 C# 结构体包含填充,就需要在偏移量和步幅中计入这些空间。" +concepts.shaders.layout.details: "常量缓冲区存放着色器参数,结构化缓冲区存放指定类型的元素数组。它们的布局由 Slang 声明决定,不使用 {inputLayout}。C# 字段偏移量、元素大小和填充必须与编译后的着色器布局一致。即使某个 C# 类型是非托管类型,可以直接按字节复制,其内存排列也未必符合着色器要求;例如,顶点中紧密排列的 {float3},在着色器缓冲区中可能需要不同的对齐方式。" +concepts.shaders.layout.guidance: "着色器参数除了普通数值,也可以包含资源句柄。句柄标识的是已有存储,因此将句柄复制到常量缓冲区并不会复制资源内容。" +concepts.shaders.layout.notes: "{computeShaderSlang} 中对应的声明为:" +concepts.shaders.layout.reference: "两个尺寸值占用前 8 字节,后面是两个各占 8 字节的句柄。C# 示例为整条记录预留 256 字节。其他记录的大小应根据各自字段以及所需的布局和对齐方式确定。" +concepts.shaders.layout.title: "数据布局" +concepts.shaders.matrices.description: "编译器采用行优先的矩阵存储方式,使同一行的元素连续排列。{link}在偏移量 0、64 和 128 处保存三个 {matrix4x4} 值,其{detail}按模型、视图和投影顺序执行 {mulVectorMatrix}。" +concepts.shaders.matrices.description.detail: "着色器" +concepts.shaders.matrices.description.link: "旋转立方体渲染器" +concepts.shaders.matrices.details: "存储顺序决定矩阵元素在内存中的排列,乘法顺序决定变换。C# 与 Slang 应采用相互匹配的约定。" +concepts.shaders.matrices.title: "矩阵约定" +concepts.shaders.title: "着色器数据与绑定" +concepts.synchronization.backends.description: "DirectX 12 和 Vulkan 将纹理转换记录为布局与访问状态的变化。在 Zenith.NET 的 Metal 后端中,{transition} 没有对应的 GPU 操作。Metal 后端将命令组织为渲染与计算编码器,并在编码器结束时插入可见性屏障。同一编码器内存在依赖的操作,例如连续的计算分派,通过显式调用 {barrier} 协调。" +concepts.synchronization.backends.details: "{link}开始图形渲染通道时,会结束计算编码器,使计算输出对后续图形工作可见。连续两次计算分派仍位于同一编码器内,即使中间录制了纹理转换,也需要屏障来处理依赖。因此,可跨后端使用的命令序列既要考虑纹理布局,也要处理访问之间的依赖。" +concepts.synchronization.backends.details.link: "计算示例" +concepts.synchronization.backends.title: "后端行为" +concepts.synchronization.barriers.context: "选择包含相关访问、且受到当前队列支持的阶段。{barrierStagesAll} 涵盖所有受支持的阶段;若依赖只涉及其中一部分,可选择更小的范围。" +concepts.synchronization.barriers.description: "假设同一个命令缓冲区内有两次计算分派,第一次写入模拟数据,第二次读取这些数据。在两次分派之间设置屏障,让第二次分派读到已经完成的写入结果。对于存储缓冲区,这样即可安排访问顺序,无须进行纹理布局转换:" +concepts.synchronization.barriers.details: "第一个参数指定产生数据的阶段,第二个参数指定使用数据的阶段。二者共同描述两次分派之间所需的执行顺序和内存可见性。" +concepts.synchronization.barriers.guidance: "{link}在模拟步骤之间采用这一方式。每道屏障都位于产生数据的分派之后、使用数据的分派之前。" +concepts.synchronization.barriers.guidance.link: "FluidTank 模拟" +concepts.synchronization.barriers.title: "管线屏障" +concepts.synchronization.dependencies.description: "逐个资源确认哪些访问涉及同一份数据。只要其中存在写入,就必须维持所需的先后顺序。两次读取本身没有冲突,但仍需满足纹理布局和呈现要求。CPU 更新数据或释放资源前,也须等待 GPU 完成对相应存储的使用。" +concepts.synchronization.dependencies.details: "应根据操作执行的位置选择机制:" +concepts.synchronization.dependencies.guidance: "一项工作可能同时需要多种同步机制。例如,纹理由另一队列生成时,除了提交依赖,还需为下一次使用设置正确的布局。这两项操作本身都不需要阻塞 CPU;只有 CPU 要访问或释放相关数据时,才需要在 CPU 端等待。" +concepts.synchronization.dependencies.table.cpuAccess.mechanism: "对相关的完成值调用 {wait}。" +concepts.synchronization.dependencies.table.cpuAccess.situation: "CPU 访问或资源释放需要等待 GPU 完成" +concepts.synchronization.dependencies.table.crossQueue.mechanism: "将生产者的 {timelineValue} 传给消费者的 {submit}。" +concepts.synchronization.dependencies.table.crossQueue.situation: "一个队列使用另一个队列生成的数据" +concepts.synchronization.dependencies.table.headings.mechanism: "机制" +concepts.synchronization.dependencies.table.headings.situation: "情况" +concepts.synchronization.dependencies.table.layoutChange.mechanism: "调用 {commandBufferTransition},指定先前布局与目标布局。" +concepts.synchronization.dependencies.table.layoutChange.situation: "纹理子资源更改其使用方式" +concepts.synchronization.dependencies.table.pipelineStages.mechanism: "调用 {commandBufferBarrier},指定产生数据和使用数据的阶段。" +concepts.synchronization.dependencies.table.pipelineStages.situation: "命令流中存在依赖关系的 GPU 阶段" +concepts.synchronization.dependencies.title: "访问依赖" +concepts.synchronization.description: "同步确定多个操作访问共享数据的顺序,并确保后续操作能够读到所需结果。在写后读依赖中,写入方称为生产者,读取方称为消费者。屏障与纹理转换协调 GPU 访问;时间线连接不同提交,并让 CPU 等待 GPU 工作完成。" +concepts.synchronization.layouts.context: "现有内容可以丢弃时,可将先前布局设为 {undefined},例如新建图像或即将完整清除的附件。若要保留内容以供加载、采样或累积,则应使用此前访问时的布局。" +concepts.synchronization.layouts.description: "纹理的用途标志声明允许的作用。{textureLayout} 描述命令序列中某一时刻对子资源的访问方式,子资源由 mip 级别和数组层确定。访问方式发生变化时,需要录制转换。例如,计算示例在 {storage} 布局中写入输出纹理,再为图形通道中的采样做准备:" +concepts.synchronization.layouts.details: "这里的 {outputTexture} 已声明 {sampledStorage} 用途,所选子资源处于 {storage} 布局。{default} 选择 mip 级别 0 和数组层 0,其他级别和层不受这次转换影响。" +concepts.synchronization.layouts.guidance: "调用 {transition} 时,提供子资源上一次使用的布局。应用程序在录制命令,以及在渲染阶段之间传递纹理时,负责跟踪这个状态。" +concepts.synchronization.layouts.title: "纹理布局" +concepts.synchronization.readback.description: "{isCompleted} 报告 GPU 的完成状态。通过命令录制的回读还需要一个步骤:将结果从内部回读存储复制到应用程序的目标内存。" +concepts.synchronization.readback.details: "{commandBufferDownload} 录制向内部回读存储复制数据的 GPU 命令。提交完成后,库在回收命令缓冲区时执行最后的 CPU 复制。对本次回读提交的完成值调用 {wait},会等待 GPU 完成,并处理该队列已完成的缓冲区,从而完成这两个步骤。调用返回前,目标内存须保持已分配状态,托管内存须保持固定。" +concepts.synchronization.readback.guidance: "仅轮询 {isCompleted} 不会执行最后的 CPU 复制;等待其他队列,也不会回收回读队列中已完成的缓冲区。上传和回读在何时使用直接内存访问或暂存存储,见{link}。" +concepts.synchronization.readback.guidance.link: "资源管理" +concepts.synchronization.readback.title: "回读完成" +concepts.synchronization.reuse.description: "三角形教程在每帧完成后才复用数据。若要让帧重叠执行,应为每个尚未完成的帧准备独立的可变存储,并跟踪何时可以再次使用。修改数据前,须等待 GPU 完成对相关字节的访问;释放资源前,则须等待它的所有使用结束。" +concepts.synchronization.reuse.details: "调整大小与关闭程序遵循相同的顺序:先停止新的资源访问,等待已有访问结束,再替换或释放资源。调用 {swapChainResize} 或释放资源、上下文前,须先完成上述等待。三角形教程已经逐帧等待,因此可以在回调之间调整大小。" +concepts.synchronization.reuse.guidance: "{swapChainPresent} 在呈现后向图形队列发出信号并等待。因此,即使去掉显式的提交等待,三角形教程仍会在呈现时等待。独立提交到其他队列的工作,则需要单独跟踪其完成状态。" +concepts.synchronization.reuse.title: "资源复用" +concepts.synchronization.timelines.context: "CPU 若要在消费者完成后读取结果、覆盖共享数据或释放资源,须先等待这次提交完成:" +concepts.synchronization.timelines.description: "时间线用递增值标识队列进度。{submit} 返回的 {timelineValue} 同时包含时间线和本次提交的值。不同时间线上的 {value} 数值不能直接比较。" +concepts.synchronization.timelines.details: "设 {producer} 和 {consumer} 是同一上下文中两个队列上已录制的命令缓冲区,后者使用前者写入的数据。提交时传入这项依赖:" +concepts.synchronization.timelines.guidance: "消费者所在的队列会先等待传入的完成值,再执行命令。CPU 无需调用 {producedWait},可以继续处理其他工作。共享资源须保留到 {consumed} 完成,同时仍需录制消费者访问所要求的纹理转换。" +concepts.synchronization.timelines.notes: "{queueTimelineSignal} 返回的值同样可以通过 {wait} 等待,也可以作为另一个队列的依赖。{signal} 将完成点排在此前已提交的工作之后,GPU 完成这些工作后便会到达该点。" +concepts.synchronization.timelines.title: "时间线与队列依赖" +concepts.synchronization.title: "同步" +home.actions.reference: "浏览 API" +home.actions.tutorial: "从三角形开始" +home.entries.description: "教程、示例与 API 参考" +home.entries.label: "文档分类" +home.entries.reference.action: "探索 API" +home.entries.reference.category: "参考" +home.entries.reference.description: "查阅 API 类型、成员与声明" +home.entries.reference.title: "API 参考" +home.entries.samples.action: "浏览示例" +home.entries.samples.category: "示例" +home.entries.samples.description: "图形与计算技术的可运行示例" +home.entries.samples.title: "示例" +home.entries.title: "文档" +home.entries.tutorial.action: "开始教程" +home.entries.tutorial.category: "教程" +home.entries.tutorial.description: "从空项目开始,绘制第一个三角形" +home.entries.tutorial.title: "第一个三角形" +home.introduction.accent: "跨平台图形开发" +home.introduction.description: "Zenith.NET 提供统一的图形与计算 API,支持 DirectX、Metal 和 Vulkan" +home.introduction.title: "面向 .NET 的{lineBreak}{accent}" +home.meta.description: "使用 Zenith.NET 开发跨平台图形与计算应用,通过统一 API 使用 DirectX、Metal 和 Vulkan" +home.scene.description: "可交互的旋转几何体。拖动或使用方向键调整视角。" +home.scene.label: "几何体显示" +home.scene.surface: "表面" +home.scene.wireframe: "线框" +home.title: "适用于 .NET 的现代 RHI" +learning.concepts.description: "选择资源用途、描述着色器数据与协调 GPU 执行" +learning.concepts.execution.description: "命令录制、提交与资源生命周期" +learning.concepts.platforms.description: "原生呈现与 UI 渲染控件" +learning.concepts.resources.description: "资源用途、内存放置与视图" +learning.concepts.shaders.description: "C# 与 Slang 的数据布局和绑定约定" +learning.concepts.synchronization.description: "依赖关系、可见性与完成状态" +learning.concepts.title: "核心概念" +learning.description: "第一次使用 Zenith.NET,可以从三角形教程开始。完成后,按需要查阅资源管理、着色器数据和同步等概念,或通过示例了解具体图形技术的实现。" +learning.entries.samples.action: "浏览示例" +learning.entries.samples.description: "几何体、计算、光线查询与网格着色的 C# 和 Slang 实现" +learning.entries.tutorial.action: "打开教程" +learning.entries.tutorial.description: "创建窗口并渲染三角形的控制台应用程序" +learning.meta.description: "Zenith.NET 编程模型的入门教程与概念说明" +learning.title: "学习" +reference.description: "资源、命令与平台集成的参考文档" +reference.entries.commands.description: "图形、计算与传输命令" +reference.entries.commands.label: "录制命令" +reference.entries.context.description: "为所选后端创建 GPU 资源" +reference.entries.context.label: "从这里开始" +reference.meta.description: "Zenith.NET 的命名空间、类型与成员" +reference.navigation.core: "核心 API 参考" +reference.title: "API 参考" +samples.computeShader.description: "示例加载 {assetsTexturesShokoPng},通过一次计算分派将图像转换为灰度,再显示输出纹理。转换只执行一次,后续帧显示相同结果。渲染器展示了采样纹理与可写纹理的绑定、向上取整线程组数量以覆盖整张图像的计算方式,以及着色器中的图像边界检查。" samples.computeShader.details: "{computeShaderRendererCs} · {computeShaderSlang}" -samples.computeShader.title: 计算着色器 -samples.cube.description: 添加了索引绘制、常量缓冲区中的模型、视图和投影矩阵以及深度测试。深度纹理会在窗口大小改变时重新创建。在从裁剪空间几何体过渡到变换对象时使用此示例;渲染器使用 {d32FloatS8UInt} 深度/模板附件。 +samples.computeShader.title: "计算着色器" +samples.cube.description: "旋转立方体加入索引绘制、常量缓冲区中的模型、视图和投影矩阵,以及深度测试。窗口大小变化时,会重建 {d32FloatS8UInt} 深度/模板纹理。" samples.cube.details: "{spinningCubeRendererCs} · {spinningCubeSlang}" -samples.cube.title: 旋转立方体 -samples.description: "选择针对您要学习的功能的专项示例。每个示例都会链接到 C# 渲染器及其 Slang 着色器。如果您希望从空项目开始阅读完整应用程序的讲解,请从 {link} 开始。" -samples.description.link: 第一个三角形 -samples.execution.description: "{link} 在一个桌面应用程序中包含了六个独立的渲染器。请使用 .NET 10 SDK 和下述受支持的桌面后端。构建并运行该应用程序,然后从控制台菜单中选择一个示例:" -samples.execution.description.link: ZenithTutorials -samples.execution.details: 宿主程序在 Windows 上选择 DirectX 12,在 macOS 上选择 Metal,在 Linux 上选择 Vulkan。请使用所选后端支持的设备、驱动程序和着色器编译器环境。Linux 窗口路径需要 X11 或 XWayland。{link} 声明了包依赖项,并复制运行时所需的着色器和纹理资产。 -samples.execution.details.link: 项目文件 -samples.execution.guidance: 这些示例共享窗口和呈现代码。您可以根据要研究的功能独立选择任何示例。 -samples.execution.title: 运行教程示例 -samples.host.description: "{appCs} 创建图形上下文、窗口和交换链。它获取命令缓冲区,调用所选的渲染器,提交帧并进行呈现。{iRendererCs} 定义了渲染器的更新、渲染、调整大小和释放方法。" -samples.host.details: 计算与光线追踪会产生离屏纹理。{texturePresenterCs} 和 {presentTextureSlang} 将这些纹理绘制到窗口当前帧的输出纹理中。宿主程序仍然拥有提交操作和交换链呈现的所有权。 -samples.host.title: 共享宿主与呈现 -samples.indirectDrawing.description: 使用索引间接参数缓冲区和结构化缓冲区中的逐实例数据绘制立方体的多个副本。CPU 提供绘制参数并更新变换。在添加 GPU 生成的参数之前,可利用此示例了解间接参数布局以及着色器对实例数据的访问。 +samples.cube.title: "旋转立方体" +samples.description: "每个示例均由 C# 渲染器与 Slang 着色器组成,集中说明一项技术。完整的应用程序设置与渲染顺序见{link}。" +samples.description.link: "第一个三角形" +samples.execution.description: "运行 {link} 项目,并从控制台菜单选择示例。" +samples.execution.description.link: "ZenithTutorials" +samples.execution.title: "运行示例" +samples.host.description: "{appCs} 初始化上下文、窗口和交换链。每帧获取命令缓冲区,调用所选渲染器,提交命令并呈现结果。{iRendererCs} 规定渲染器的更新、渲染、调整大小和释放操作。" +samples.host.details: "计算与光线追踪渲染器生成离屏纹理。{texturePresenterCs} 和 {presentTextureSlang} 将这些纹理绘制到当前输出纹理,随后由共享宿主提交命令并呈现这一帧。" +samples.host.title: "宿主与呈现" +samples.indirectDrawing.description: "间接绘制通过索引绘制参数缓冲区和保存各实例数据的结构化缓冲区,绘制多个立方体。CPU 提供绘制参数并更新变换。" samples.indirectDrawing.details: "{indirectDrawingRendererCs} · {indirectDrawingSlang}" -samples.indirectDrawing.title: 间接绘制 -samples.meshShading.description: 使用任务着色器(task shader)剔除球体实例,并将其索引传递给输出几何体的网格着色器(mesh shader)。渲染器在创建管线前会检查 {contextCapabilitiesMeshShadingSupported}。可利用此示例跟踪贯穿任务与网格阶段的资源句柄与有效负载数据。 +samples.indirectDrawing.title: "间接绘制" +samples.meshShading.description: "任务着色器剔除球体实例,将保留的索引传给负责生成几何体的网格着色器。创建管线前,渲染器检查 {contextCapabilitiesMeshShadingSupported}。" samples.meshShading.details: "{meshShadingRendererCs} · {meshShadingSlang}" -samples.meshShading.title: 网格着色(Mesh Shading) -samples.rayTracing.description: 为地面和程序化球体构建底层与顶层加速结构,然后在计算着色器中执行内联光线查询。渲染器在构建工作负载之前会检查 {contextCapabilitiesRayTracingSupported}。此示例适用于学习加速结构输入以及着色器端的光线遍历。 +samples.meshShading.title: "网格着色" +samples.rayTracing.description: "该示例为地面和程序化球体构建底层与顶层加速结构,再在计算着色器中执行内联光线查询。初始化前检查 {contextCapabilitiesRayTracingSupported}。" samples.rayTracing.details: "{rayTracingRendererCs} · {rayTracingSlang}" -samples.rayTracing.title: 光线追踪 -samples.title: 示例 -samples.triangle.description: 创建顶点缓冲区及匹配的输入布局,然后通过图形管线绘制三个顶点。利用此示例将资源创建与渲染通道中的命令关联起来。 +samples.rayTracing.title: "光线追踪" +samples.title: "示例" +samples.triangle.description: "三角形示例将顶点缓冲区与对应的输入布局关联,通过图形管线绘制三个顶点。" samples.triangle.details: "{helloTriangleRendererCs} · {helloTriangleSlang} · {link}" -samples.triangle.details.link: 完整教程 -samples.triangle.title: Hello Triangle -samples.workloads.description: 主仓库的 {link} 包含组合了多项特性的应用程序。它们各自的项目直接引用库源码。在检出的 Zenith.NET 源码树中,运行所选项目即可,例如: -samples.workloads.description.link: Experiments 目录 -samples.workloads.details: 这些窗口实验项目在 Windows、macOS 和 Linux/X11 上使用相同的宿主选项。关于在 Avalonia、WinForms、WPF、WinUI/Uno 或 MAUI 中绘制,以及控件帧生命周期和实现链接,请参阅{link}。 -samples.workloads.details.link: 平台集成 +samples.triangle.details.link: "完整教程" +samples.triangle.title: "Hello Triangle" +samples.workloads.description: "主仓库的{link}包含规模较大的应用程序,这些项目直接引用库源码。" +samples.workloads.description.link: "Experiments 目录" +samples.workloads.details: "窗口实验项目采用相同的 Windows、macOS 和 Linux/X11 呈现路径。Avalonia、WinForms、WPF、WinUI/Uno 和 MAUI 控件的帧生命周期及实现代码见{link}。" +samples.workloads.details.link: "平台集成" samples.workloads.table.cornellBox.example: "{link}" -samples.workloads.table.cornellBox.example.link: CornellBox -samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: "路径追踪、降噪、色调映射、分辨率放大以及 ImGui 控件。需要光线追踪支持以及对应桌面后端的着色器编译环境。" +samples.workloads.table.cornellBox.example.link: "CornellBox" +samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: "路径追踪、降噪、色调映射、分辨率放大和 ImGui 控件。需要光线追踪支持。" samples.workloads.table.fluidTank.example: "{link}" -samples.workloads.table.fluidTank.example.link: FluidTank -samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: 计算流体模拟、模拟各阶段之间的依赖关系以及多通道表面渲染。需要对应桌面后端与着色器编译环境。 -samples.workloads.table.headings.example: 示例 -samples.workloads.table.headings.whatItDemonstratesAndRequires: 演示内容与运行要求 +samples.workloads.table.fluidTank.example.link: "FluidTank" +samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: "计算流体模拟、模拟阶段之间的依赖,以及多通道表面渲染。" +samples.workloads.table.headings.example: "示例" +samples.workloads.table.headings.whatItDemonstratesAndRequires: "技术与运行要求" samples.workloads.table.inkCanvas.example: "{link}" -samples.workloads.table.inkCanvas.example.link: InkCanvas -samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: 原生窗口中的 Skia 绘制与输入处理。需要对应目标平台的后端和 Skia 原生库。 +samples.workloads.table.inkCanvas.example.link: "InkCanvas" +samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: "原生窗口中的 Skia 绘制与输入处理。需要对应目标平台的后端和 Skia 原生库。" samples.workloads.table.platformDetection.example: "{link}" -samples.workloads.table.platformDetection.example.link: PlatformDetection -samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: 尝试为每个后端创建图形上下文并报告设备功能。若上下文创建失败,则报告为不支持;该结果也可能意味着缺少驱动程序或运行时依赖。 -samples.workloads.title: 探索更大型的工作负载 -tutorial.context.description: 窗口现在可以打开了,但我们尚未创建向其进行渲染的 GPU 对象。{graphicsContext} 提供对所选图形后端及其命令队列的访问。 -tutorial.context.details: 在{emphasis}插入此代码块: -tutorial.context.details.emphasis: using 指令之后、{iWindowWindow} 之前 -tutorial.context.guidance: 分支逻辑在 Windows 上选择 DirectX 12,在 macOS 上选择 Metal,在 Linux 上选择 Vulkan。接下来的渲染代码均使用共享的 Zenith.NET API。我们在开发期间请求启用验证层,并打印通过 {validationMessage} 报告的消息。诊断信息取决于后端以及机器上可用的验证组件。 -tutorial.context.title: 创建图形上下文 -tutorial.description: 构建一个 .NET 控制台应用程序,打开窗口并绘制一个具有平滑颜色渐变的三角形。您将学习顶点数据、着色器和管线状态是如何协同工作的,然后录制并提交生成该图像的命令。 -tutorial.details: 请按顺序完成各个部分。您将首先打开一个空窗口,然后显示背景颜色,最后绘制三角形。在添加下一部分之前,每个检查点都会确认应用程序当前部分的正常运行。初始化只执行一次;每次调用渲染回调时都会录制新的一帧。 +samples.workloads.table.platformDetection.example.link: "PlatformDetection" +samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: "尝试为每个后端创建上下文,并报告设备能力。创建失败时显示为不支持,原因可能是设备、驱动程序或缺失的运行时依赖。" +samples.workloads.title: "综合应用" +tutorial.context.description: "{graphicsContext} 通过所选后端连接应用程序与 GPU,并提供创建渲染资源的方法。" +tutorial.context.details: "在{emphasis}插入上下文初始化代码:" +tutorial.context.details.emphasis: "using 指令之后、{iWindowWindow} 之前" +tutorial.context.guidance: "各分支为当前平台选择后端并请求启用验证。{validationMessage} 消息会输出到控制台。" +tutorial.context.imports: "在 {programCs} 顶部添加以下 using 指令:" +tutorial.context.title: "图形上下文" +tutorial.description: "本教程从一个空的 .NET 控制台项目开始,逐步完成窗口创建,并在窗口中绘制一个彩色三角形。" +tutorial.details: "本教程有三个检查点:空窗口、单色背景和彩色三角形。每完成一个检查点,先运行程序确认结果,再继续添加下一部分。" tutorial.draw.context: "{draw} 的参数如下:" -tutorial.draw.description: 在 {windowRender} 回调中,在 {beginRenderPass} 和 {endRenderPass} 之间,将 {addTheTriangleDrawCommandsHereLater} 替换为以下三个命令: -tutorial.draw.details: "{setPipeline} 选择我们刚才创建的着色器和状态。在绑定顶点数据之前设置它:后端使用管线的输入布局来解释该绑定。" -tutorial.draw.guidance: "{setVertexBufferVertexBuffer} 将从字节偏移量 0 开始的缓冲区绑定到输入槽 0。该槽对应于 {inputLayouts} 中的单个条目。它不会再次复制或上传数据。" -tutorial.draw.notes: 此时命令仍仅处于已录制状态。位于渲染回调末尾的 {submitWait} 和 {present} 调用会执行工作并显示其结果。清除操作仍然是必要的,因为三角形只覆盖图像的一部分;背景在每帧中也必须接收到已定义的颜色。 -tutorial.draw.table.firstInstance.meaning: 从零开始进行实例编号。 -tutorial.draw.table.firstVertex.meaning: 从缓冲区中的第一个顶点开始。 -tutorial.draw.table.headings.argument: 参数 -tutorial.draw.table.headings.description: 值 -tutorial.draw.table.headings.meaning: 含义 -tutorial.draw.table.instanceCount.meaning: 绘制三角形的一个副本。 -tutorial.draw.table.vertexCount.meaning: 读取三个顶点。 -tutorial.draw.title: 在通道内绘制三角形 -tutorial.execution.description: 从 {firstTriangle} 目录构建并运行: -tutorial.execution.details: 窗口中应显示一个三角形,在深色背景下具有红色的上顶点、绿色的右下角顶点和蓝色的左下角顶点。内部应显示这些颜色之间的平滑渐变。 -tutorial.execution.guidance: 调整窗口大小。调整大小的回调会更新帧缓冲区尺寸并重设交换链的大小。渲染通道建立与该图像匹配的视口。由于顶点位置保持为归一化坐标,三角形保持窗口宽度和高度的相同比例;改变纵横比可能会拉伸其形状。保持对象的纵横比需要投影或视口策略,这超出了本次基础绘制的范围。 -tutorial.execution.title: 运行、调整大小与关闭 -tutorial.frame.commands.context: 在 {endRenderPass} 之后,第二次转换准备将图像用于呈现。{submit} 结束录制并提交命令缓冲区;{wait} 等待 GPU 完成该提交。然后 {present} 请求显示渲染出的图像。 -tutorial.frame.commands.description: 渲染通道(render pass)将使用相同附件的绘制操作组合在一起。此处,颜色附件是交换链的输出纹理,即接收我们绘制内容的图像。{colorAttachmentClear} 创建一个描述,指示通道清除为给定的 RGBA 颜色,并在通道结束时保留结果。{beginRenderPass} 录制这些指令;GPU 在命令提交后执行清除。 -tutorial.frame.commands.details: 方括号中包含我们唯一的颜色附件。{null} 参数表示没有深度/模板附件,该附件通常用于存储深度值和模板掩码以进行深度与模板测试。 -tutorial.frame.commands.guidance: "{beginRenderPass} 设置覆盖附件的视口和裁剪区域。视口将渲染坐标映射到像素,裁剪区域限制可以写入的像素。这些默认设置覆盖整个输出纹理,这正是该三角形所需的。" -tutorial.frame.commands.title: 清除、提交与呈现 -tutorial.frame.description: 首先用一种背景颜色填充图像。此操作称为清除(clear)。如果该颜色出现在窗口中,则说明原生呈现目标、命令提交和呈现路径工作正常。在添加几何体和着色器之前,此检查点可让您验证帧循环。 -tutorial.frame.details: 渲染回调是 Silk.NET 在需要绘制帧时调用的代码。此回调不需要事件的流逝时间参数,因此将其命名为 {value}。在{emphasis}注册它: +tutorial.draw.description: "在 {windowRender} 回调中,用以下命令替换 {addTheTriangleDrawCommandsHereLater},位置保持在 {beginRenderPass} 与 {endRenderPass} 之间:" +tutorial.draw.details: "{setPipeline} 选择着色器和渲染状态。后端按管线的输入布局解释顶点绑定,因此这一步必须先于顶点绑定。" +tutorial.draw.guidance: "{setVertexBufferVertexBuffer} 从缓冲区的字节偏移 0 开始,将已上传的顶点数据绑定到输入槽 0,对应 {inputLayouts} 中唯一的条目。" +tutorial.draw.notes: "这些调用录制绘制命令。已有的 {submitWait} 提交命令并等待 GPU 完成,随后 {present} 请求显示完成的图像。保留通道开始时的清除操作,让三角形以外的区域也有确定的背景色。" +tutorial.draw.table.firstInstance.meaning: "实例编号从零开始。" +tutorial.draw.table.firstVertex.meaning: "从缓冲区中的第一个顶点开始。" +tutorial.draw.table.headings.argument: "参数" +tutorial.draw.table.headings.description: "值" +tutorial.draw.table.headings.meaning: "含义" +tutorial.draw.table.instanceCount.meaning: "绘制一个三角形实例。" +tutorial.draw.table.vertexCount.meaning: "读取三个顶点。" +tutorial.draw.title: "绘制命令" +tutorial.execution.description: "构建并运行 {firstTriangle} 项目。" +tutorial.execution.details: "窗口中应出现一个三角形:上方为红色,右下为绿色,左下为蓝色,背景为深色。三个顶点的颜色经过插值,在三角形内部形成平滑过渡。" +tutorial.execution.guidance: "调整窗口大小时,图像的像素尺寸会改变,顶点坐标保持不变。视口将这些坐标映射到新的宽度和高度,因此改变窗口的宽高比会拉伸三角形。" +tutorial.execution.title: "运行应用程序" +tutorial.frame.commands.context: "{endRenderPass} 之后的第二次转换使输出纹理进入可呈现的布局。{submit} 结束录制并提交命令缓冲区,{wait} 阻塞至本次提交完成,随后 {present} 请求显示渲染结果。" +tutorial.frame.commands.description: "渲染通道将写入同一组附件的绘制操作组织在一起。本通道用交换链的输出纹理接收颜色输出。{colorAttachmentClear} 指定以 RGBA 颜色初始化该附件,并在通道结束时保留内容。{beginRenderPass} 按这些设置录制通道的开始命令。" +tutorial.frame.commands.details: "集合中有一个颜色附件。{null} 表示本通道不使用深度/模板附件。" +tutorial.frame.commands.guidance: "{beginRenderPass} 默认让视口和裁剪区域覆盖整个附件。视口把渲染坐标映射为像素位置,裁剪区域则限制可以写入的范围。" +tutorial.frame.commands.title: "清除、提交与呈现" +tutorial.frame.description: "先把窗口填成一种背景色,这个操作称为清除。背景正常显示后,就说明呈现目标、命令提交和呈现流程已经接通,可以继续加入三角形的顶点和着色器。" +tutorial.frame.details: "Silk.NET 在需要绘制一帧时调用渲染回调。本示例不使用回调传入的时间间隔,因此将该参数命名为 {value}。在{emphasis}注册回调:" tutorial.frame.details.emphasis: "{windowRun} 之前" -tutorial.frame.target.description: "{graphicsQueueCommandBuffer} 获取一个已开始录制的命令缓冲区。录制是为 GPU 描述工作;它不会立即执行该工作。" -tutorial.frame.target.details: 第一个 {transition} 为颜色附件访问准备输出纹理。{default} 选择 mip 级别 0 和数组层 0。我们使用 {undefined} 作为先前布局,因为我们将清除整个图像并丢弃其先前的内部数据。需要保留现有内容的通道必须改用其实际的先前布局。 -tutorial.frame.target.guidance: 每帧都使用交换链当前的输出纹理。呈现操作可能会改变当前可用的图像,因此从较早帧保存的纹理并不是永久性的窗口渲染目标。 -tutorial.frame.target.title: 准备输出纹理 -tutorial.frame.title: 显示背景颜色 -tutorial.geometry.data.description: 在{emphasis}添加此数组。接下来的资源创建步骤也按所示顺序位于该回调之前。 +tutorial.frame.target.description: "{graphicsQueueCommandBuffer} 返回可直接录制的命令缓冲区。录制描述 GPU 工作,提交后才开始执行。" +tutorial.frame.target.details: "纹理布局描述操作对纹理的访问方式。第一次 {transition} 将输出纹理准备为颜色附件。这里的 {default} 选择 mip 级别 0 和数组层 0,也就是输出纹理的基础图像。由于这个通道会清除整张图像,可以指定 {undefined},允许丢弃原有内容。" +tutorial.frame.target.guidance: "呈现后可能换用另一张图像,因此每一帧都要获取当前的输出纹理。" +tutorial.frame.target.title: "准备输出纹理" +tutorial.frame.title: "第一帧" +tutorial.geometry.data.description: "在{emphasis}添加顶点数组。后续资源初始化也放在该回调之前,顺序如下。" tutorial.geometry.data.description.emphasis: "{windowRender} 之前" -tutorial.geometry.data.details: 数组的每个元素创建一个 {vertex}。内部的两个 {new} 表达式创建其 {vector3} 位置和 {vector4} 颜色。各顶点描述了顶部、右下角和左下角。顶点着色器将提供第四个位置坐标 {w}。当 w 等于 1 时,x 和 y 直接描述归一化设备坐标:-1 和 +1 是图像边缘,0 是中心。这些坐标不依赖于窗口的像素尺寸。 -tutorial.geometry.data.guidance: 每种颜色包含红、绿、蓝和阿尔法分量。三个顶点的阿尔法均为 1。所有三个位置的 z 坐标均为 0,将它们置于同一平面上。这些位置不需要相机或变换矩阵,因为它们已经直接描述了我们想要渲染的坐标。对于这个单一的平面三角形,我们还将禁用混合与深度测试,并省略深度缓冲区。 -tutorial.geometry.data.title: 选择顶点坐标 -tutorial.geometry.description: "顶点由一个位置以及绘制时使用的数据组成。我们的三角形有三个顶点,每个角一个。每个顶点都包含位置和颜色。GPU 会对颜色进行插值,计算三角形内部各处的中间值。" -tutorial.geometry.format.description: 在{emphasis}追加此声明: +tutorial.geometry.data.details: "每个条目构造一个 {vertex},内部的两个 {new} 表达式分别提供 {vector3} 位置和 {vector4} 颜色。三个位置对应上角、右下角和左下角。顶点着色器将 {w} 作为第四个位置坐标;w 为 1 时,x、y 也就是归一化设备坐标,-1 与 +1 对应图像边界,0 对应中心,与像素尺寸无关。" +tutorial.geometry.data.guidance: "每个颜色包含红、绿、蓝和 alpha 分量,alpha 设为 1。三个顶点的 z 坐标均为 0,位于同一平面。" +tutorial.geometry.data.title: "顶点位置与颜色" +tutorial.geometry.description: "三角形的每个顶点都有位置和颜色。GPU 根据三个位置确定三角形的形状,再对顶点颜色插值,得到内部各处的颜色。" +tutorial.geometry.format.description: "在{emphasis}追加顶点声明:" tutorial.geometry.format.description.emphasis: "{programCs} 的末尾、清理语句之后" -tutorial.geometry.format.details: "{file} 将此类型限制在 {programCs} 内部,构造函数初始化其位置和颜色字段。{layoutKindSequential} 保持字段按照声明顺序排列。{position} 包含三个 32 位浮点数,{color} 包含四个。在该结构体中,位置从字节 0 开始,颜色从字节 12 开始,完整的顶点占用 28 个字节。我们将向图形管线描述这完全相同的布局。" -tutorial.geometry.format.title: 定义顶点 -tutorial.geometry.title: 向 GPU 提供三个顶点 -tutorial.geometry.upload.context: "{fixed} 防止垃圾回收器在使用数组地址时移动该数组。对于此 CPU 可写缓冲区,{upload} 在返回之前会映射、复制并取消映射内存,因此之后无需保持数组固定。缓冲区必须在整个渲染过程中保持有效,并且上传只需进行一次,因为顶点不会发生变化。" -tutorial.geometry.upload.description: 托管数组是 CPU 数据。{buffer} 为 GPU 提供存储空间,以便其可以从中读取顶点。在数组之后,添加: -tutorial.geometry.upload.details: 总大小为 {sizeofVertexVerticesLength}:每个顶点 28 字节,三个顶点,总共 84 字节。{bufferUsagesVertex} 允许顶点输入访问。{cpuWriteOnly} 允许 CPU 直接初始化这个小缓冲区。描述符的步幅(stride)记录了元素大小;我们稍后创建的输入布局将告知顶点获取机制如何读取各个属性。 -tutorial.geometry.upload.guidance: 创建缓冲区并不会填充数据。{upload} 将数组复制到该分配中,从目标字节偏移量 0 开始。其源描述提供了指针和要复制的字节数。 -tutorial.geometry.upload.notes: 在 {programCs} 底部的清理代码中,紧邻 {swapChainDispose} 之前添加 {vertexBufferDispose}。对于更大的静态几何体,{link}解释了何时应选择仅 GPU 内存并通过传输进行上传。 -tutorial.geometry.upload.notes.link: 资源管理 -tutorial.geometry.upload.title: 分配缓冲区并上传数组 -tutorial.input.description: 顶点字节和着色器均已就绪。接下来描述 GPU 应该如何读取每个顶点。属性是一个单独的值,例如位置或颜色。输入布局为每个属性赋予格式和字节偏移量;步幅(stride)给出从一个顶点到下一个顶点的字节距离。在创建着色器之后添加此初始化块: -tutorial.input.details: "{inputLayoutAdd} 在当前步幅处追加一个元素,并将该步幅增加该元素的大小。它不会检查 C# 结构体。在此处它生成了 CPU 内存与着色器输入之间的以下契约:" -tutorial.input.guidance: "更改 C# 字段顺序或填充而不更新此描述会导致 GPU 读取错误的字节。默认的 {semanticIndex} 为 0,匹配 {pOSITION0} 和 {cOLOR0}。这两个元素属于同一个缓冲区,因此管线将包含一个输入布局,并且我们将该缓冲区绑定到槽 0。" -tutorial.input.table.headings.byteOffset: 字节偏移量 +tutorial.geometry.format.details: "{file} 将类型的使用范围限定在 {programCs} 内,{layoutKindSequential} 则保留字段的声明顺序。{position} 包含三个 32 位浮点数,字节偏移量为 0;{color} 包含四个,字节偏移量为 12。因此,每个顶点占 28 字节。稍后将通过输入布局描述这一排列,让 GPU 正确读取各字段。" +tutorial.geometry.format.imports: "在 {programCs} 顶部添加以下 using 指令,以使用向量类型和结构体布局特性:" +tutorial.geometry.format.title: "顶点表示" +tutorial.geometry.title: "顶点数据" +tutorial.geometry.upload.context: "{fixed} 防止垃圾回收器在地址使用期间移动数组。对于这个 CPU 可写缓冲区,{upload} 会映射内存、复制数据,并在返回前解除映射,因此只需在调用期间固定数组。顶点数据在初始化时上传一次即可;缓冲区则必须保留到渲染结束。" +tutorial.geometry.upload.description: "将顶点存入 {buffer},供 GPU 在绘制时读取。在顶点数组之后紧接着添加分配与上传代码:" +tutorial.geometry.upload.details: "分配大小为 {sizeofVertexVerticesLength},即三个 28 字节顶点,共 84 字节。{bufferUsagesVertex} 声明顶点输入用途,{cpuWriteOnly} 允许 CPU 直接初始化。描述中的步幅记录元素大小,随后定义的输入布局指定 GPU 如何读取各个顶点属性。" +tutorial.geometry.upload.guidance: "分配不会初始化缓冲区内容。{upload} 使用数据描述中的源指针和字节数,将数组复制到目标字节偏移量 0。" +tutorial.geometry.upload.imports: "在 {programCs} 顶部的 using 指令中添加 {bufferAlias},以区分 Zenith.NET 的缓冲区类型与 {systemBuffer}。" +tutorial.geometry.upload.notes: "在 {programCs} 末尾的清理代码中,紧接在 {swapChainDispose} 之前加入 {vertexBufferDispose}。较大静态几何体所需的 GPU 专用存储与上传方式见{link}。" +tutorial.geometry.upload.notes.link: "资源管理" +tutorial.geometry.upload.title: "缓冲区分配与上传" +tutorial.input.description: "GPU 需要知道位置、颜色等顶点属性存在哪里。输入布局指定每个属性的格式和字节偏移量,并用步幅表示从一个顶点到下一个顶点相隔多少字节。在创建着色器之后添加以下代码:" +tutorial.input.details: "{inputLayoutAdd} 将每个属性追加在前一个属性之后,并将其大小计入步幅。偏移量根据这里提供的格式计算,而非通过检查 C# 结构体获得。这两个字段对应的布局如下:" +tutorial.input.guidance: "{semanticIndex} 默认为 0,与着色器中的 {pOSITION0} 和 {cOLOR0} 对应。位置与颜色存放在同一个顶点缓冲区中,因此管线只需在槽 0 使用一个输入布局。如果 C# 结构体的字段顺序或填充发生变化,也要相应调整此布局。" +tutorial.input.table.headings.byteOffset: "字节偏移量" tutorial.input.table.headings.cField: "C# 字段" -tutorial.input.table.headings.format: 格式 -tutorial.input.table.headings.shaderInput: 着色器输入 -tutorial.input.table.nextVertex.cField: 下一个顶点 -tutorial.input.table.nextVertex.format: 总步幅:28 字节 -tutorial.input.table.nextVertex.shaderInput: 下一个输入记录 +tutorial.input.table.headings.format: "格式" +tutorial.input.table.headings.shaderInput: "着色器输入" +tutorial.input.table.nextVertex.cField: "下一个顶点" +tutorial.input.table.nextVertex.format: "总步幅:28 字节" +tutorial.input.table.nextVertex.shaderInput: "下一个输入记录" tutorial.input.table.vertexColor.format: "{float4}(16 字节)" tutorial.input.table.vertexPosition.format: "{float3}(12 字节)" -tutorial.input.title: 描述顶点输入布局 -tutorial.lifecycle.description: 完成的应用程序重复执行以下序列: -tutorial.lifecycle.details: 关闭窗口将从 {run} 返回。每个渲染的帧都已经等待其 GPU 工作完成,因此我们现在可以安全释放它所使用的资源。{windowRun} 之后的清理代码应为: -tutorial.lifecycle.guidance: "在销毁原生窗口前释放交换链,并在释放所有资源后释放图形上下文。队列拥有并回收提交的命令缓冲区,交换链拥有其输出纹理。因此,本应用程序不需要单独对这些命令缓冲区或输出纹理调用 {dispose}。" -tutorial.lifecycle.title: 跟踪一帧的生命周期 -tutorial.pipeline.behavior: 在输入布局之后,添加: -tutorial.pipeline.context: "{cullNone} 填充三角形,并且不因面的朝向而将其剔除。顶点顺序决定面的环绕方向;关闭剔除可以避免因这个顺序而使第一个三角形不可见。" -tutorial.pipeline.description: 我们现在拥有顶点数据、输入布局和两个着色器。{graphicsPipeline} 将它们连接起来,并指定 GPU 如何将顶点组装为图元并将结果写入附件。 -tutorial.pipeline.details: 管线将可编程着色器阶段与固定功能设置相结合,后者控制诸如三角形组装、面剔除和混合等 GPU 操作。对于这个三角形,选择以下设置: -tutorial.pipeline.guidance: 颜色格式取自 {swapChainDescFormat}。它必须与渲染通道使用的图像匹配。{count1} 表示每像素一个采样点。 -tutorial.pipeline.item: "{triangleList} 将每组连续的三个顶点组装成一个三角形。我们将提供三个顶点并绘制一次,因此不需要索引缓冲区。" -tutorial.pipeline.notes: "{depthNone} 禁用深度测试和写入,与没有深度附件的通道相匹配。" -tutorial.pipeline.reference: "{opaque} 禁用混合,因此片元着色器的颜色会替换三角形内部的背景。" -tutorial.pipeline.title: 连接着色器与顶点布局 -tutorial.pipeline.usage: 着色器对象在创建管线后即可释放,正如示例渲染器中所做的那样。对于使用它进行绘制的每一帧,保持管线本身处于有效状态。在清理代码中将 {pipelineDispose} 添加到 {vertexBufferDispose} 之前。管线创建是渲染回调之前的最后一步初始化。 -tutorial.pipeline.validation: 管线描述声明了附件配置;它不会创建另一个图像。{inputLayouts} 具有一个条目,因为位置和颜色一起存储在一个缓冲区中。 -tutorial.presentation.title: 将 GPU 连接到窗口 -tutorial.project.context: 在项目的构建设置中启用{emphasis}({allowUnsafeBlocks})。我们将使用它将顶点数据传递给 GPU,并用于窗口辅助类的原生调用。 -tutorial.project.context.emphasis: 允许不安全代码 -tutorial.project.description: 创建项目并进入其目录: -tutorial.project.details: 安装软件包: -tutorial.project.guidance: "{zenithNET} 提供共享的渲染 API。三个后端包允许同一个程序选择适合其平台的实现。{zenithNETCompiler} 负责为该实现编译 Slang 着色器(我们稍后将编写的小型 GPU 程序)。Silk.NET 提供窗口和事件循环。" -tutorial.project.title: 创建控制台项目 -tutorial.requirements.context: 您可以从一个空项目开始跟随本页操作。{link}及其{detail}可作为此处使用的渲染和窗口 API 的参考。 -tutorial.requirements.context.detail: 共享宿主 -tutorial.requirements.context.link: Hello Triangle 示例 -tutorial.requirements.description: "您需要 {emphasis}、代码编辑器或 IDE,以及配备了 Zenith.NET 后端支持的 GPU 和驱动程序的桌面设备。具备基本的 C# 知识即可;图形概念会在首次使用时予以介绍。这是一个普通的 {net10} 控制台项目。后端负责将 Zenith.NET 操作转换为对图形 API(例如 DirectX 12、Metal 或 Vulkan)的调用。应用程序在启动时选择其中之一:" -tutorial.requirements.description.emphasis: .NET 10 SDK -tutorial.requirements.details: 对于此处使用的窗口路径,Linux 需要与 X11 兼容的窗口会话。对于本三角形而言,不需要可选的光线追踪和网格着色(mesh shading)特性。 -tutorial.requirements.guidance: Zenith.NET 渲染到由应用程序提供的表面中。Silk.NET.Windowing 将创建桌面窗口并处理其事件。在 macOS 上,呈现目标是 Metal 图层({cAMetalLayerCs});教程中的窗口辅助类会为我们附加该图层。 -tutorial.requirements.table.headings.graphicsBackend: 图形后端 -tutorial.requirements.table.headings.platform: 平台 -tutorial.requirements.table.headings.windowSurface: 窗口表面 -tutorial.requirements.table.linux.graphicsBackend: Vulkan 1.4 -tutorial.requirements.table.linux.platform: Linux -tutorial.requirements.table.linux.windowSurface: X11 窗口与显示;XWayland 也同样适用 -tutorial.requirements.table.macOS.graphicsBackend: Metal 4 -tutorial.requirements.table.macOS.platform: macOS -tutorial.requirements.table.macOS.windowSurface: 附加到窗口的 Metal 图层 -tutorial.requirements.table.windows.graphicsBackend: DirectX 12 -tutorial.requirements.table.windows.platform: Windows -tutorial.requirements.table.windows.windowSurface: Win32 窗口句柄 -tutorial.requirements.title: 开始之前 -tutorial.resize.context: 再次运行 {dotnetRun}。窗口现在应该具有均匀的暗色背景,并且在调整大小后继续填满窗口。保留此回调:三角形将在其现有的渲染通道内绘制。 -tutorial.resize.description: 交换链的图像必须跟随帧缓冲区尺寸。使用 {framebufferResize} 响应像素大小的变化,包括由显示缩放引起的变化。在渲染回调之后、仍处于 {windowRun} 之前,添加: -tutorial.resize.details: Silk.NET 区分窗口大小变化与{link}。我们需要后者,因为交换链存储的是像素。最小化的窗口可以具有零大小的帧缓冲区。在那种情况下,两个回调都会跳过它们的 GPU 工作。调整大小后,渲染通道将为其视口和裁剪区域使用新的附件尺寸。 -tutorial.resize.details.link: 帧缓冲区大小变化 -tutorial.resize.guidance: 我们在每次提交后都会等待,因此当调整大小处理程序替换图像时,之前的帧不会继续使用这些图像。当前的 {present} 实现也会在图形队列上等待。这个简单的循环确保一帧的工作在下一帧开始前完成;{link}涵盖了更高级的调度方式。 -tutorial.resize.guidance.link: 同步 -tutorial.resize.title: 响应窗口大小调整 -tutorial.shaders.compilation.context: 编译在初始化期间执行一次。{appContextBaseDirectory} 负责在可执行文件旁定位复制的着色器,而与当前工作目录无关。这些着色器仅使用顶点输入,因此目前还没有常量缓冲区、纹理或资源句柄需要绑定。 -tutorial.shaders.compilation.description: 在 {triangleSlang} 的文件属性中,将{emphasis}设置为{detail}。这会使着色器在可执行文件旁可用。 -tutorial.shaders.compilation.description.detail: 如果较新则复制 -tutorial.shaders.compilation.description.emphasis: 复制到输出目录 -tutorial.shaders.compilation.details: 返回 {programCs}。在顶点上传之后、渲染回调之前添加这些初始化语句: -tutorial.shaders.compilation.guidance: "{zenithCompiler} 返回包含所请求图形 API 代码的着色器描述。{createShader} 创建对应的后端对象。图形 API 和入口点名称都很关键:使用 {contextGraphicsApi},并将 {vSMain} 和 {fSMain} 的拼写保持与 Slang 文件中完全一致。" -tutorial.shaders.compilation.title: 针对所选后端进行编译 -tutorial.shaders.context: "{fSInput} 将顶点着色器的输出连接到片元着色器的输入。由顶点着色器写入时,{sVPOSITION} 提供裁剪空间位置,即 GPU 用来判断哪些内容位于可见图像范围内的四个坐标。{cOLOR0} 传递需要在顶点之间插值的颜色。两个阶段使用的类型与语义必须一致。" -tutorial.shaders.description: 着色器是由 GPU 执行的程序。本次绘制需要一个顶点着色器来确定顶点位置,以及一个片元着色器来生成三角形内部的颜色。我们将使用 Slang 着色器语言编写它们,并从同一文件中编译两个入口点。入口点是着色器阶段开始执行的函数。 -tutorial.shaders.details: 创建 {triangleSlang},从以下两个结构体开始: -tutorial.shaders.fragment.description: 将片元入口点追加到同一个文件中: -tutorial.shaders.fragment.details: 光栅化确定三角形覆盖了哪些图像位置。它生成片元(由片元着色器处理的数据),并在覆盖区域内插值顶点颜色。{fSMain} 通过 {sVTARGET} 返回此插值颜色,该语义标识第一个颜色附件。 -tutorial.shaders.fragment.guidance: 顶点颜色插值与附件混合是相互独立的。混合是将片元的输出与附件中已存储的颜色相结合。我们设置的不透明混合状态禁用了该组合,因此插值得到的颜色将直接替换三角形内部的背景。 -tutorial.shaders.fragment.title: 为片元着色 -tutorial.shaders.guidance: "{vSInput} 描述顶点着色器从顶点缓冲区接收的内容。语义 {pOSITION0} 和 {cOLOR0} 标识输入;仅凭 C# 字段名称无法建立该映射。" -tutorial.shaders.title: 编写两个着色器阶段 -tutorial.shaders.vertex.description: 将顶点入口点追加到 {triangleSlang} 中: -tutorial.shaders.vertex.details: GPU 对每个输入顶点调用此入口点。它为位置添加齐次坐标 {w} 并传递颜色。在顶点阶段之后,位置会被除以 w;在此处该除法保持 x、y 和 z 不变。这就是为什么上面选择的位置可以直接理解为归一化设备坐标的原因。 -tutorial.shaders.vertex.title: 定位每个顶点 -tutorial.surface.description: 图形上下文还需要知道在何处显示其输出。在{emphasis}添加以下内容: +tutorial.input.title: "顶点输入布局" +tutorial.lifecycle.description: "每帧依次执行以下操作:" +tutorial.lifecycle.details: "关闭窗口后,{run} 返回,程序继续执行清理代码。每一帧都已等待其提交完成,因此现在可以释放这些命令使用的资源。{windowRun} 之后完整的清理代码如下:" +tutorial.lifecycle.guidance: "先释放交换链,再销毁其原生窗口;先释放应用程序资源,再释放上下文。已提交的命令缓冲区由队列回收,输出纹理由交换链管理,二者都不需要单独调用 {dispose}。" +tutorial.lifecycle.title: "帧生命周期与清理" +tutorial.pipeline.behavior: "在输入布局之后创建管线:" +tutorial.pipeline.context: "{cullNone} 关闭面剔除,因此无论顶点在画面中呈顺时针还是逆时针排列,三角形都会被绘制。" +tutorial.pipeline.description: "{graphicsPipeline} 将顶点布局、两个着色器,以及图元组装和附件输出所需的设置组合在一起。" +tutorial.pipeline.details: "着色器负责处理顶点和片元。其余管线设置决定图元如何组装、是否剔除某个朝向的面,以及如何进行深度测试和颜色混合:" +tutorial.pipeline.guidance: "管线颜色格式必须匹配渲染通道附件,因此直接取自 {swapChainDescFormat}。{count1} 表示每像素一个采样点。" +tutorial.pipeline.item: "{triangleList} 将每组连续的三个顶点组装成一个三角形。" +tutorial.pipeline.notes: "{depthNone} 关闭深度测试和深度写入,与通道没有深度附件的配置一致。" +tutorial.pipeline.reference: "{opaque} 关闭混合,因此片元着色器输出直接替换三角形内部的背景色。" +tutorial.pipeline.title: "图形管线" +tutorial.pipeline.usage: "管线创建完成后即可释放着色器对象。渲染期间保留管线,在清理代码中将 {pipelineDispose} 放在 {vertexBufferDispose} 之前。" +tutorial.presentation.title: "图形上下文与呈现" +tutorial.project.context: "在项目构建设置中启用{emphasis}({allowUnsafeBlocks})。窗口辅助代码的原生调用和顶点上传需要不安全代码。" +tutorial.project.context.emphasis: "允许不安全代码" +tutorial.project.description: "创建名为 {firstTriangle} 的 C# 控制台项目,目标框架设为 .NET 10。" +tutorial.project.details: "为项目添加以下 NuGet 包:" +tutorial.project.guidance: "{zenithNET} 提供统一渲染 API,三个后端包提供各平台的实现。{zenithNETCompiler} 为所选后端编译稍后介绍的 Slang 着色器。Silk.NET 负责窗口创建与事件处理。" +tutorial.project.title: "项目设置" +tutorial.requirements.context: "{link}及其{detail}提供了本教程的参考实现。" +tutorial.requirements.context.detail: "共享宿主" +tutorial.requirements.context.link: "Hello Triangle 示例" +tutorial.requirements.description: "需要 {emphasis},并具备基础 C# 知识。应用程序以 {net10} 为目标框架。GPU 和驱动程序须支持所在平台选用的后端:" +tutorial.requirements.description.emphasis: ".NET 10 SDK" +tutorial.requirements.guidance: "Zenith.NET 渲染到应用程序提供的原生呈现目标。Silk.NET.Windowing 创建窗口并处理事件。macOS 使用由 {cAMetalLayerCs} 表示的 Metal 图层,窗口辅助代码负责将其连接到窗口。" +tutorial.requirements.table.headings.graphicsBackend: "图形后端" +tutorial.requirements.table.headings.platform: "平台" +tutorial.requirements.table.linux.graphicsBackend: "Vulkan 1.4" +tutorial.requirements.table.linux.platform: "Linux(X11 或 XWayland)" +tutorial.requirements.table.macOS.graphicsBackend: "Metal 4" +tutorial.requirements.table.macOS.platform: "macOS" +tutorial.requirements.table.windows.graphicsBackend: "DirectX 12" +tutorial.requirements.table.windows.platform: "Windows" +tutorial.requirements.title: "前置条件" +tutorial.resize.context: "再次构建并运行程序。调整窗口大小后,背景应继续填满整个窗口:每次开始新的渲染通道时,视口和裁剪区域都会按调整后的附件尺寸设置。保留渲染回调,后面将在这个通道内绘制三角形。" +tutorial.resize.description: "帧缓冲区尺寸变化时,交换链也要随之调整。在渲染回调之后、{windowRun} 之前注册 {framebufferResize} 回调:" +tutorial.resize.details: "这里监听的是以像素为单位的{link},而非窗口逻辑尺寸的变化。窗口最小化时,帧缓冲区的宽度或高度可能变为零;此时,尺寸变化回调保留现有交换链,不执行调整。渲染回调也会在任一尺寸为零时直接返回,直到帧缓冲区恢复有效尺寸后再继续绘制。" +tutorial.resize.details.link: "帧缓冲区大小变化" +tutorial.resize.guidance: "渲染回调会等待当前帧的提交完成,再调用 {present}。因此,尺寸变化回调替换交换链图像时,此前帧的工作已经结束。关于完成状态与资源生命周期的要求,详见{link}。" +tutorial.resize.guidance.link: "同步" +tutorial.resize.title: "窗口尺寸变化" +tutorial.shaders.compilation.context: "{appContextBaseDirectory} 让程序从输出目录加载已复制的着色器。即使从其他工作目录启动程序,查找文件的位置也不会改变。" +tutorial.shaders.compilation.description: "将 {triangleSlang} 的文件属性{emphasis}设为{detail},构建时便会将着色器复制到可执行文件所在目录。" +tutorial.shaders.compilation.description.detail: "如果较新则复制" +tutorial.shaders.compilation.description.emphasis: "复制到输出目录" +tutorial.shaders.compilation.details: "返回 {programCs},在顶点上传之后、渲染回调之前添加着色器初始化:" +tutorial.shaders.compilation.guidance: "{zenithCompiler} 为 {contextGraphicsApi} 指定的后端编译源码,{createShader} 再根据编译后的描述创建着色器对象。入口点名称 {vSMain} 和 {fSMain} 分别选中 Slang 文件中定义的两个函数。" +tutorial.shaders.compilation.title: "编译着色器" +tutorial.shaders.context: "{fSInput} 连接两个着色器阶段。顶点着色器将裁剪空间位置写入 {sVPOSITION},GPU 据此判断三角形的可见部分。{cOLOR0} 字段传递顶点颜色,颜色经过三角形内部的插值后到达片元着色器。两个阶段必须使用一致的颜色类型与语义。" +tutorial.shaders.description: "着色器是在 GPU 上运行的程序。顶点着色器确定每个顶点的位置,片元着色器则确定图像中被覆盖位置的颜色。我们将两个阶段写在同一个 Slang 文件中,并分别定义入口点,也就是各阶段开始执行的函数。" +tutorial.shaders.details: "创建 {triangleSlang},先定义输入与输出结构:" +tutorial.shaders.fragment.description: "在同一文件中追加片元入口点:" +tutorial.shaders.fragment.details: "光栅化确定三角形在图像中的覆盖范围,并在这些位置生成片元。每个片元的颜色由三个顶点的颜色插值得到。{fSMain} 返回这个颜色,{sVTARGET} 则将结果送到第一个颜色附件。" +tutorial.shaders.fragment.title: "片元着色" +tutorial.shaders.guidance: "{vSInput} 定义顶点着色器输入。{pOSITION0} 和 {cOLOR0} 按语义标识属性,C# 字段名称本身不建立这一映射。" +tutorial.shaders.title: "着色器阶段" +tutorial.shaders.vertex.description: "在 {triangleSlang} 中追加顶点入口点:" +tutorial.shaders.vertex.details: "GPU 为每个输入顶点调用这一入口点,补充齐次坐标 {w} 并传递颜色。顶点处理结束后,位置要除以 w。本例 w 为 1,x、y、z 保持不变,可直接解释为归一化设备坐标。" +tutorial.shaders.vertex.title: "顶点着色" +tutorial.surface.description: "在{emphasis}指定原生呈现目标:" tutorial.surface.description.emphasis: "{windowCenter} 之后、{windowRun} 之前" -tutorial.surface.details: "{surface} 描述了原生呈现目标及其像素尺寸。帧缓冲区是与窗口关联的像素图像。{framebufferSize} 以像素为单位给出其尺寸;启用显示缩放时,窗口的逻辑尺寸可能会有所不同。" -tutorial.surface.guidance: 该表面与上面选定的后端相匹配。Windows 提供窗口句柄,Linux 提供 X11 显示与窗口,macOS 辅助类提供附加的 Metal 图层。这是将我们的窗口连接到渲染流程中唯一与平台相关的部分。 -tutorial.surface.title: 描述原生呈现目标 -tutorial.swapChain.context: 交换链同时使用了图形上下文与原生窗口。将 {programCs} 底部的 {windowDispose} 行替换为以下清理顺序: -tutorial.swapChain.description: 使用表面描述来创建将要呈现的图像。紧随表面代码块之后,添加: -tutorial.swapChain.details: "{swapChain} 管理窗口中显示的图像。在每一帧中,{drawable} 为我们提供作为 {texture}(用于图像数据的 API 类型)的当前图像。绘制完成后,{present} 请求显示结果并前进到下一个 drawable。" -tutorial.swapChain.guidance: "{b8G8R8A8UNorm} 按蓝、绿、红和阿尔法通道的顺序存储四个 8 位颜色通道。{uNorm} 表示从 0 到 255 的整数值对应从 0 到 1 的值。着色器仍将返回逻辑 RGBA 值;此格式决定这些通道在图像中的存储方式。稍后,图形管线将使用 {swapChainDescFormat} 来匹配此附件。" -tutorial.swapChain.title: 创建交换链 -tutorial.title: 第一个三角形 -tutorial.troubleshooting.description: 首先查看控制台中的任何错误,然后利用前面的检查点确定失败的阶段: -tutorial.troubleshooting.details: 使用{link}和{detail}来对比顶点数据、输入布局和绘制操作。该示例将窗口和提交逻辑放在共享宿主中;本教程将应用程序流程保留在 {programCs} 中。继续阅读{context}以学习索引绘制、变换和深度测试。 -tutorial.troubleshooting.details.context: 旋转立方体 -tutorial.troubleshooting.details.detail: Slang 着色器 -tutorial.troubleshooting.details.link: 示例渲染器 -tutorial.troubleshooting.table.backend.check: 检查所选后端是否受设备和已安装的图形驱动程序支持。 -tutorial.troubleshooting.table.backend.symptom: 后端创建失败 -tutorial.troubleshooting.table.drawing.check: 检查上传大小、输入布局、管线选择以及渲染通道内绘制命令的位置。 -tutorial.troubleshooting.table.drawing.symptom: 背景出现但三角形未出现 -tutorial.troubleshooting.table.headings.check: 检查项 -tutorial.troubleshooting.table.headings.symptom: 现象 -tutorial.troubleshooting.table.input.check: 检查 28 字节步幅以及 0 和 12 的位置/颜色偏移量。 -tutorial.troubleshooting.table.input.symptom: 顶点位置或颜色损坏 -tutorial.troubleshooting.table.shaders.check: 检查复制的 {triangleSlang}、入口点拼写以及编译器报告的诊断信息。 -tutorial.troubleshooting.table.shaders.symptom: 清除颜色步骤有效,但着色器加载失败 -tutorial.troubleshooting.table.window.check: 确认 .NET 项目能够构建成功,并且仅包含窗口的步骤可以在桌面会话中运行。在 Linux 上,检查 X11 或 XWayland 是否可用。 -tutorial.troubleshooting.table.window.symptom: 没有窗口打开 -tutorial.troubleshooting.title: 检查失败的阶段 -tutorial.window.context: "{usingZenithTutorials} 导入辅助类的命名空间。每个 C# 文件使用各自的常规 using 指令,因此互操作导入在两个文件中都是必需的。别名 {buffer} 指向 Zenith.NET 的缓冲区类型,以将其与 {systemBuffer} 区分开来。" -tutorial.window.description: 将 {cocoaHelperCs} 添加到项目中,保持其命名空间不变。在该文件顶部、其命名空间声明之前添加 {interopUsing}。该辅助类在 macOS 上为窗口附加 Metal 图层;其他平台分支不会调用它。 -tutorial.window.details: 将生成的 {programCs} 替换为以下代码。它使用顶级语句,按顺序执行而无需显式的 {main} 方法。后续部分将告诉您在该文件的何处添加代码: -tutorial.window.guidance: "{graphicsAPINone} 要求 Silk.NET 创建一个没有自身图形上下文的窗口。我们将使用 Zenith.NET 创建该上下文。{initialize} 创建原生窗口并使其句柄可用。句柄是由窗口系统提供的标识符。{center} 使窗口居中,{run} 处理事件直到窗口关闭。然后执行进入 {dispose},释放窗口。" -tutorial.window.notes: 运行 {dotnetRun}。应该会打开一个空窗口,并对移动、调整大小和关闭做出响应。由于我们尚未提交任何渲染命令,其内容尚未定义。在继续之前将其关闭。 -tutorial.window.title: 打开窗口 -ui.action.copy: 复制 -ui.action.navigate: 导航 -ui.action.open: 打开 -ui.action.source: 查看源码 -ui.api.browse: 浏览命名空间和类型。 -ui.api.clearTypeSearch: 清除类型搜索 -ui.api.findType: 查找类型 -ui.api.loadError: 无法加载类型。刷新此页面以重试。 -ui.api.loadingNamespaces: 正在加载命名空间… -ui.api.loadingTypes: 正在加载类型… -ui.api.matchingTypes: 匹配的类型 -ui.api.namespace: 命名空间 -ui.api.namespaces: 命名空间 -ui.api.noNamespaceTypes: 此命名空间中没有类型。 -ui.api.noTypes: 没有匹配的类型。 -ui.api.types: 类型 -ui.content.reference: 参考 -ui.content.source: 源代码 -ui.content.tutorial: 教程 -ui.contents.close: 关闭目录 -ui.contents.open: 打开目录 -ui.contents.title: 目录 -ui.footer.caption: 适用于 .NET 的现代 RHI。 -ui.footer.label: 页脚 -ui.language.label: 语言 -ui.language.unavailable: 未翻译 -ui.members.clear: 清除成员搜索 -ui.members.close: 关闭成员查找器 -ui.members.empty: 没有匹配的成员。 -ui.members.open: 转到成员 -ui.members.placeholder: 名称或签名… -ui.members.search: 搜索成员 -ui.members.title: 查找成员 -ui.members.undeclared: 此类型没有声明的成员。 -ui.navigation.api: API -ui.navigation.concepts: 概念 -ui.navigation.home: 首页 -ui.navigation.label: 主导航 -ui.navigation.toggle: 切换导航 -ui.outline.title: 本页导读 -ui.reference.assembly: 程序集 -ui.reference.classes: 类 -ui.reference.constructors: 构造函数 +tutorial.surface.details: "帧缓冲区是窗口用于显示的像素图像。{surface} 描述原生呈现目标及其尺寸,{framebufferSize} 给出以像素为单位的大小。启用显示缩放时,这个大小可能与窗口的逻辑尺寸不同。" +tutorial.surface.guidance: "呈现目标提供后端所需的原生句柄:Windows 使用 Win32 窗口,Linux 使用 X11 显示与窗口,macOS 使用已连接的 Metal 图层。" +tutorial.surface.title: "原生呈现目标" +tutorial.swapChain.context: "交换链同时依赖上下文与窗口。将 {programCs} 末尾的 {windowDispose} 替换为以下释放顺序:" +tutorial.swapChain.description: "紧接呈现目标描述,创建交换链:" +tutorial.swapChain.details: "{swapChain} 管理窗口呈现的图像。{drawable} 以图像资源 {texture} 的形式提供当前图像。渲染后,{present} 请求显示该图像,并推进到下一个输出纹理。" +tutorial.swapChain.guidance: "{b8G8R8A8UNorm} 按蓝、绿、红和 alpha 顺序保存四个 8 位通道。{uNorm} 将整数 0–255 对应到 0–1。着色器仍输出逻辑 RGBA 值,格式只规定存储表示;管线通过 {swapChainDescFormat} 匹配附件。" +tutorial.swapChain.title: "交换链" +tutorial.title: "第一个三角形" +tutorial.troubleshooting.description: "结合控制台诊断与三个检查点定位失败阶段:" +tutorial.troubleshooting.details: "{link}与{detail}可用于核对顶点数据、输入布局和绘制操作。该示例将窗口与提交逻辑放入共享宿主,本教程则保留在 {programCs} 中。{context}进一步介绍索引绘制、变换与深度测试。" +tutorial.troubleshooting.details.context: "旋转立方体" +tutorial.troubleshooting.details.detail: "Slang 着色器" +tutorial.troubleshooting.details.link: "示例渲染器" +tutorial.troubleshooting.table.backend.check: "检查所选后端是否受设备和已安装的图形驱动程序支持。" +tutorial.troubleshooting.table.backend.symptom: "后端创建失败" +tutorial.troubleshooting.table.drawing.check: "检查上传大小、输入布局、管线选择以及渲染通道内绘制命令的位置。" +tutorial.troubleshooting.table.drawing.symptom: "背景出现但三角形未出现" +tutorial.troubleshooting.table.headings.check: "检查项" +tutorial.troubleshooting.table.headings.symptom: "现象" +tutorial.troubleshooting.table.input.check: "检查步幅是否为 28 字节,位置和颜色是否分别从偏移 0 和 12 字节开始。" +tutorial.troubleshooting.table.input.symptom: "顶点位置或颜色异常" +tutorial.troubleshooting.table.shaders.check: "检查复制的 {triangleSlang}、入口点拼写以及编译器报告的诊断信息。" +tutorial.troubleshooting.table.shaders.symptom: "背景色正常显示,但着色器加载失败" +tutorial.troubleshooting.table.window.check: "确认 .NET 项目能够构建成功,并且仅包含窗口的步骤可以在桌面会话中运行。在 Linux 上,检查 X11 或 XWayland 是否可用。" +tutorial.troubleshooting.table.window.symptom: "窗口未打开" +tutorial.troubleshooting.title: "问题排查" +tutorial.window.description: "将 {cocoaHelperCs} 下载到项目中。该辅助类负责将 Metal 图层连接到 macOS 窗口。" +tutorial.window.details: "将自动生成的 {programCs} 内容替换为以下代码。它使用顶级语句,按书写顺序执行,不需要显式编写 {main} 方法。后续各节会指出新代码应放在哪里:" +tutorial.window.guidance: "{graphicsAPINone} 将图形上下文的创建交给 Zenith.NET。{initialize} 创建原生窗口,使窗口系统的句柄可供使用;{center} 把窗口放到屏幕中央。{run} 持续处理事件,直到窗口关闭,随后执行 {dispose} 释放窗口。" +tutorial.window.notes: "构建并运行程序,检查窗口能否打开、移动、调整大小和关闭。此时还没有提交渲染命令,窗口内容尚未定义。关闭窗口后再继续。" +tutorial.window.title: "创建窗口" +ui.action.copy: "复制" +ui.action.navigate: "导航" +ui.action.open: "打开" +ui.action.source: "查看源码" +ui.api.browse: "浏览命名空间和类型。" +ui.api.clearTypeSearch: "清除类型搜索" +ui.api.findType: "查找类型" +ui.api.loadError: "无法加载类型。刷新此页面以重试。" +ui.api.loadingNamespaces: "正在加载命名空间…" +ui.api.loadingTypes: "正在加载类型…" +ui.api.matchingTypes: "匹配的类型" +ui.api.namespace: "命名空间" +ui.api.namespaces: "命名空间" +ui.api.noNamespaceTypes: "此命名空间中没有类型。" +ui.api.noTypes: "没有匹配的类型。" +ui.api.types: "类型" +ui.content.reference: "参考" +ui.content.source: "源代码" +ui.content.tutorial: "教程" +ui.contents.close: "关闭目录" +ui.contents.open: "打开目录" +ui.contents.title: "目录" +ui.footer.caption: "面向 .NET 的现代 RHI" +ui.footer.label: "页脚" +ui.language.label: "语言" +ui.language.unavailable: "未翻译" +ui.members.clear: "清除成员搜索" +ui.members.close: "关闭成员查找器" +ui.members.empty: "没有匹配的成员。" +ui.members.open: "转到成员" +ui.members.placeholder: "名称或签名…" +ui.members.search: "搜索成员" +ui.members.title: "查找成员" +ui.members.undeclared: "此类型没有声明的成员。" +ui.navigation.api: "API" +ui.navigation.concepts: "概念" +ui.navigation.home: "首页" +ui.navigation.label: "主导航" +ui.navigation.toggle: "切换导航" +ui.outline.title: "本页导读" +ui.reference.assembly: "程序集" +ui.reference.classes: "类" +ui.reference.constructors: "构造函数" ui.reference.declaration: "C# 类型声明" -ui.reference.delegates: 委托 -ui.reference.derived: 派生类型 -ui.reference.enums: 枚举 -ui.reference.events: 事件 -ui.reference.examples: 示例 -ui.reference.exceptions: 异常 -ui.reference.extensionMethods: 扩展方法 -ui.reference.fields: 字段 -ui.reference.implementations: 显式接口实现 -ui.reference.implements: 实现 -ui.reference.inheritance: 继承 -ui.reference.inheritedMembers: 继承的成员 -ui.reference.interfaces: 接口 -ui.reference.metadata: 类型元数据 -ui.reference.methods: 方法 -ui.reference.namespace: 命名空间 -ui.reference.open: 打开 {name} 的参考文档 -ui.reference.operators: 运算符 -ui.reference.parameters: 参数 -ui.reference.properties: 属性 -ui.reference.related: 另请参阅 -ui.reference.relationships: 继承与元数据 -ui.reference.remarks: 备注 -ui.reference.returns: 返回值 -ui.reference.structs: 结构体 -ui.reference.typeParameters: 类型参数 -ui.reference.value: 值 -ui.reference.values: 值 -ui.search.close: 关闭搜索 -ui.search.empty: 没有找到与“{query}”相关的结果。 -ui.search.hint: 搜索教程、概念、示例和 API 参考。 -ui.search.loading: 正在加载搜索… -ui.search.more: 显示更多结果 -ui.search.pending: 正在搜索… -ui.search.placeholder: 您在寻找什么? -ui.search.resultCount: 结果:{count} -ui.search.title: 搜索文档 -ui.search.unavailable: 搜索暂不可用。您仍然可以直接打开下方页面。 +ui.reference.delegates: "委托" +ui.reference.derived: "派生类型" +ui.reference.enums: "枚举" +ui.reference.events: "事件" +ui.reference.examples: "示例" +ui.reference.exceptions: "异常" +ui.reference.extensionMethods: "扩展方法" +ui.reference.fields: "字段" +ui.reference.implementations: "显式接口实现" +ui.reference.implements: "实现" +ui.reference.inheritance: "继承" +ui.reference.inheritedMembers: "继承的成员" +ui.reference.interfaces: "接口" +ui.reference.metadata: "类型元数据" +ui.reference.methods: "方法" +ui.reference.namespace: "命名空间" +ui.reference.open: "打开 {name} 的参考文档" +ui.reference.operators: "运算符" +ui.reference.parameters: "参数" +ui.reference.properties: "属性" +ui.reference.related: "另请参阅" +ui.reference.relationships: "继承与元数据" +ui.reference.remarks: "备注" +ui.reference.returns: "返回值" +ui.reference.structs: "结构体" +ui.reference.typeParameters: "类型参数" +ui.reference.value: "值" +ui.reference.values: "值" +ui.search.close: "关闭搜索" +ui.search.empty: "没有找到与“{query}”相关的结果。" +ui.search.hint: "搜索教程、概念、示例和 API 参考。" +ui.search.loading: "正在加载搜索…" +ui.search.more: "显示更多结果" +ui.search.pending: "正在搜索…" +ui.search.placeholder: "输入搜索内容" +ui.search.resultCount: "结果:{count}" +ui.search.title: "搜索文档" +ui.search.unavailable: "搜索暂不可用,可直接打开下方页面。" diff --git a/documents/locales/zh-CN/translation.md b/documents/locales/zh-CN/translation.md index 5dfaef19..9fa07d83 100644 --- a/documents/locales/zh-CN/translation.md +++ b/documents/locales/zh-CN/translation.md @@ -8,6 +8,16 @@ 翻译只修改本目录 `strings.yml` 的值。键集合必须与英文完全一致,不得自行新增、删除或重命名键,包括看起来相同或暂未遇到的界面文案。如果原文存在问题,向维护者指出资源键和问题,由英文及共享页面先统一修正,再同步译文。 +## 文风与上下文 + +采用严谨、自然的技术教材文风,先解释操作之间的关系,再说明条件和限制。教程保留明确的操作步骤与可观察的结果。学术风格不等于增加被动句、抽象名词或长句。 + +按文章的阅读顺序审校,结合前后段落、表格和代码理解内容。资源键只是存储边界,不是孤立的翻译单元。链接标签和强调片段应放回完整句子检查,避免机械复述、反复请求读者操作,以及不说明实际含义的比喻。 + +标题、界面标签、首页可见的简短介绍和页脚文案不加句末句号;正文、诊断信息和无障碍操作说明保留正常标点。每个概念使用一种通行译法,不零散附加英文括注。API 标识符、文件名和实际设置项的名称保持准确;括号可用于必要解释,不作为例行的双语标注。 + +判断一句话是否需要保留,要看它是否解释当前操作、设计选择、可观察结果或正确使用的条件。删去未使用功能的罗列、泛泛的环境提醒和重复前提。标题及跨样式的短语也须整体翻译,不沿用英文语序。首页标题的 `{accent}` 与 `{lineBreak}` 可按中文调整位置,样式和换行不能决定语序。正文删改由维护者先统一更新英文、共享绑定及各语言键集合,再同步译文。 + ## 文本与占位符 使用自然、简洁的技术中文,以完整句子或段落为单位翻译,保留前提、否定、单位、操作顺序和生命周期约束。不要逐词拼接译文,也不要添加原文没有的技术保证、平台要求、包版本或发布说明。产品名、包名、文件名、C#/Slang 标识符和大小写保持原样。 @@ -49,7 +59,7 @@ docfx serve documents/_site --hostname 127.0.0.1 --port 8080 本语言已注册,完整字典经构建成功后即可使用,无需改配置。缺键、多余键、空值、非字符串值或占位符名称不匹配会导致构建失败。构建不会判断译文是否准确或是否仍残留未翻译的英文,必须人工通读。 -各语言共用页面路径,通过 `?lang=zh-CN` 选择语言,切换时保留路径和锚点。没有明确指定语言时,依次采用已保存的手动选择、浏览器语言偏好、英文。该译本尚未发布,或字典加载/页面资源校验失败时,页面回退到英文,而不是逐句混用语言。语言列表按语言代码排序。 +各语言共用页面路径,通过 `?lang=zh-CN` 选择语言,切换时保留路径和锚点。没有明确指定语言时,依次采用已保存的手动选择、浏览器语言偏好、英文。如果该译本尚未发布,或字典加载/页面资源校验失败时,页面回退到英文,而不是逐句混用语言。语言列表按语言代码排序。 交付前核对键和占位符,并在桌面及 320 像素宽度检查首页、Learn 入口、三角形教程、概念页、示例页和 API 界面。按初学者的顺序通读教程,检查术语、按钮、搜索、代码复制、API 跳转,以及切换语言后的当前章节位置。标识符、声明和代码仍使用共享原文;只翻译字典提供的界面与正文。测试字典和临时检查文件放在仓库外,不提交占位译文。 @@ -70,7 +80,7 @@ docfx serve documents/_site --hostname 127.0.0.1 --port 8080 | texture | 纹理 | | heap | 堆 | | view | 视图;区分资源视图与 UI 控件 | -| render pass | 渲染通道(render pass) | +| render pass | 渲染通道 | | render target | 渲染目标 | | color attachment | 颜色附件 | | depth/stencil | 深度/模板 | @@ -84,7 +94,7 @@ docfx serve documents/_site --hostname 127.0.0.1 --port 8080 | drawable | 当前帧的输出纹理;`Drawable` 标识符不译,不一律称为交换链图像 | | framebuffer | 帧缓冲区;尺寸以原文规定的像素单位表述 | | barrier / timeline | 屏障/时间线 | -| bindless | 首次写“无绑定(bindless)”,保留 API 标识符 | +| bindless | 无绑定;保留 API 标识符 | | upload | 上传 | | download / readback | GPU 数据语境使用“回读”;下载文件时使用“下载” | | undefined | 未定义;不能改写为某个具体默认结果 | diff --git a/documents/locales/zh-TW/strings.yml b/documents/locales/zh-TW/strings.yml index 9c4258dc..95b8b5f8 100644 --- a/documents/locales/zh-TW/strings.yml +++ b/documents/locales/zh-TW/strings.yml @@ -1,604 +1,592 @@ ### YamlMime:Resources -concepts.execution.context.description: "{graphicsContext} 代表一個後端裝置,並提供其圖形、計算與傳輸佇列。相同工作負載所需的緩衝區、紋理、著色器與管線應透過同一個圖形上下文建立。由另一個圖形上下文建立的資源或控制代碼不能直接繫結至此圖形上下文的命令緩衝區。" -concepts.execution.context.details: 依據平台與呈現表面選取後端。API 保持共用,但裝置支援度仍至關重要。{capabilities} 公開裝置名稱以及 {rayTracingSupported} 與 {meshShadingSupported} 旗標。在建立選用的工作負載之前,請像 {link} 與 {detail} 範例一樣先檢查對應的旗標。這些旗標並非格式、記憶體或平台限制的完整清單。 -concepts.execution.context.details.detail: 網格著色(mesh shading) -concepts.execution.context.details.link: 光線追蹤 -concepts.execution.context.title: 圖形上下文連接資源與佇列 -concepts.execution.description: Zenith.NET 應用程式建立 GPU 資源、記錄使用這些資源的命令,並將這些命令提交至佇列。在 GPU 執行提交項目的同時,CPU 可以繼續執行。即使記錄呼叫已經返回,仍須保持資源有效,直到該工作完成。 -concepts.execution.ownership.description: "在此處,所有權代表釋放的責任。C# 參考可保持受控物件可達;但它無法防止明確的 {dispose} 終結原生資源。同樣地,提交使用緩衝區的命令不會將該緩衝區的所有權移轉給佇列。" -concepts.execution.ownership.details: "關閉時,停止提交新工作,等待涉及的每個佇列完成對資源的最後一次使用,再釋放應用程式建立的資源,最後釋放圖形上下文。釋放上下文會釋放它自身的佇列與內部輔助物件;它不會等待所有應用程式工作,也不會釋放應用程式建立的全部資源。" -concepts.execution.ownership.guidance: "渲染期間也要遵循相同的生命週期規則。保留資源最後一次使用的完成值,以判斷何時可以覆寫其資料或取代資源。有關檢視及其底層資源的生命週期,請參閱{link}。" -concepts.execution.ownership.guidance.link: 資源管理 -concepts.execution.ownership.table.applicationResources.object: 應用程式建立的資源 -concepts.execution.ownership.table.applicationResources.ownership: 應用程式在最後一次 GPU 使用後予以處置。 -concepts.execution.ownership.table.commandBuffers.object: 借用的命令緩衝區 -concepts.execution.ownership.table.commandBuffers.ownership: 佇列管理並回收它們。 -concepts.execution.ownership.table.headings.object: 物件 -concepts.execution.ownership.table.headings.ownership: 誰來釋放? -concepts.execution.ownership.table.queues.object: 圖形上下文佇列與其時間線 -concepts.execution.ownership.table.queues.ownership: 圖形上下文與佇列管理它們。 -concepts.execution.ownership.table.swapChainDrawable.ownership: 交換鏈管理它。 -concepts.execution.ownership.title: 將所有權與 GPU 完成分開處理 -concepts.execution.pipelines.description: 圖形管線結合了著色器、頂點輸入配置、將頂點組裝為基本圖元的規則、附件格式與渲染狀態。在繫結頂點、索引或常數資料以及發出繪圖命令之前設定它。其附件格式與取樣計數必須符合渲染通道的附件。 -concepts.execution.pipelines.details: 計算管線為分派提供著色器進入點,以啟動 GPU 執行緒群組。在分派之前設定它及其常數。計算分派屬於圖形渲染通道之外。變更管線即代表後續命令解譯其輸入方式的變更;在使用所選管線之前,請繫結該管線所需的資料。 -concepts.execution.pipelines.guidance: "{link}展示了完整的圖形執行序列。{detail}記錄了一次分派,隨後透過圖形通道顯示其結果。" -concepts.execution.pipelines.guidance.detail: 計算範例 -concepts.execution.pipelines.guidance.link: 三角形的渲染回呼 -concepts.execution.pipelines.title: 管線決定命令如何解譯資料 -concepts.execution.queues.description: 當單一影格結合了繪圖、計算與複製時,請從 {graphicsQueue} 開始。將相依的工作保持在單一佇列上可讓其順序更容易追蹤。 -concepts.execution.queues.details: 佇列接受批次命令以供執行。個別佇列不一定對應到個別的硬體引擎,因此它們的工作可能無法同時執行。當工作負載能從重疊執行中獲益時請使用其他佇列,並在某個佇列耗用另一個佇列的結果時新增明確的相依性。 -concepts.execution.queues.guidance: 當後續命令相依於先前的寫入時,應用程式還必須確保這些寫入對後續命令而言可用。將兩個命令緩衝區提交至相同佇列並不會自動建立所有這類相依性。命令可能會使用不同的 GPU 階段,且後續存取可能需要屏障或紋理轉換。{link}說明了提交順序與資源可見度之間的區別。 -concepts.execution.queues.guidance.link: 同步 -concepts.execution.queues.table.computeQueue.workToRecord: 計算分派與相容的傳輸工作,不包含圖形渲染通道。 -concepts.execution.queues.table.graphicsQueue.workToRecord: 渲染通道與繪圖,加上影格所使用的計算與傳輸操作。 -concepts.execution.queues.table.headings.queue: 佇列 -concepts.execution.queues.table.headings.workToRecord: 要記錄的工作 -concepts.execution.queues.table.transferQueue.workToRecord: 上傳、回讀與複製工作,不包含繪圖或計算分派。 -concepts.execution.queues.title: 依據欲執行的工作選擇佇列 -concepts.execution.recording.context: 佇列會輪詢完成狀態並回收完成的命令緩衝區。為每次新記錄呼叫 {queueCommandBuffer};它可能會傳回回收的執行個體。請勿處置借用的命令緩衝區、請勿重複提交兩次,也不要在提交後繼續向其中記錄。給定的命令緩衝區一次僅由一個執行緒進行記錄;佇列的內部鎖定無法防止對命令緩衝區的並行編輯。 -concepts.execution.recording.description: "{queueCommandBuffer} 會傳回已開始記錄的 {commandBuffer}。記錄命令及其相依性,接著呼叫 {submit} 一次。提交會結束記錄,並傳回識別該佇列上完成點的 {timelineValue}。" -concepts.execution.recording.details: 例如,在將影格記錄至 {commandBuffer} 後,三角形教學會提交它並等待完成: -concepts.execution.recording.guidance: "{submit} 排程工作;{wait} 防止 CPU 繼續執行,直到該提交完成為止。記錄繪製、結束渲染通道與提交命令緩衝區是個別分開的操作。記錄繪製與結束通道皆不會等待 GPU。" -concepts.execution.recording.title: 記錄不會執行命令 -concepts.execution.title: 執行模型 -concepts.platforms.description: 選擇您的應用程式是自行擁有原生視窗與影格迴圈,還是使用 UI 渲染控制項。該選擇決定了誰取得輸出紋理、提交命令並呈現結果。輸出紋理是用作目前影格輸出的紋理。螢幕外圖形與計算工作不需要視窗或交換鏈。 -concepts.platforms.frame.context: 在該通道內部新增您的管線繫結與繪圖命令。在返回之前結束通道。不要獨立提交提供的命令緩衝區或自行呈現,也不要處置命令緩衝區或輸出紋理。如果您的處理常式在另一種配置中使用輸出紋理,請將其恢復為 {colorAttachment} 以進行控制項的最終轉換。 -concepts.platforms.frame.description: 這些整合實作了 {iZenithView}。應用程式提供其 {graphicsContext},在 {updateRequested} 中更新場景資料,並使用 {renderEventArgs} 在 {renderRequested} 中記錄渲染。 -concepts.platforms.frame.details: "控制項負責每個影格的完整流程:取得輸出紋理與命令緩衝區,將輸出紋理轉換為 {colorAttachment},叫用處理常式,然後執行該框架所需的提交與呈現步驟。" -concepts.platforms.frame.guidance: "對於名為 {view}、已完成初始化且已指派圖形上下文的 {iZenithView},此處理常式會記錄一個完整的清除通道。它需要 {usingZenithNET}:" -concepts.platforms.frame.notes: "控制項在每個影格開始時皆從 {undefined} 轉換,因此應用程式不能依賴保留輸出紋理的先前內容。每個影格皆請清除或渲染所需的影像。將持續累加或快取的渲染內容保留在應用程式自身的紋理中,然後透過檢視顯示該紋理。" -concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat} 提供整合的預設色彩格式。在比對附件格式、取樣計數與尺寸時,請檢查實際事件中的輸出紋理。" -concepts.platforms.frame.title: 記錄至 UI 控制項提供的影格中 -concepts.platforms.integration.context: WinForms、WPF 與 Windows 的 WinUI 路徑需要 Windows。MAUI 應用程式需要其目標平台的工作負載,且必須使用 {useZenithView} 註冊控制項處理常式;請參閱 {extensionsCs}。架構支援與後端支援都必須滿足。 -concepts.platforms.integration.description: 控制項共用事件介面,但呈現方式並非全部相同: -concepts.platforms.integration.details: 點陣圖回讀(bitmap readback)在 UI 顯示之前將渲染的像素複製至 CPU 記憶體中。共用紋理互通避免了該回讀,但仍可能需要 GPU 複製與同步。因此,共用的 {renderRequested} 介面並不代表相同的呈現成本或原生互通需求。 -concepts.platforms.integration.guidance: 使用適合應用程式架構的套件;例如: -concepts.platforms.integration.table.avalonia.integration: Avalonia -concepts.platforms.integration.table.avalonia.presentation: "渲染至紋理,再將像素回讀至 {writeableBitmap}。請參閱 {zenithViewCs} 與 {surfaceCs}。" -concepts.platforms.integration.table.headings.integration: 整合 -concepts.platforms.integration.table.headings.presentation: 影像如何到達 UI -concepts.platforms.integration.table.maui.integration: .NET MAUI -concepts.platforms.integration.table.maui.presentation: 在 Android、iOS 與 Mac Catalyst 上使用原生呈現目標,在 Windows 上使用共用紋理合成。請參閱{link}。 -concepts.platforms.integration.table.maui.presentation.link: 平台實作 -concepts.platforms.integration.table.uno.integration: Uno 路徑 -concepts.platforms.integration.table.uno.presentation: "將像素回讀至 {writeableBitmap}。請參閱 {zenithViewUnoCs}。" -concepts.platforms.integration.table.winForms.integration: WinForms -concepts.platforms.integration.table.winForms.presentation: 為控制項的 {hWND} 建立 Zenith.NET 交換鏈。請參閱 {zenithViewCs}。 -concepts.platforms.integration.table.winUI.integration: Windows 上的 WinUI -concepts.platforms.integration.table.winUI.presentation: 渲染至匯入的共用 Direct3D 11 紋理,接著複製到附加至 {swapChainPanel} 的合成交換鏈。請參閱 {zenithViewWinUICs}。 -concepts.platforms.integration.table.wpf.integration: WPF -concepts.platforms.integration.table.wpf.presentation: 匯入共用 Direct3D 11 紋理,接著透過 Direct3D 互通複製到由 {d3DImage} 顯示的表面。請參閱 {surfaceCs}。 -concepts.platforms.integration.title: 選擇呈現路徑以及架構 -concepts.platforms.lifecycle.context: 對於 UI 檢視,在建立相符的渲染資源時,使用事件輸出紋理的 {descWidth}、{descHeight}、{descFormat} 與 {descSampleCount}。控制項決定該輸出紋理的解析度;不要假設其邏輯尺寸或顯示比例一律等於紋理尺寸。 -concepts.platforms.lifecycle.description: 對於原生交換鏈,請以像素為單位傳遞畫面緩衝區尺寸。啟用顯示比例縮放時,以邏輯單位表示的視窗大小可能會有所不同。略過零大小的畫面緩衝區,在像素大小變更時調整交換鏈大小,並為每個影格取得 {swapChainDrawable}。輸出紋理歸交換鏈所有,且可能會在呈現或調整大小後變更。 -concepts.platforms.lifecycle.details: "{swapChainResize} 會變更現有呈現目標的尺寸。{swapChainRefresh} 會取代呈現目標描述,包括原生控制代碼。在執行任一作業前,應先完成對受影響資源的所有未完成存取。銷毀原生呈現目標前,應先釋放交換鏈。" -concepts.platforms.lifecycle.guidance: "重新建立尺寸跟隨視窗變更的應用程式自身深度或螢幕外紋理,並更新包含其控制代碼的常數。當附件格式與取樣計數維持相容時,管線可以在尺寸變更後繼續使用。{link}在取代深度紋理的同時保留了其管線。" -concepts.platforms.lifecycle.guidance.link: 旋轉立方體渲染器 -concepts.platforms.lifecycle.title: "讓輸出紋理的尺寸與生命週期配合宿主" -concepts.platforms.ownership.description: "應用程式擁有其指派的圖形上下文以及為渲染所建立的資源。控制項擁有其自身的呈現資源。變更檢視的 {graphicsContext} 屬性會使排程器重新建立控制項的資源;它不會為新上下文重新建立應用程式的管線、緩衝區或紋理。" -concepts.platforms.ownership.details: 將資源取代與檢視的影格生命週期相互協調。在處置應用程式資源或指派的上下文之前,停止檢視的影格活動並完成未決的 GPU 使用。移除檢視不會將上下文所有權移轉給控制項。 -concepts.platforms.ownership.guidance: 共用的 {frameSchedulerCs} 透過檢視的 UI 發送器發送影格工作。保持影格處理常式聚焦於更新與記錄影格;該處過長的 CPU 工作也會延遲 UI。 -concepts.platforms.ownership.title: 將應用程式資源保持在控制項所有權之外 -concepts.platforms.surface.context: 視窗程式庫或 UI 架構支援作業系統並不保證所選的 GPU 後端在該處可用。裝置功能、驅動程式與原生表面支援仍必須相符。在建立這些工作負載之前,請透過 {contextCapabilities} 檢查選用的光線追蹤與網格著色(mesh shading)。 -concepts.platforms.surface.description: "{link}使用 Silk.NET 建立視窗並處理事件。Zenith.NET 透過 {surface} 描述與 {swapChain} 連接至該視窗。表面包含原生控制代碼與尺寸;建構該描述並不會建立或擁有作業系統視窗。" -concepts.platforms.surface.description.link: 三角形教學 -concepts.platforms.surface.details: 控制代碼必須與所選後端相符: -concepts.platforms.surface.guidance: "教學的 {appCs} 顯示了 Windows、macOS 與 X11 的選項。其 Linux 宿主程式提供 Xlib 控制代碼;在 Wayland 工作階段中使用它需要 XWayland。原生 Wayland 應用程式將透過 {surfaceWayland} 提供不同的控制代碼。" -concepts.platforms.surface.table.android.backend: Android 上的 Vulkan。 -concepts.platforms.surface.table.apple.backend: Apple 平台上的 Metal。 -concepts.platforms.surface.table.headings.backend: 後端路徑 +concepts.execution.context.description: "{graphicsContext} 透過特定後端連接應用程式與 GPU 裝置,並提供圖形、計算與傳輸佇列。一起使用的資源必須屬於同一上下文;緩衝區、紋理、著色器、管線及其控制代碼不能跨上下文繫結。" +concepts.execution.context.details: "{capabilities} 提供裝置名稱與支援的功能。建立光線追蹤或網格著色所需的資源前,分別透過 {rayTracingSupported} 與 {meshShadingSupported} 確認支援情況。{link}與{detail}範例展示了初始化時的檢查方式。" +concepts.execution.context.details.detail: "網格著色" +concepts.execution.context.details.link: "光線追蹤" +concepts.execution.context.title: "圖形上下文" +concepts.execution.description: "GPU 工作從 CPU 端開始準備:應用程式建立資源,記錄使用這些資源的命令,再提交到佇列。提交後,CPU 可以繼續處理其他工作,同時由 GPU 執行命令。相關資源必須保留到 GPU 執行結束。" +concepts.execution.ownership.description: "所有權決定由誰釋放物件,GPU 完成狀態決定何時可以釋放。即使仍保留物件的 C# 參考,呼叫 {dispose} 也會釋放其原生資源。提交命令不會將資源所有權轉交給佇列。" +concepts.execution.ownership.details: "結束程式時,先停止提交新工作,並等待所有相關佇列完成最後一次資源存取。接著釋放應用程式資源,最後釋放上下文。上下文會釋放自身的佇列與內部輔助物件,因此這一步必須在應用程式工作全部完成後進行。" +concepts.execution.ownership.guidance: "渲染期間,若準備覆寫資料或替換資源,就應追蹤仍在使用它們的工作。等待這些存取完成後,再修改資料或釋放儲存空間。檢視與底層資源如何遵循這個生命週期規則,見{link}。" +concepts.execution.ownership.guidance.link: "資源管理" +concepts.execution.ownership.table.applicationResources.object: "應用程式建立的資源" +concepts.execution.ownership.table.applicationResources.ownership: "最後一次 GPU 使用完成後,由應用程式釋放。" +concepts.execution.ownership.table.commandBuffers.object: "借用的命令緩衝區" +concepts.execution.ownership.table.commandBuffers.ownership: "由佇列管理和回收。" +concepts.execution.ownership.table.headings.object: "物件" +concepts.execution.ownership.table.headings.ownership: "釋放責任" +concepts.execution.ownership.table.queues.object: "圖形上下文佇列與其時間線" +concepts.execution.ownership.table.queues.ownership: "由上下文和佇列管理。" +concepts.execution.ownership.table.swapChainDrawable.ownership: "由交換鏈管理。" +concepts.execution.ownership.title: "所有權與生命週期" +concepts.execution.pipelines.description: "圖形管線規定繪製所用的著色器、頂點輸入佈局、圖元組裝方式、附件格式和渲染狀態。繫結頂點、索引或常數資料之前,須先選擇管線;管線宣告的附件格式與取樣數也必須與渲染通道一致。" +concepts.execution.pipelines.details: "計算管線選擇分派所執行的著色器進入點。在圖形渲染通道之外,先繫結管線及其常數,再執行分派。" +concepts.execution.pipelines.guidance: "{link}給出了完整的圖形命令順序。{detail}則先執行計算分派,再透過圖形通道顯示結果。" +concepts.execution.pipelines.guidance.detail: "計算範例" +concepts.execution.pipelines.guidance.link: "三角形的渲染回呼" +concepts.execution.pipelines.title: "管線狀態" +concepts.execution.queues.description: "一個影格同時包含繪製、計算與複製時,通常從 {graphicsQueue} 開始。將彼此相依的操作放在同一佇列,能簡化順序管理。" +concepts.execution.queues.details: "不同佇列可分別接收獨立的工作負載,但未必對應獨立的硬體引擎。若工作能從重疊執行中受益,再考慮增加佇列。當一個佇列使用另一個佇列產生的資料時,需要在兩次提交之間建立明確的相依關係。" +concepts.execution.queues.guidance: "即使位於同一佇列,彼此相依的操作也可能需要屏障或紋理轉換,讓後續存取讀到先前寫入的結果。這種記憶體相依關係與提交順序不同,具體指定方式見{link}。" +concepts.execution.queues.guidance.link: "同步" +concepts.execution.queues.table.computeQueue.workToRecord: "計算分派與相容的傳輸工作,不包含圖形渲染通道。" +concepts.execution.queues.table.graphicsQueue.workToRecord: "渲染通道、繪製、計算與傳輸操作。" +concepts.execution.queues.table.headings.queue: "佇列" +concepts.execution.queues.table.headings.workToRecord: "支援的工作" +concepts.execution.queues.table.transferQueue.workToRecord: "上傳、回讀與複製工作,不包含繪圖或計算分派。" +concepts.execution.queues.title: "佇列選擇" +concepts.execution.recording.context: "佇列會回收已完成的命令緩衝區以供重複使用。每次記錄時,透過 {queueCommandBuffer} 取得緩衝區,同一時間只由一個執行緒記錄,而且只提交一次。提交後交由佇列管理,不再修改、重複提交或自行釋放。" +concepts.execution.recording.description: "{queueCommandBuffer} 傳回的 {commandBuffer} 已開始記錄。完成操作及其相依關係的記錄後,呼叫一次 {submit},結束記錄並提交命令。傳回的 {timelineValue} 識別這次提交在佇列上的完成點。" +concepts.execution.recording.details: "三角形教學將一個影格記錄到 {commandBuffer} 後,按如下方式提交並等待完成:" +concepts.execution.recording.guidance: "記錄會建立命令序列,{submit} 則安排該序列執行。接著呼叫 {wait},CPU 執行緒便會等待這次提交完成。教學因此採用逐影格執行的流程:目前影格完成後,才開始下一個影格。" +concepts.execution.recording.title: "記錄與提交" +concepts.execution.title: "執行模型" +concepts.platforms.description: "呈現流程可以由應用程式管理,也可以交給 UI 渲染控制項。這決定了誰來取得目前影格的輸出紋理、記錄與提交命令,以及顯示渲染結果。" +concepts.platforms.frame.context: "在通道內繫結管線並記錄繪製命令,處理程式返回前須結束通道。控制項負責提交命令與呈現結果;處理程式不可自行提交命令緩衝區,也不可釋放傳入的命令緩衝區或輸出紋理。若改變了輸出紋理的佈局,返回前須恢復為 {colorAttachment},讓控制項能完成最後的轉換。" +concepts.platforms.frame.description: "各控制項實作 {iZenithView} 介面。應用程式設定 {graphicsContext},在 {updateRequested} 中更新場景,並在 {renderRequested} 中透過傳入的 {renderEventArgs} 記錄命令。" +concepts.platforms.frame.details: "每個影格中,控制項會取得輸出紋理與命令緩衝區,將輸出紋理轉換為 {colorAttachment},再呼叫更新和渲染處理程式。之後,控制項提交已記錄的工作,並透過對應框架的呈現機制顯示影像。" +concepts.platforms.frame.guidance: "先在檔案中加入 {usingZenithNET}。假定名為 {view} 的 {iZenithView} 執行個體已初始化,且已設定圖形上下文,可註冊以下處理程式來清除其輸出紋理:" +concepts.platforms.frame.notes: "初始轉換使用 {undefined},允許丟棄先前影像的內容。因此,每個影格都應重新繪製或清除整張影像。需要累積或快取的渲染結果,可儲存在應用程式擁有的紋理中,再將該紋理繪製到控制項的輸出紋理上。" +concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat} 提供這些整合使用的預設色彩格式。" +concepts.platforms.frame.title: "透過 UI 控制項渲染" +concepts.platforms.integration.context: "WinForms、WPF 與 Windows 版 WinUI 整合在 Windows 上執行。使用 MAUI 時,安裝目標平台的工作負載,並透過 {useZenithView} 註冊控制項處理程式,具體見 {extensionsCs}。" +concepts.platforms.integration.description: "控制項共用事件介面,但呈現機制因框架而異:" +concepts.platforms.integration.details: "各實作將 GPU 影像送到 UI 的方式不同。點陣圖回讀先將像素複製到 CPU 記憶體,再顯示影像;共用紋理互通能省去這次 CPU 複製,但仍可能需要 GPU 複製與同步。選擇整合方式時,除了共用的 {renderRequested} 事件介面,也應考慮其呈現方式。" +concepts.platforms.integration.guidance: "透過 NuGet 加入所用 UI 框架的整合套件。Avalonia 對應的套件為 {avaloniaPackage}。" +concepts.platforms.integration.table.avalonia.integration: "Avalonia" +concepts.platforms.integration.table.avalonia.presentation: "渲染到紋理後,將像素回讀到 {writeableBitmap},實作見 {zenithViewCs} 和 {surfaceCs}。" +concepts.platforms.integration.table.headings.integration: "整合" +concepts.platforms.integration.table.headings.presentation: "呈現機制" +concepts.platforms.integration.table.maui.integration: ".NET MAUI" +concepts.platforms.integration.table.maui.presentation: "Android、iOS 和 Mac Catalyst 使用原生呈現目標;Windows 使用共用紋理合成,具體見{link}。" +concepts.platforms.integration.table.maui.presentation.link: "平台實作" +concepts.platforms.integration.table.uno.integration: "Uno 路徑" +concepts.platforms.integration.table.uno.presentation: "將像素回讀到 {writeableBitmap},實作見 {zenithViewUnoCs}。" +concepts.platforms.integration.table.winForms.integration: "WinForms" +concepts.platforms.integration.table.winForms.presentation: "為控制項的 {hWND} 建立 Zenith.NET 交換鏈,實作見 {zenithViewCs}。" +concepts.platforms.integration.table.winUI.integration: "Windows 上的 WinUI" +concepts.platforms.integration.table.winUI.presentation: "渲染到匯入的共用 Direct3D 11 紋理,再複製到與 {swapChainPanel} 連線的合成交換鏈,具體見 {zenithViewWinUICs}。" +concepts.platforms.integration.table.wpf.integration: "WPF" +concepts.platforms.integration.table.wpf.presentation: "匯入共用 Direct3D 11 紋理,再經 Direct3D 互通複製到由 {d3DImage} 顯示的表面,具體見 {surfaceCs}。" +concepts.platforms.integration.title: "框架與呈現路徑" +concepts.platforms.lifecycle.context: "建立配套附件時,使用渲染事件傳入的輸出紋理的 {descWidth}、{descHeight}、{descFormat} 與 {descSampleCount}。該紋理提供渲染目標的實際尺寸,不應依控制項的版面配置尺寸或顯示縮放比例推算。" +concepts.platforms.lifecycle.description: "交換鏈使用以像素計量的畫面緩衝區寬度與高度。啟用顯示縮放時,這些值可能不同於視窗的邏輯尺寸。任一尺寸為零時,暫停渲染與交換鏈尺寸調整。每個影格重新取得 {swapChainDrawable}:這張紋理由交換鏈管理,可能在呈現或調整大小後被替換。" +concepts.platforms.lifecycle.details: "畫面緩衝區尺寸改變時,先等待 GPU 完成對舊影像的存取,再呼叫 {swapChainResize}。替換原生呈現目標時,也應先等待這些存取結束,再將新的目標描述與控制代碼傳給 {swapChainRefresh}。結束程式時,先釋放交換鏈,再銷毀其原生呈現目標。" +concepts.platforms.lifecycle.guidance: "應用程式的深度紋理或離屏紋理若隨視窗尺寸改變,就需要在調整大小時重建,並更新包含其控制代碼的常數。只要附件格式與取樣數仍然相符,管線就可以繼續使用。{link}展示了如何調整紋理尺寸並保留管線。" +concepts.platforms.lifecycle.guidance.link: "旋轉立方體渲染器" +concepts.platforms.lifecycle.title: "交換鏈尺寸與生命週期" +concepts.platforms.ownership.description: "應用程式擁有所設定的上下文及其渲染資源,控制項擁有呈現資源。檢視的 {graphicsContext} 改變後,排程程式會為新上下文重建控制項資源。應用程式也須為該上下文重建自己的管線、緩衝區與紋理。" +concepts.platforms.ownership.details: "替換渲染資源前,先停止檢視的影格活動,並等待使用這些資源的 GPU 工作完成,再釋放舊資源或上下文。移除檢視後,所設定的上下文仍由應用程式負責釋放。" +concepts.platforms.ownership.guidance: "共用的 {frameSchedulerCs} 透過檢視的 UI 排程器執行影格處理程式。處理程式應專注於場景資料更新與命令記錄,其中耗時的 CPU 工作也會延遲介面回應。" +concepts.platforms.ownership.title: "應用程式與控制項的責任" +concepts.platforms.surface.description: "{link}使用 Silk.NET 建立視窗並處理事件。Zenith.NET 透過 {surface} 描述取得原生視窗控制代碼與尺寸,再據此建立 {swapChain}。作業系統視窗仍由應用程式負責管理。" +concepts.platforms.surface.description.link: "三角形教學" +concepts.platforms.surface.details: "原生控制代碼必須與所選後端匹配:" +concepts.platforms.surface.guidance: "{appCs} 中的範例宿主支援 Windows、macOS 與 X11。Linux 視窗提供 Xlib 控制代碼,因此在 Wayland 工作階段中需要 XWayland。原生 Wayland 應用程式則透過 {surfaceWayland} 提供顯示與表面的控制代碼。" +concepts.platforms.surface.table.android.backend: "Android 上的 Vulkan。" +concepts.platforms.surface.table.apple.backend: "Apple 平台上的 Metal。" +concepts.platforms.surface.table.headings.backend: "後端與平台" concepts.platforms.surface.table.headings.factory: "呈現目標工廠方法" concepts.platforms.surface.table.headings.handles: "宿主程式提供的控制代碼" concepts.platforms.surface.table.wayland.backend: "具有原生 Wayland 宿主程式的 Vulkan。" -concepts.platforms.surface.table.wayland.handles: Wayland 顯示與表面 -concepts.platforms.surface.table.win32.backend: Windows 上的 DirectX 12 或 Vulkan。 -concepts.platforms.surface.table.xlib.backend: Linux 上帶有 X11 或 XWayland 的 Vulkan。 -concepts.platforms.surface.table.xlib.handles: X11 顯示與視窗 -concepts.platforms.surface.title: 當應用程式擁有呈現時提供原生呈現目標 -concepts.platforms.title: 平台整合 -concepts.resources.allocation.context: "除非需要自行實作記憶體配置器,否則先使用圖形上下文建立的資源。使用堆積時,應先等待所有使用這些資源的 GPU 工作完成,再釋放堆積中放置的資源,最後釋放堆積本身。" -concepts.resources.allocation.description: "{heap} 提供記憶體,供您在指定的位元組位移處放置資源。應用程式負責選擇這些位移,並追蹤哪些區域正在使用。" -concepts.resources.allocation.details: "放置資源前,使用準確的緩衝區或紋理描述呼叫 {contextGetSizeAndAlignment}。所選位移必須是傳回對齊值的整數倍,預留空間必須滿足傳回的大小,資源也必須位於堆積的總位元組範圍內。仍在使用的配置區域不得重疊。紋理儲存空間可能包含後端特有的填補與對齊,因此不能以像素數量乘以每像素位元組數來計算配置大小。" -concepts.resources.allocation.guidance: "對於放置於堆積的緩衝區,其記憶體駐留設定應與堆積一致。這裡介紹的一般 GPU 紋理應使用僅供 GPU 使用的堆積。大小與對齊是放置資源的要求,並不保證所有後端都能將任意資源放入任意堆積。" -concepts.resources.allocation.title: 在需要配置控制時將資源放置於堆積中 -concepts.resources.bufferUsages.table.constant.role: 透過常數緩衝區繫結讀取的著色器參數。 +concepts.platforms.surface.table.wayland.handles: "Wayland 顯示與表面" +concepts.platforms.surface.table.win32.backend: "Windows 上的 DirectX 12 或 Vulkan。" +concepts.platforms.surface.table.xlib.backend: "Linux 上帶有 X11 或 XWayland 的 Vulkan。" +concepts.platforms.surface.table.xlib.handles: "X11 顯示與視窗" +concepts.platforms.surface.title: "原生呈現目標" +concepts.platforms.title: "平台整合" +concepts.resources.allocation.context: "放置在堆積中的資源,在整個生命週期內都依賴堆積的儲存空間。最後一次 GPU 使用完成後,應先釋放資源,再釋放堆積。" +concepts.resources.allocation.description: "應用程式需要自行管理記憶體配置時,可以使用 {heap}。堆積為資源提供儲存空間,應用程式選擇明確的位元組位移來放置資源,並記錄各區域的使用情況。" +concepts.resources.allocation.details: "對每個資源,使用建立時所需的緩衝區或紋理描述呼叫 {contextGetSizeAndAlignment}。依傳回的大小預留空間,起始位移須為傳回對齊值的整數倍,而且整個區域須位於堆積內,不與其他仍有效的配置重疊。紋理可能包含後端特有的填充,因此不能只依像素數量與每像素位元組數計算配置大小。" +concepts.resources.allocation.guidance: "放置在堆積中的緩衝區,必須使用與堆積相同的駐留設定。紋理儲存使用 GPU 專用堆積。" +concepts.resources.allocation.title: "堆積配置" +concepts.resources.bufferUsages.table.constant.role: "透過常數緩衝區繫結讀取的著色器參數。" concepts.resources.bufferUsages.table.headings.role: "作用" -concepts.resources.bufferUsages.table.headings.usage: 用途 -concepts.resources.bufferUsages.table.index.role: 索引繪圖所使用的索引。 +concepts.resources.bufferUsages.table.headings.usage: "用途" +concepts.resources.bufferUsages.table.index.role: "索引繪圖所使用的索引。" concepts.resources.bufferUsages.table.indirect.role: "間接繪製或分派命令讀取的引數。" concepts.resources.bufferUsages.table.none.role: "未宣告任何緩衝區用途旗標。" concepts.resources.bufferUsages.table.storageReadOnly.role: "透過唯讀著色器繫結存取的緩衝區資料。" concepts.resources.bufferUsages.table.storageReadWrite.role: "透過讀寫著色器繫結存取的緩衝區資料。" concepts.resources.bufferUsages.table.transferDst.role: "GPU 複製作業的目的地儲存空間。" concepts.resources.bufferUsages.table.transferSrc.role: "GPU 複製作業的來源資料。" -concepts.resources.bufferUsages.table.vertex.role: 為繪製擷取的頂點屬性。 -concepts.resources.bufferUsages.title: 緩衝區用途 -concepts.resources.description: "依據將要使用資源的作業選擇資源描述。如果一個紋理既要接收渲染結果,又要供著色器取樣,還要回讀至 CPU,就需要宣告這三種用途,並處理作業之間的同步。記憶體放置位置與資源生命週期則是另外需要考慮的問題。" -concepts.resources.memory.context: 對於 CPU 可存取的緩衝區,{map} 會提供位址給 CPU。它不會等待 GPU 停止存取相同的位元組。{unmap} 同樣不會提交工作或等待完成。在覆寫 CPU 可寫入資料之前,請先完成仍需要其舊內容的 GPU 讀取。 -concepts.resources.memory.description: "{bufferDesc} 具有 {residency} 欄位。請依據 CPU 與 GPU 將如何存取資料來選擇:" -concepts.resources.memory.details: 記憶體駐留描述對配置預期的 CPU 存取。它並不代表每部裝置皆具有實體獨立的 CPU 與 GPU 記憶體。三角形教學使用 {cpuWriteOnly} 直接初始化小型頂點緩衝區。大型靜態網格則可改為從單次上傳的僅 GPU 儲存空間中獲益。 -concepts.resources.memory.guidance: "{textureDesc} 沒有記憶體駐留欄位。由圖形上下文建立的一般紋理使用 GPU 儲存空間。其公用 API 提供上傳與回讀作業來傳輸 CPU 資料,但不提供直接對應記憶體的方法。明確指定的堆積提供記憶體放置控制,下文將介紹。" -concepts.resources.memory.table.cpuReadOnly.cPUAccess: "在 GPU 複製完成後讀取對應的記憶體。" +concepts.resources.bufferUsages.table.vertex.role: "供繪製命令讀取的頂點屬性。" +concepts.resources.bufferUsages.title: "緩衝區用途" +concepts.resources.description: "資源描述規定應用程式如何使用其儲存空間。例如,一張紋理若要作為渲染目標、供著色器取樣,並將內容複製回 CPU,就需要宣告這三種操作的用途。記憶體放置決定 CPU 的存取方式,同步與生命週期管理則決定何時可以存取資料或釋放儲存空間。" +concepts.resources.memory.context: "對於 CPU 可存取的緩衝區,{map} 提供 CPU 讀寫資料所用的位址。映射與 {unmap} 都不會等待 GPU 工作。CPU 讀取 GPU 寫入的結果前,應用程式須先等待寫入完成;修改同一塊記憶體前,也須等待 GPU 對這些位元組的存取結束。" +concepts.resources.memory.description: "{bufferDesc} 的 {residency} 欄位指定 CPU 對所配置記憶體的預期存取方式:" +concepts.resources.memory.details: "駐留設定表達 CPU 的存取需求,即使 CPU 與 GPU 共用實體記憶體也同樣適用。三角形教學使用 {cpuWriteOnly} 直接初始化小型頂點緩衝區。較大的靜態幾何資料,則可考慮上傳到 GPU 專用儲存空間。" +concepts.resources.memory.guidance: "透過上下文直接建立的紋理使用 GPU 儲存空間,因此 {textureDesc} 沒有駐留欄位。應用程式透過上傳與回讀,在紋理與 CPU 記憶體之間交換資料。" +concepts.resources.memory.table.cpuReadOnly.cPUAccess: "唯讀" concepts.resources.memory.table.cpuReadOnly.typicalRole: "GPU 產生的回讀資料" -concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "在先前的 GPU 讀取完成後寫入對應的記憶體。" +concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "唯寫" concepts.resources.memory.table.cpuWriteOnly.typicalRole: "CPU 提供或更新的資料" -concepts.resources.memory.table.gpuOnly.cPUAccess: "透過上傳緩衝區或回讀緩衝區傳輸位元組。" +concepts.resources.memory.table.gpuOnly.cPUAccess: "無" concepts.resources.memory.table.gpuOnly.typicalRole: "靜態幾何體與 GPU 工作資料" -concepts.resources.memory.table.headings.cPUAccess: CPU 存取 -concepts.resources.memory.table.headings.residency: 記憶體駐留 +concepts.resources.memory.table.headings.cPUAccess: "預期 CPU 存取" +concepts.resources.memory.table.headings.residency: "記憶體駐留" concepts.resources.memory.table.headings.typicalRole: "典型用途" -concepts.resources.memory.title: "依所需的 CPU 存取方式選擇記憶體" -concepts.resources.textureUsages.description: "傳輸用途旗標描述 GPU 複製的方向。CPU 存取則是另一項記憶體放置選擇,下文將介紹。" -concepts.resources.textureUsages.details: "組合用途旗標只是宣告多個作用,不會執行對應作業,也不會安排存取順序。紋理仍然需要適當的{link},而且其格式必須在所選裝置上支援要求的用途。" -concepts.resources.textureUsages.details.link: "配置與同步" +concepts.resources.memory.title: "CPU 存取與記憶體放置" +concepts.resources.textureUsages.description: "傳輸旗標宣告資源在 GPU 複製中作為來源或目標。CPU 能否直接存取這塊儲存空間,則由記憶體放置方式決定。" +concepts.resources.textureUsages.details: "用途旗標宣告紋理可以發揮的作用。在這些作用之間切換時,需要對應的{link};所選裝置也必須支援以該紋理格式執行所宣告的操作。" +concepts.resources.textureUsages.details.link: "佈局與同步" concepts.resources.textureUsages.table.colorAttachment.role: "渲染通道中的色彩附件。" concepts.resources.textureUsages.table.depthStencilAttachment.role: "渲染通道中的深度/樣板附件。" concepts.resources.textureUsages.table.headings.role: "作用" -concepts.resources.textureUsages.table.headings.usage: 用途 +concepts.resources.textureUsages.table.headings.usage: "用途" concepts.resources.textureUsages.table.none.role: "未宣告任何紋理用途旗標。" concepts.resources.textureUsages.table.sampled.role: "透過取樣紋理繫結讀取的紋理資料。" concepts.resources.textureUsages.table.storage.role: "透過儲存紋理繫結供著色器讀取或寫入的紋理資料。" concepts.resources.textureUsages.table.transferDst.role: "GPU 複製作業的目的地影像儲存空間。" concepts.resources.textureUsages.table.transferSrc.role: "GPU 複製作業的來源影像資料。" -concepts.resources.textureUsages.title: 紋理用途 -concepts.resources.title: 資源管理 -concepts.resources.transfers.context: "回讀作業會記錄一條將 GPU 資料複製至內部回讀儲存空間的命令。當程式庫重設已完成的命令緩衝區以供重複使用時,才會將這些位元組複製至提供的 CPU 目的地。在該提交完成值的 {wait} 返回之前,目的地記憶體必須保持已配置狀態,受控記憶體也必須保持釘選。" -concepts.resources.transfers.description: "上傳將 CPU 資料複製至 GPU 資源,回讀將資源資料複製回 CPU 記憶體。資源本身提供的方法會在返回前完成該次傳輸:" -concepts.resources.transfers.details: "這些等待只涵蓋方法本身提交的傳輸。它們不會發現另一個佇列上既有讀寫作業對該資源的相依性。呼叫資源本身的傳輸方法前,應先建立這些相依性。直接透過對應記憶體複製資料時,也需要呼叫端確保相關 GPU 工作已完成。" -concepts.resources.transfers.guidance: 當複製作業應與其他工作一起記錄時,請使用 {commandBufferUpload} 或 {commandBufferDownload}。其指標生命週期各有不同: -concepts.resources.transfers.item: "上傳會在呼叫期間將 CPU 來源資料複製至內部上傳緩衝區,也稱暫存記憶體。來源指標只需在該次呼叫期間保持有效。" -concepts.resources.transfers.notes: "對於紋理,列跨距是 CPU 資料相鄰兩列之間的位元組距離,切片跨距是相鄰深度切片之間的位元組距離。它們並不代表紋理內部的 GPU 記憶體配置。有關工作完成與資料回讀的區別,請參閱{link}。" -concepts.resources.transfers.notes.link: 同步 -concepts.resources.transfers.table.bufferDownload.transfer: 針對 {cpuReadOnly} 進行直接 CPU 複製;否則在傳輸佇列上提交下載並等待。 -concepts.resources.transfers.table.bufferUpload.transfer: 針對 {cpuWriteOnly} 進行直接 CPU 複製;否則在傳輸佇列上提交上傳並等待。 -concepts.resources.transfers.table.headings.method: 方法 -concepts.resources.transfers.table.headings.transfer: "資料傳輸方式" +concepts.resources.textureUsages.title: "紋理用途" +concepts.resources.title: "資源管理" +concepts.resources.transfers.context: "回讀先將 GPU 資料複製到內部回讀空間。程式庫回收已完成的命令緩衝區時,再將資料複製到指定的 CPU 目標。對這次回讀提交的完成值呼叫 {wait},可以完成這兩個步驟。在呼叫返回前,目標記憶體須保持已配置狀態,受控記憶體須保持固定。" +concepts.resources.transfers.description: "上傳將 CPU 資料複製到 GPU 資源,回讀則將資源資料複製到 CPU 記憶體。緩衝區與紋理上的這些方法會在傳輸完成後返回:" +concepts.resources.transfers.details: "呼叫這些方法前,先處理與其他佇列存取之間的衝突。方法內部的等待只涵蓋自身傳輸,不會建立與其他佇列的相依關係。直接透過映射記憶體複製時,則完全由呼叫端負責等待會產生衝突的 GPU 存取。" +concepts.resources.transfers.guidance: "若要將傳輸與其他 GPU 工作一起提交,可透過 {commandBufferUpload} 或 {commandBufferDownload} 記錄。上傳來源與回讀目標的記憶體生命週期要求不同:" +concepts.resources.transfers.item: "上傳呼叫期間,程式庫會將來源資料複製到內部的臨時上傳空間,也就是暫存記憶體。GPU 隨後從這塊空間讀取,因此應用程式的來源指標只需保持有效到呼叫返回。" +concepts.resources.transfers.notes: "紋理傳輸中的列跨距是 CPU 資料相鄰兩列之間的位元組距離;切片跨距則是相鄰深度切片之間的位元組距離。傳輸操作依這些值,在 CPU 資料與紋理的 GPU 儲存空間之間複製內容。GPU 完成與資料送達回讀目標為何是兩個步驟,見{link}。" +concepts.resources.transfers.notes.link: "同步" +concepts.resources.transfers.table.bufferDownload.transfer: "對於 {cpuReadOnly},直接從映射記憶體複製;否則向傳輸佇列提交回讀,並等待完成。" +concepts.resources.transfers.table.bufferUpload.transfer: "對於 {cpuWriteOnly},直接複製到映射記憶體;否則向傳輸佇列提交上傳,並等待完成。" +concepts.resources.transfers.table.headings.method: "方法" +concepts.resources.transfers.table.headings.transfer: "傳輸行為" concepts.resources.transfers.table.textureTransfers.method: "{textureUpload} / {textureDownload}" -concepts.resources.transfers.table.textureTransfers.transfer: "使用圖形佇列,將所選子資源轉換為複製所需的配置,完成複製後轉換為要求的最終配置,並等待傳輸完成。" -concepts.resources.transfers.title: "選擇立即完成的傳輸或隨命令記錄的傳輸" -concepts.resources.usages.description: "{bufferUsages} 與 {textureUsages} 是宣告資源預期角色的旗標列舉。它們分別指派給 {bufferDescUsages} 與 {textureDescUsages}。當資源具有多個角色時,旗標列舉允許使用 {value} 組合多個成員。" -concepts.resources.usages.title: 在建立資源之前宣告所需的用途 -concepts.resources.views.description: "{bufferView} 描述緩衝區區域及其解譯方式。{textureView} 選取相容的紋理型別、格式與子資源範圍。檢視共用底層儲存空間,不會複製資料,也不會新增建立資源時遺漏的用途。指定檢視範圍也不代表各後端都會進行著色器邊界檢查。" -concepts.resources.views.details: "預設檢視可以直接使用資源本身的控制代碼;若需要不同區域或相容的解譯方式,則建立檢視。在 GPU 工作可能使用檢視及其底層資源期間,應保留兩者的 C# 參考;僅有資源控制代碼並不能維持任一物件存活。只有在最後一次 GPU 使用完成後才能釋放它們。取代其中任一物件後,還應更新包含其舊{link}的常數。" +concepts.resources.transfers.table.textureTransfers.transfer: "將複製及其紋理轉換提交到圖形佇列,並等待完成。操作結束後,所選子資源處於指定的最終佈局。" +concepts.resources.transfers.title: "立即傳輸與命令記錄" +concepts.resources.usages.description: "{bufferUsages} 與 {textureUsages} 是宣告資源用途的旗標列舉,分別設定於 {bufferDescUsages} 與 {textureDescUsages}。資源需要多種用途時,可透過 {value} 組合對應的成員。" +concepts.resources.usages.title: "資源用途" +concepts.resources.views.description: "{bufferView} 描述緩衝區的一塊區域及其資料解讀方式。{textureView} 選擇子資源範圍,以及相容的紋理型別與格式。兩者都參考既有儲存空間,並遵循建立時宣告的用途。檢視範圍用來描述存取範圍,各後端並不因此提供一致的著色器邊界檢查。" +concepts.resources.views.details: "資源本身的控制代碼提供預設檢視。需要其他區域或相容的解讀方式時,再建立獨立檢視。檢視及其底層資源都必須保留到 GPU 使用結束;僅持有資源控制代碼,無法維持任一物件的存活。替換其中任一物件時,還須更新包含舊{link}的常數。" concepts.resources.views.details.link: "資源控制代碼" -concepts.resources.views.guidance: "{link}展示了在調整大小時取代深度紋理。{detail}展示了輸入紋理與其可寫入輸出分開保持。兩者都讓資源的生命週期遵循實際使用它的工作。" -concepts.resources.views.guidance.detail: 計算範例 -concepts.resources.views.guidance.link: 旋轉立方體渲染器 -concepts.resources.views.title: "讓檢視及其底層資源在使用期間保持有效" -concepts.shaders.binding.context: 在計算範例中,{input} 會填入 {inputTextureSampledHandle},而 {output} 會填入 {outputTextureStorageHandle}。Slang 的具型別 {descriptorHandle} 指示著色器如何存取各個資源: -concepts.shaders.binding.description: "{setConstantBuffer} 為目前管線的常數資料繫結緩衝區與位元組位移。它繫結現有的 GPU 可見儲存空間;它不會上傳 C# 數值。請先填入緩衝區,並在覆寫其位元組之前確保先前的 GPU 讀取者已完成。" -concepts.shaders.binding.details: 在設定常數緩衝區之前先設定管線。對於已建立並上傳資源的計算工作負載,記錄使用此順序: -concepts.shaders.binding.guidance: 此程式碼片段假設存在記錄中的 {commandBuffer}、{computePipeline}、具有 {bufferUsagesConstant} 用途的已上傳 {constantBuffer},以及工作負載的執行緒群組計數。位移 0 繫結緩衝區的起始處。如果多個常數資料記錄共用一個緩衝區,則每個記錄的起始位移必須符合後端的繫結對齊需求。該需求與記錄內部的欄位配置分開獨立。 -concepts.shaders.binding.notes: "{resourceHandle} 儲存兩個 32 位元欄位,但其解譯歸後端所有。請勿將其視為通用描述項索引、位址或可在上下文之間傳遞的數值。控制代碼不會建立資源、不會新增遺漏的用途,也不會執行同步。" -concepts.shaders.binding.reference: 保留對資源及用於取得其控制代碼之任何檢視的參考,並僅在著色器的最後一次使用完成後處置它們。取代紋理或檢視時,更新包含其舊控制代碼的常數。{link}解釋了該生命週期關係。 -concepts.shaders.binding.reference.link: 資源管理 -concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: 讀取著色器型別 {t} 的結構化元素。 -concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: 讀取或寫入著色器型別 {t} 的結構化元素。 -concepts.shaders.binding.table.headings.access: 預期存取 +concepts.resources.views.title: "檢視與底層資源" +concepts.shaders.binding.context: "計算範例將 {inputTextureSampledHandle} 寫入 {input},將 {outputTextureStorageHandle} 寫入 {output}。在 Slang 中,{descriptorHandle} 的型別引數規定了著色器存取資源的方式:" +concepts.shaders.binding.description: "{setConstantBuffer} 選擇既有緩衝區與位元組位移,目前管線從該位置讀取常數。著色器使用這些參數前,先將資料上傳到對應的儲存空間。如果先前提交的 GPU 工作仍在讀取相同位元組,須等待該工作完成後再更新。" +concepts.shaders.binding.details: "準備好命令緩衝區、計算管線、已填入資料的常數緩衝區及執行緒群組數量後,依以下順序記錄分派。常數緩衝區會繫結到目前管線,因此必須先選擇管線:" +concepts.shaders.binding.guidance: "這裡,{commandBuffer} 使用 {computePipeline} 及 {constantBuffer} 中的參數記錄分派。緩衝區需要宣告 {bufferUsagesConstant} 用途,位移 0 選擇其起始位置。若多筆常數記錄共用緩衝區,每筆記錄的起始位移還須符合後端繫結的對齊要求,這與記錄內部的欄位佈局是兩項不同要求。" +concepts.shaders.binding.notes: "{resourceHandle} 包含兩個 32 位元欄位,含義由後端解釋,其值只在建立資源的上下文中有效。" +concepts.shaders.binding.reference: "保留資源及用於取得控制代碼的檢視,直到著色器完成最後一次存取。替換紋理或檢視後,應更新仍含舊控制代碼的常數。相關所有權規則見{link}。" +concepts.shaders.binding.reference.link: "資源管理" +concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: "讀取著色器型別 {t} 的結構化元素" +concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: "讀寫著色器型別 {t} 的結構化元素" +concepts.shaders.binding.table.headings.access: "預期存取" concepts.shaders.binding.table.headings.cHandle: "C# 控制代碼" -concepts.shaders.binding.table.headings.slangFieldType: Slang 欄位型別 -concepts.shaders.binding.table.samplerHandle.access: 提供紋理取樣狀態。 -concepts.shaders.binding.table.textureSampledHandle.access: 讀取紋理。 -concepts.shaders.binding.table.textureStorageHandle.access: 讀取或寫入儲存紋理。 -concepts.shaders.binding.title: 繫結常數緩衝區及其描述的資源 -concepts.shaders.compilation.description: "{zenithCompiler} 會編譯具名的 Slang 進入點並傳回 {shaderDesc}。使用上下文的 {graphicsApi},讓結果以將建立著色器的後端為目標:DirectX 12 的 DXIL、Metal 的 Metal 程式庫,或 Vulkan 的 SPIR-V。" -concepts.shaders.compilation.details: 例如,在已有 {context} 且三角形著色器已複製到可執行檔旁的情況下: -concepts.shaders.compilation.guidance: "{vSMain} 必須與著色器檔案中的進入點名稱完全相符。在建立管線期間維持著色器物件有效,接著在管線建立完成後予以處置,如 {link} 所示。請執行一次此初始化,而非在每個影格中重新編譯。" -concepts.shaders.compilation.guidance.link: 第一個三角形 -concepts.shaders.compilation.title: 為選取的上下文編譯進入點 -concepts.shaders.description: "著色器接收應用程式提供的資料。頂點屬性描述個別頂點;緩衝區保存參數或陣列;資源控制代碼識別著色器將存取的其他資源。C# 宣告與 Slang 宣告必須在這些數值的意義上達成共識。僅比對欄位名稱是不夠的:配置、資源存取與繫結皆必須相符。" -concepts.shaders.dispatch.description: "{dispatch} 接收執行緒群組的數目。計算範例的 {numthreads} 進入點每組執行 16 × 16 個執行緒。將影像尺寸除以 16 並無條件進位即可找出群組計數。例如,17 × 19 的影像需要 2 × 2 組。著色器會比對其像素座標與影像尺寸,因為最後的群組可能包含位於影像外部的執行緒。" -concepts.shaders.dispatch.details: 編譯器將進入點宣告的群組大小儲存在 {shaderDescThreadGroupSize} 中;它不會將提供給 {dispatch} 的像素尺寸轉換為群組計數。完整的繫結與分派範例請結合使用 {computeShaderRendererCs} 及其著色器,並在另一個通道取用輸出前參閱 {link}。 -concepts.shaders.dispatch.details.link: 同步 -concepts.shaders.dispatch.title: 分派執行緒群組,而非像素 -concepts.shaders.layout.context: "{link}明確指出了它們的位移。此宣告的作用範圍需要 {systemRuntimeInteropServices} 與 {zenithNET}:" +concepts.shaders.binding.table.headings.slangFieldType: "Slang 欄位型別" +concepts.shaders.binding.table.samplerHandle.access: "紋理取樣狀態" +concepts.shaders.binding.table.textureSampledHandle.access: "紋理讀取" +concepts.shaders.binding.table.textureStorageHandle.access: "儲存紋理的讀寫" +concepts.shaders.binding.title: "常數緩衝區與資源控制代碼" +concepts.shaders.compilation.description: "{zenithCompiler} 將指定的 Slang 進入點編譯為 {shaderDesc}。上下文的 {graphicsApi} 決定目標格式:DirectX 12 使用 DXIL,Metal 使用 Metal 程式庫,Vulkan 使用 SPIR-V。" +concepts.shaders.compilation.details: "建立名為 {context} 的圖形上下文後,可以編譯已複製到執行檔所在目錄的三角形著色器:" +concepts.shaders.compilation.guidance: "進入點名稱 {vSMain} 必須與著色器檔案中的函式宣告一致。在初始化階段編譯著色器並建立管線,渲染期間重複使用管線。管線建立完成後,即可釋放著色器物件,具體見{link}。" +concepts.shaders.compilation.guidance.link: "第一個三角形" +concepts.shaders.compilation.title: "著色器編譯" +concepts.shaders.description: "C# 與 Slang 宣告必須約定一致的資料位置與存取方式。頂點輸入佈局描述頂點屬性,著色器緩衝區宣告描述參數與陣列,資源控制代碼則識別著色器使用的資源。" +concepts.shaders.dispatch.description: "{dispatch} 指定要執行多少個執行緒群組。計算範例宣告 {numthreads},因此每組包含 16 × 16 個執行緒。將影像寬度與高度分別除以 16,並向上取整,即可覆蓋整張影像:17 × 19 的影像需要 2 × 2 組。著色器檢查每個執行緒的座標,並跳過位於影像範圍以外的執行緒。" +concepts.shaders.dispatch.details: "{shaderDescThreadGroupSize} 提供宣告的群組大小,可用來計算傳給 {dispatch} 的群組數量。完整計算過程見 {computeShaderRendererCs}。分派完成後,存取輸出影像時仍須符合{link}中說明的要求。" +concepts.shaders.dispatch.details.link: "同步" +concepts.shaders.dispatch.title: "執行緒群組" +concepts.shaders.layout.context: "{link}透過影像尺寸與兩個紋理控制代碼展示這種排列。各欄位的起始位置由明確位移指定。以下宣告使用 {systemRuntimeInteropServices} 與 {zenithNET} 命名空間:" concepts.shaders.layout.context.link: "計算範例的 C# 常數" -concepts.shaders.layout.description: "對於頂點輸入,管線的 {inputLayout} 描述了格式、位移、跨距與語意。三角形的 {float3} 位置加上隨後的 {float4} 色彩共佔用 28 位元組,色彩位於位元組 12 處。{inputLayoutAdd} 會計算此緊密配置;它不會檢查 C# 結構。如果 C# 欄位包含填補,請提供相符的配置,而不要假設欄位是緊密排列的。" -concepts.shaders.layout.details: "常數緩衝區保存著色器參數,而結構化緩衝區保存宣告型別的元素陣列。兩者皆依據其 Slang 宣告進行讀取。它們不使用 {inputLayout}。請檢查編譯後著色器表示法的欄位位移與元素大小(包含填補)。非受控 C# 型別適合以位元組形式複製,但這本身無法證明它與著色器型別相符。特別是,請勿將頂點緊密排列的 {float3} 配置套用至每個著色器緩衝區。" -concepts.shaders.layout.guidance: 資源控制代碼是參照現有資源的小型數值。將控制代碼複製至常數緩衝區並不會複製資源的內容。 -concepts.shaders.layout.notes: "{computeShaderSlang} 中的對應宣告為:" -concepts.shaders.layout.reference: "尺寸佔用前八個位元組,後隨兩個八位元組的資源控制代碼。C# 範例總共保留了 256 位元組。該大小是範例選擇的儲存大小,而非所有 Slang 結構或常數裝載皆佔用 256 位元組的規則。填補總大小也無法修正位於錯誤位移處的欄位。" -concepts.shaders.layout.title: 頂點輸入與著色器資料具有不同的配置規則 -concepts.shaders.matrices.description: 編譯器要求列優先(row-major)矩陣儲存,這會將每列的元素一起儲存。{link}將三個 {matrix4x4} 數值放置於位移 0、64 與 128 處。其{detail}依模型、檢視與投影順序使用 {mulVectorMatrix}。 -concepts.shaders.matrices.description.detail: 著色器 -concepts.shaders.matrices.description.link: 旋轉立方體渲染器 -concepts.shaders.matrices.details: 儲存順序決定矩陣元素如何佔用記憶體;乘法順序決定變換。請保持兩端一致。在未檢查這兩個選擇的情況下加入轉置可能會掩蓋一個不相符,同時引入另一個不相符。 -concepts.shaders.matrices.title: 保持矩陣儲存與乘法順序一致 -concepts.shaders.title: 著色器資料與繫結 -concepts.synchronization.backends.description: DirectX 12 與 Vulkan 使用配置與存取資訊對紋理轉換進行編碼。Metal 在 Zenith.NET 的 {transition} 實作中沒有對應的操作。Metal 將記錄的工作分組為渲染與計算編碼器。後端在結束這些群組時插入可見度屏障,使先前的寫入可用於後續工作。明確的 {barrier} 呼叫處理相依性,例如同一個編碼器內連續的計算分派。 -concepts.synchronization.backends.details: 變更工作負載時此差異至關重要。在{link}中,分派之後接續圖形渲染通道,這在 Metal 上也會建立編碼器邊界。兩個相依的計算分派不會僅透過變更紋理宣告的配置就建立該邊界。保留共用 API 所需的轉換,並單獨識別實際生產與取用命令之間的相依性。 -concepts.synchronization.backends.details.link: 計算範例 -concepts.synchronization.backends.title: 轉換在每個後端並非完全相同 -concepts.synchronization.barriers.context: "{barrierStagesAll} 是較廣泛的範圍,而非自動相依性偵測器。選取實際涵蓋工作的階段,並僅在支援這些操作的佇列上使用它們。" -concepts.synchronization.barriers.description: 考慮兩個計算分派:第一個寫入模擬資料,第二個讀取該資料以執行下一步。兩者皆使用儲存緩衝區,因此沒有要變更的紋理配置。在命令緩衝區中的分派之間插入此內容: -concepts.synchronization.barriers.details: 第一個引數識別生產階段,第二個引數識別取用階段。屏障在 GPU 上建立對應的執行與記憶體相依性。後端將這些階段轉譯為其執行與記憶體存取規則。此屏障不會變更紋理的配置,也不會等待裝置上的所有工作。 -concepts.synchronization.barriers.guidance: "{link}在相依分派之間使用了此模式。在發生相依性的位置放置屏障。在取用者已經記錄之後放置屏障無法將該取用者排在較早的生產者之後。" -concepts.synchronization.barriers.guidance.link: FluidTank 模擬 -concepts.synchronization.barriers.title: 以屏障為相依命令排序 -concepts.synchronization.dependencies.description: 針對每個共用資源,識別首先存取它的操作、接續的操作,以及是否有任何存取進行寫入。兩次讀取相同資料不需要排序來保護其內容,儘管配置變更或呈現可能會施加其他需求。寫入後接續讀取、讀取後接續覆寫或兩次寫入皆可能需要建立相依性。 -concepts.synchronization.dependencies.details: 接著依據這些操作執行的位置選擇機制: -concepts.synchronization.dependencies.guidance: 這些機制互相關聯,但不可互換。依序提交命令並不能取代每個記憶體相依性。佇列等待不會宣告新的紋理配置,命令屏障也不會在呼叫端的 CPU 執行緒上等待。 -concepts.synchronization.dependencies.table.cpuAccess.mechanism: 針對相關完成值呼叫 {wait}。 -concepts.synchronization.dependencies.table.cpuAccess.situation: CPU 在存取或釋放資料之前必須等待 -concepts.synchronization.dependencies.table.crossQueue.mechanism: 將其 {timelineValue} 傳遞給取用端命令緩衝區的 {submit}。 -concepts.synchronization.dependencies.table.crossQueue.situation: 另一個佇列上的提交產生了資料 -concepts.synchronization.dependencies.table.headings.mechanism: 機制 -concepts.synchronization.dependencies.table.headings.situation: 情況 -concepts.synchronization.dependencies.table.layoutChange.mechanism: 帶有前一個與下一個配置的 {commandBufferTransition}。 -concepts.synchronization.dependencies.table.layoutChange.situation: 紋理子資源變更其使用方式 -concepts.synchronization.dependencies.table.pipelineStages.mechanism: 帶有生產者與取用者階段的 {commandBufferBarrier}。 -concepts.synchronization.dependencies.table.pipelineStages.situation: 命令串流中相依的 GPU 階段 -concepts.synchronization.dependencies.title: 從生產者與取用者開始著手 -concepts.synchronization.description: 讀取先前命令寫入資料的命令,相依於這些寫入已完成且對其可見。寫入者為生產者(producer);讀取者為取用者(consumer)。CPU 在讀取、覆寫或釋放共用資料之前也需要完成點。Zenith.NET 針對這些不同的相依性提供了屏障、紋理轉換與時間線。 -concepts.synchronization.layouts.context: "{undefined} 代表不需要保留先前的內容。它適用於新影像或將被完全清除的附件。它不是用來避免追蹤需要載入、取樣或累加內容之影像配置的手段。" -concepts.synchronization.layouts.description: 用途旗標描述紋理支援的角色。{textureLayout} 描述特定操作將如何存取特定子資源。子資源是選取的 Mip 層級與陣列層。變更其配置是為該存取做好準備;它不會將紋理轉換為不同的像素格式。例如,計算範例在 {storage} 配置中寫入輸出紋理,接著在圖形通道中對其進行取樣。在這些使用之間,它記錄了: -concepts.synchronization.layouts.details: 此程式碼片段假設 {outputTexture} 是以 {sampledStorage} 用途建立的,且其選取的子資源處於 {storage} 配置。{default} 選取 Mip 層級 0 與陣列層 0。該操作不會轉換紋理的每個 Mip 或層。 -concepts.synchronization.layouts.guidance: 應用程式提供先前的配置。{transition} 不會維護應用程式可見的配置追蹤器,也不會從先前的命令推斷該值。只要資源在渲染階段之間傳遞,即應追蹤其配置。 -concepts.synchronization.layouts.title: 追蹤每個紋理子資源的配置 -concepts.synchronization.readback.description: "{isCompleted} 僅查詢 GPU 時間線是否已達到某個值。它本身不會回收命令緩衝區,也不會將暫存的回讀資料複製至應用程式的目的地指標所指向的記憶體。" -concepts.synchronization.readback.details: "{commandBufferDownload} 首先記錄將資料複製至內部回讀儲存空間的命令。重設已完成的命令緩衝區以供重複使用時,才會由 CPU 將資料複製至提供的指標所指向的記憶體。在該次回讀提交的 {wait} 返回之前,目的地記憶體必須保持有效,受控記憶體必須保持釘選;返回後才能讀取資料或釋放記憶體。等待另一個佇列上的後續提交,本身不會輪詢回讀作業所屬的佇列。" -concepts.synchronization.readback.guidance: "因此,僅輪詢 {isCompleted} 後立即讀取非同步回讀的目的地記憶體並不足夠。{link}介紹了直接複製與透過暫存記憶體傳輸的路徑。" -concepts.synchronization.readback.guidance.link: 資源管理 -concepts.synchronization.readback.title: GPU 完成與下載的 CPU 資料是不同的步驟 -concepts.synchronization.reuse.description: 對於第一個渲染器,在每個影格之後立即等待最為直截了當。若要重疊工作,請為未決影格提供個別的可變資料,並保留每個影格最終用途的完成值。在更新常數緩衝區、取代紋理或處置管線之前,請完成對受影響資源的所有未決存取。 -concepts.synchronization.reuse.details: 調整大小或關閉時,在等待舊工作之前請先停止新用途。{swapChainResize}、資源處置與上下文處置不能用作應用程式工作的通用等待。三角形教學可以在回呼之間安全地調整大小,因為每個先前的影格都已完成其提交。 -concepts.synchronization.reuse.guidance: 目前的 {swapChainPresent} 在其呈現操作之後也會在圖形佇列上發出訊號並等待。因此,僅移除三角形明確的提交等待並不會自動建立起重疊的呈現迴圈。圖形佇列等待對仍在另一個佇列上執行的獨立工作也毫無作用。 -concepts.synchronization.reuse.title: 僅在最後存取後重複使用資料 -concepts.synchronization.timelines.context: 在 CPU 讀取、覆寫或釋放這些資源之前,請等待其最後一次使用: -concepts.synchronization.timelines.description: 時間線使用遞增的數值追蹤佇列上的完成進度。{submit} 傳回包含該時間線與提交關聯數值的 {timelineValue}。來自不同時間線的完成值不能僅透過其數值 {value} 欄位進行比較。 -concepts.synchronization.timelines.details: 假設 {producer} 與 {consumer} 是來自相同上下文之兩個佇列中已記錄的命令緩衝區。生產者寫入取用者使用的資料。像這樣提交它們: -concepts.synchronization.timelines.guidance: 傳遞產生的數值會使取用佇列在 GPU 上等待該數值。CPU 在此處不呼叫 {producedWait}。在 {consumed} 完成之前保持共用資源有效,並記錄取用者所需的任何紋理配置變更。 -concepts.synchronization.timelines.notes: "{wait} 等待該時間線值,接著檢查其所屬佇列中已完成的提交。完成的命令緩衝區會重設以供重複使用,其中暫存的回讀資料會複製至提供的 CPU 目的地。{queueTimelineSignal} 也可以在已提交至該佇列的工作之後排入完成點。呼叫 {signal} 不代表 GPU 已經到達該點。" -concepts.synchronization.timelines.title: 使用時間線進行完成通知與佇列交接 -concepts.synchronization.title: 同步 -home.actions.reference: 瀏覽 API -home.actions.tutorial: 從三角形開始 -home.entries.description: 第一個影格。聚焦的範例。深入探討 API。 -home.entries.label: 探索說明文件 -home.entries.reference.action: 探索 API -home.entries.reference.category: 參考 -home.entries.reference.description: 尋找支援您應用程式的型別、簽章與成員。 -home.entries.reference.title: API 參考 -home.entries.samples.action: 瀏覽範例 -home.entries.samples.category: 範例 -home.entries.samples.description: 透過原始碼探索聚焦的渲染與計算技術。 -home.entries.samples.title: 範例 -home.entries.title: 開始建置。 -home.entries.tutorial.action: 開始教學 -home.entries.tutorial.category: 教學 -home.entries.tutorial.description: 從設定到第一個影格,建置完整的渲染應用程式。 -home.entries.tutorial.title: 第一個三角形 -home.introduction.accent: "以 C# 打造。" -home.introduction.description: 透過單一 .NET API 建立資源、記錄命令並提交圖形或計算工作。 -home.introduction.title: 建置專屬的渲染器。 -home.meta.description: "橫跨 DirectX、Metal 與 Vulkan,為圖形與計算提供一致的 C# API。" -home.scene.description: 旋轉幾何體研究。拖曳或使用方向鍵調整檢視。 -home.scene.label: 幾何體顯示 -home.scene.surface: 表面 -home.scene.wireframe: 線框 -home.title: 適用於 .NET 的現代 RHI -learning.concepts.description: 在組合渲染通道之前,先理解命令、資源、著色器資料與同步如何相互配合。 -learning.concepts.execution.description: 記錄 GPU 工作、予以提交並維持其資源存活。 -learning.concepts.platforms.description: 連接原生視窗或 UI 渲染控制項。 -learning.concepts.resources.description: 選擇資源用途、記憶體配置位置與檢視。 -learning.concepts.shaders.description: "使 C# 配置與資源控制代碼符合 Slang。" -learning.concepts.synchronization.description: 安排相依存取的順序,並掌握工作完成的時間點。 -learning.concepts.title: 核心概念 -learning.description: 從完整的三角形教學開始。接著利用聚焦範例與概念指南,理解更大型渲染器背後的資源、資料與相依性。 -learning.entries.samples.action: 瀏覽範例 -learning.entries.samples.description: "尋找幾何體、計算、光線查詢與網格著色(mesh shading)的 C# 和 Slang 範例。" -learning.entries.tutorial.action: 開啟教學 -learning.entries.tutorial.description: 建立主控台應用程式、開啟視窗並繪製三角形。 -learning.meta.description: 開始使用 Zenith.NET 並探索其程式設計模型。 -learning.title: 學習 -reference.description: 查詢資源型別、命令簽章與平台整合。 -reference.entries.commands.description: 記錄圖形、計算與傳輸命令。 -reference.entries.commands.label: 記錄工作 -reference.entries.context.description: 為所選後端建立 GPU 資源。 -reference.entries.context.label: 從這裡開始 -reference.meta.description: 探索 Zenith.NET 中的型別與成員。 -reference.navigation.core: 瀏覽核心 API。 -reference.title: API 參考 -samples.computeShader.description: 透過計算分派將影像轉換為灰階並顯示產生的紋理。展示了用於取樣輸入紋理與可寫入輸出紋理的資源控制代碼、無條件進位的執行緒群組計數,以及著色器內部的邊界檢查。請保留隨附的 {assetsTexturesShokoPng} 資產;渲染器會處理一次並在後續影格中呈現結果。 +concepts.shaders.layout.description: "對於頂點輸入,{inputLayout} 描述各屬性的格式、位移與語義,以及相鄰頂點之間的跨距。三角形先儲存 {float3} 位置,再儲存 {float4} 色彩:色彩的位元組位移為 12,每個頂點占 28 位元組。{inputLayoutAdd} 根據元素格式計算這個緊密排列的佈局。若 C# 結構包含填充,就需要在位移與跨距中計入這些空間。" +concepts.shaders.layout.details: "常數緩衝區儲存著色器參數,結構化緩衝區儲存指定型別的元素陣列。它們的佈局由 Slang 宣告決定,不使用 {inputLayout}。C# 欄位位移、元素大小與填充,必須符合編譯後的著色器佈局。即使某個 C# 型別是非受控型別,可以直接依位元組複製,其記憶體排列也未必符合著色器要求;例如,頂點中緊密排列的 {float3},在著色器緩衝區中可能需要不同的對齊方式。" +concepts.shaders.layout.guidance: "著色器參數除了普通數值,也可以包含資源控制代碼。控制代碼識別的是既有儲存空間,因此將它複製到常數緩衝區,不會複製資源內容。" +concepts.shaders.layout.notes: "{computeShaderSlang} 中對應的宣告為:" +concepts.shaders.layout.reference: "兩個尺寸值占用前 8 位元組,後面是兩個各占 8 位元組的控制代碼。C# 範例為整筆記錄預留 256 位元組。其他記錄的大小,應依各自欄位以及所需的佈局與對齊方式決定。" +concepts.shaders.layout.title: "資料佈局" +concepts.shaders.matrices.description: "編譯器採用列優先的矩陣儲存方式,使同一列的元素連續排列。{link}在位移 0、64 和 128 處儲存三個 {matrix4x4} 值,其{detail}按模型、檢視和投影順序執行 {mulVectorMatrix}。" +concepts.shaders.matrices.description.detail: "著色器" +concepts.shaders.matrices.description.link: "旋轉立方體渲染器" +concepts.shaders.matrices.details: "儲存順序決定矩陣元素在記憶體中的排列,乘法順序決定變換。C# 與 Slang 應採用相互配合的約定。" +concepts.shaders.matrices.title: "矩陣約定" +concepts.shaders.title: "著色器資料與繫結" +concepts.synchronization.backends.description: "DirectX 12 與 Vulkan 將紋理轉換記錄為佈局與存取狀態的變更。在 Zenith.NET 的 Metal 後端中,{transition} 沒有對應的 GPU 操作。Metal 後端將命令組織成渲染與計算編碼器,並在編碼器結束時插入可見性屏障。同一編碼器內彼此相依的操作,例如連續的計算分派,透過明確呼叫 {barrier} 協調。" +concepts.synchronization.backends.details: "{link}開始圖形渲染通道時,會結束計算編碼器,讓後續圖形工作能讀取計算輸出。連續兩次計算分派仍位於同一編碼器內,即使中間記錄了紋理轉換,也需要屏障來處理相依關係。因此,跨後端使用的命令序列既要考慮紋理佈局,也要處理存取之間的相依關係。" +concepts.synchronization.backends.details.link: "計算範例" +concepts.synchronization.backends.title: "後端行為" +concepts.synchronization.barriers.context: "選擇涵蓋相關存取,且目前佇列支援的階段。{barrierStagesAll} 包含所有支援的階段;若相依關係只涉及其中一部分,可選擇較小的範圍。" +concepts.synchronization.barriers.description: "假設同一個命令緩衝區內有兩次計算分派,第一次寫入模擬資料,第二次讀取這些資料。在兩次分派之間設定屏障,讓第二次分派讀到已完成的寫入結果。對於儲存緩衝區,這樣即可安排存取順序,不需要進行紋理佈局轉換:" +concepts.synchronization.barriers.details: "第一個引數指定產生資料的階段,第二個引數指定使用資料的階段。兩者共同描述兩次分派之間所需的執行順序與記憶體可見性。" +concepts.synchronization.barriers.guidance: "{link}在模擬步驟之間採用這個方式。每道屏障都位於產生資料的分派之後、使用資料的分派之前。" +concepts.synchronization.barriers.guidance.link: "FluidTank 模擬" +concepts.synchronization.barriers.title: "管線屏障" +concepts.synchronization.dependencies.description: "逐一確認每個資源有哪些存取涉及同一份資料。只要其中包含寫入,就必須維持所需的先後順序。兩次讀取本身沒有衝突,但仍需符合紋理佈局與呈現要求。CPU 更新資料或釋放資源前,也須等待 GPU 完成對該儲存空間的使用。" +concepts.synchronization.dependencies.details: "應根據操作執行的位置選擇機制:" +concepts.synchronization.dependencies.guidance: "一項工作可能同時需要多種同步機制。例如,紋理由另一個佇列產生時,除了提交相依關係,還需為下一次使用設定正確的佈局。這兩項操作本身都不需要阻塞 CPU;只有 CPU 要存取或釋放相關資料時,才需要在 CPU 端等待。" +concepts.synchronization.dependencies.table.cpuAccess.mechanism: "針對相關完成值呼叫 {wait}。" +concepts.synchronization.dependencies.table.cpuAccess.situation: "CPU 存取或資源釋放需要等待 GPU 完成" +concepts.synchronization.dependencies.table.crossQueue.mechanism: "將生產者的 {timelineValue} 傳給消費者的 {submit}。" +concepts.synchronization.dependencies.table.crossQueue.situation: "一個佇列使用另一個佇列產生的資料" +concepts.synchronization.dependencies.table.headings.mechanism: "機制" +concepts.synchronization.dependencies.table.headings.situation: "情況" +concepts.synchronization.dependencies.table.layoutChange.mechanism: "呼叫 {commandBufferTransition},指定先前佈局與目標佈局。" +concepts.synchronization.dependencies.table.layoutChange.situation: "紋理子資源變更其使用方式" +concepts.synchronization.dependencies.table.pipelineStages.mechanism: "呼叫 {commandBufferBarrier},指定產生資料和使用資料的階段。" +concepts.synchronization.dependencies.table.pipelineStages.situation: "命令串流中相依的 GPU 階段" +concepts.synchronization.dependencies.title: "存取相依關係" +concepts.synchronization.description: "同步確定多個操作存取共用資料的順序,並讓後續操作能讀到所需結果。在寫後讀相依關係中,寫入端稱為生產者,讀取端稱為消費者。屏障與紋理轉換協調 GPU 存取;時間線連接不同提交,並讓 CPU 等待 GPU 工作完成。" +concepts.synchronization.layouts.context: "現有內容可以丟棄時,可將先前佈局設為 {undefined},例如新建影像或即將完整清除的附件。若要保留內容以供載入、取樣或累積,則應使用前次存取時的佈局。" +concepts.synchronization.layouts.description: "紋理的用途旗標宣告允許的作用。{textureLayout} 描述命令序列中某個時點對子資源的存取方式,子資源由 mip 級別與陣列層識別。存取方式改變時,需要記錄轉換。例如,計算範例在 {storage} 佈局中寫入輸出紋理,再為圖形通道中的取樣做準備:" +concepts.synchronization.layouts.details: "這裡的 {outputTexture} 已宣告 {sampledStorage} 用途,所選子資源處於 {storage} 佈局。{default} 選擇 mip 級別 0 和陣列層 0,其他級別和層不受這次轉換影響。" +concepts.synchronization.layouts.guidance: "呼叫 {transition} 時,提供子資源上一次使用時的佈局。應用程式在記錄命令,以及在渲染階段之間傳遞紋理時,負責追蹤這個狀態。" +concepts.synchronization.layouts.title: "紋理佈局" +concepts.synchronization.readback.description: "{isCompleted} 回報 GPU 的完成狀態。透過命令記錄的回讀還需要一個步驟:將結果從內部回讀空間複製到應用程式的目標記憶體。" +concepts.synchronization.readback.details: "{commandBufferDownload} 記錄向內部回讀空間複製資料的 GPU 命令。提交完成後,程式庫在回收命令緩衝區時執行最後的 CPU 複製。對這次回讀提交的完成值呼叫 {wait},會等待 GPU 完成,並處理該佇列已完成的緩衝區,從而完成這兩個步驟。呼叫返回前,目標記憶體須保持已配置狀態,受控記憶體須保持固定。" +concepts.synchronization.readback.guidance: "只輪詢 {isCompleted} 不會執行最後的 CPU 複製;等待其他佇列,也不會回收回讀佇列中已完成的緩衝區。上傳與回讀何時使用直接記憶體存取或暫存空間,見{link}。" +concepts.synchronization.readback.guidance.link: "資源管理" +concepts.synchronization.readback.title: "回讀完成" +concepts.synchronization.reuse.description: "三角形教學在每個影格完成後才重複使用資料。若要讓影格重疊執行,應為每個尚未完成的影格準備獨立的可變儲存空間,並追蹤何時可以再次使用。修改資料前,須等待 GPU 完成對相關位元組的存取;釋放資源前,則須等待它的所有使用結束。" +concepts.synchronization.reuse.details: "調整大小與結束程式遵循相同順序:先停止新的資源存取,等待既有存取結束,再替換或釋放資源。呼叫 {swapChainResize} 或釋放資源、上下文前,須先完成上述等待。三角形教學已經逐影格等待,因此可以在回呼之間調整大小。" +concepts.synchronization.reuse.guidance: "{swapChainPresent} 在呈現後向圖形佇列發出訊號並等待。因此,即使移除明確的提交等待,三角形教學仍會在呈現時等待。獨立提交到其他佇列的工作,需要另外追蹤其完成狀態。" +concepts.synchronization.reuse.title: "資源重複使用" +concepts.synchronization.timelines.context: "CPU 若要在消費者完成後讀取結果、覆寫共用資料或釋放資源,須先等待這次提交完成:" +concepts.synchronization.timelines.description: "時間線用遞增值識別佇列進度。{submit} 傳回的 {timelineValue} 同時包含時間線和本次提交的值。不同時間線上的 {value} 數值不能直接比較。" +concepts.synchronization.timelines.details: "設 {producer} 與 {consumer} 是同一上下文中兩個佇列上已記錄的命令緩衝區,後者使用前者寫入的資料。提交時傳入以下相依關係:" +concepts.synchronization.timelines.guidance: "消費者所在的佇列會先等待傳入的完成值,再執行命令。CPU 不必呼叫 {producedWait},可以繼續處理其他工作。共用資源須保留到 {consumed} 完成,同時仍需記錄消費者存取所要求的紋理轉換。" +concepts.synchronization.timelines.notes: "{queueTimelineSignal} 傳回的值,同樣可以透過 {wait} 等待,也可以作為另一個佇列的相依條件。{signal} 將完成點排在先前已提交的工作之後,GPU 完成這些工作後就會到達該點。" +concepts.synchronization.timelines.title: "時間線與佇列相依關係" +concepts.synchronization.title: "同步" +home.actions.reference: "瀏覽 API" +home.actions.tutorial: "從三角形開始" +home.entries.description: "教學、範例與 API 參考" +home.entries.label: "文件分類" +home.entries.reference.action: "探索 API" +home.entries.reference.category: "參考" +home.entries.reference.description: "查閱 API 型別、成員與宣告" +home.entries.reference.title: "API 參考" +home.entries.samples.action: "瀏覽範例" +home.entries.samples.category: "範例" +home.entries.samples.description: "可直接執行的圖形與計算範例" +home.entries.samples.title: "範例" +home.entries.title: "文件" +home.entries.tutorial.action: "開始教學" +home.entries.tutorial.category: "教學" +home.entries.tutorial.description: "從空白專案開始,繪製第一個三角形" +home.entries.tutorial.title: "第一個三角形" +home.introduction.accent: "跨平台圖形應用" +home.introduction.description: "Zenith.NET 提供統一的圖形與計算 API,支援 DirectX、Metal 與 Vulkan" +home.introduction.title: "以 .NET 開發{lineBreak}{accent}" +home.meta.description: "透過 Zenith.NET 開發跨平台圖形與計算應用程式,以共用 API 使用 DirectX、Metal 與 Vulkan" +home.scene.description: "可互動的旋轉幾何體。拖動或使用方向鍵調整視角。" +home.scene.label: "幾何體顯示" +home.scene.surface: "表面" +home.scene.wireframe: "線框" +home.title: "適用於 .NET 的現代 RHI" +learning.concepts.description: "選擇資源用途、描述著色器資料與協調 GPU 執行" +learning.concepts.execution.description: "命令記錄、提交與資源生命週期" +learning.concepts.platforms.description: "原生呈現與 UI 渲染控制項" +learning.concepts.resources.description: "資源用途、記憶體放置與檢視" +learning.concepts.shaders.description: "C# 與 Slang 的資料佈局和繫結約定" +learning.concepts.synchronization.description: "相依關係、可見性與完成狀態" +learning.concepts.title: "核心概念" +learning.description: "初次使用 Zenith.NET,可以從三角形教學開始。完成後,再依需要查閱資源管理、著色器資料與同步等概念,或透過範例了解各種圖形技術的實作。" +learning.entries.samples.action: "瀏覽範例" +learning.entries.samples.description: "幾何體、計算、光線查詢與網格著色的 C# 和 Slang 實作" +learning.entries.tutorial.action: "開啟教學" +learning.entries.tutorial.description: "建立視窗並渲染三角形的主控台應用程式" +learning.meta.description: "Zenith.NET 程式設計模型的入門教學與概念說明" +learning.title: "學習" +reference.description: "資源、命令與平台整合的參考文件" +reference.entries.commands.description: "圖形、計算與傳輸命令" +reference.entries.commands.label: "記錄命令" +reference.entries.context.description: "為所選後端建立 GPU 資源" +reference.entries.context.label: "從這裡開始" +reference.meta.description: "Zenith.NET 的命名空間、型別與成員" +reference.navigation.core: "核心 API 參考" +reference.title: "API 參考" +samples.computeShader.description: "範例載入 {assetsTexturesShokoPng},透過一次計算分派將影像轉成灰階,再顯示輸出紋理。轉換只執行一次,後續影格顯示同一結果。渲染器展示了取樣紋理與可寫紋理的繫結、向上取整群組數量以覆蓋整張影像的計算方式,以及著色器中的影像邊界檢查。" samples.computeShader.details: "{computeShaderRendererCs} · {computeShaderSlang}" -samples.computeShader.title: 計算著色器 -samples.cube.description: 新增索引繪製、常數緩衝區中的模型、檢視與投影矩陣,以及深度測試。深度紋理會在調整大小時重新建立。從裁剪空間幾何體過渡到變換物件時可參考此範例;渲染器使用 {d32FloatS8UInt} 深度/樣板附件。 +samples.computeShader.title: "計算著色器" +samples.cube.description: "旋轉立方體加入索引繪製、常數緩衝區中的模型、檢視和投影矩陣,以及深度測試。視窗調整大小時,會重建 {d32FloatS8UInt} 深度/樣板紋理。" samples.cube.details: "{spinningCubeRendererCs} · {spinningCubeSlang}" -samples.cube.title: 旋轉立方體 -samples.description: "針對您要研究的功能選擇聚焦的範例。每個範例都會連結至 C# 渲染器及其 Slang 著色器。若希望從空白專案逐步理解完整的應用程式,請從 {link} 開始。" -samples.description.link: 第一個三角形 -samples.execution.description: "{link} 在單一桌面應用程式中包含六個獨立的渲染器。請使用 .NET 10 SDK 與下方所述受支援的桌面後端。建置並執行該應用程式,然後從主控台功能表中選取範例:" -samples.execution.description.link: ZenithTutorials -samples.execution.details: "宿主程式在 Windows 上選取 DirectX 12,在 macOS 上選取 Metal,在 Linux 上選取 Vulkan。請使用所選後端支援的裝置、驅動程式與著色器編譯器環境。Linux 視窗路徑需要 X11 或 XWayland。{link} 宣告了套件相依性,並複製執行階段所需的著色器與紋理資產。" -samples.execution.details.link: 專案檔 -samples.execution.guidance: 這些範例共用視窗處理與呈現程式碼。您可以依據想研究的功能獨立選擇任何範例。 -samples.execution.title: 執行教學範例 -samples.host.description: "{appCs} 建立圖形上下文、視窗與交換鏈。它取得命令緩衝區、呼叫選取的渲染器、提交影格並進行呈現。{iRendererCs} 定義了渲染器的更新、渲染、調整大小與處置方法。" -samples.host.details: "計算與光線追蹤會產生螢幕外紋理。{texturePresenterCs} 與 {presentTextureSlang} 將這些紋理繪製到視窗目前影格的輸出紋理中。宿主程式仍保有提交與交換鏈呈現的所有權。" -samples.host.title: "共用宿主程式與呈現" -samples.indirectDrawing.description: 使用索引間接引數緩衝區與結構化緩衝區中的逐執行個體資料繪製立方體的多個複本。CPU 提供繪製引數並更新變換。在加入 GPU 產生的引數前,可透過此範例了解間接引數配置以及著色器對執行個體資料的存取。 +samples.cube.title: "旋轉立方體" +samples.description: "每個範例均由 C# 渲染器與 Slang 著色器組成,集中說明一項技術。完整的應用程式設定與渲染順序見{link}。" +samples.description.link: "第一個三角形" +samples.execution.description: "執行 {link} 專案,並從主控台選單選擇範例。" +samples.execution.description.link: "ZenithTutorials" +samples.execution.title: "執行範例" +samples.host.description: "{appCs} 初始化上下文、視窗和交換鏈。每個影格取得命令緩衝區,呼叫所選渲染器,提交命令並呈現結果。{iRendererCs} 規定渲染器的更新、渲染、調整大小和釋放操作。" +samples.host.details: "計算與光線追蹤渲染器產生離屏紋理。{texturePresenterCs} 與 {presentTextureSlang} 將這些紋理繪製到目前的輸出紋理,接著由共用宿主提交命令並呈現這個影格。" +samples.host.title: "宿主與呈現" +samples.indirectDrawing.description: "間接繪製透過索引繪製引數緩衝區,以及儲存各執行個體資料的結構化緩衝區,繪製多個立方體。CPU 提供繪製引數並更新變換。" samples.indirectDrawing.details: "{indirectDrawingRendererCs} · {indirectDrawingSlang}" -samples.indirectDrawing.title: 間接繪製 -samples.meshShading.description: 使用工作著色器(task shader)剔除球體執行個體,並將其索引傳遞至發出幾何體的網格著色器(mesh shader)。渲染器在建立管線前會檢查 {contextCapabilitiesMeshShadingSupported}。可用於追蹤跨工作與網格階段的資源控制代碼及裝載資料。 +samples.indirectDrawing.title: "間接繪製" +samples.meshShading.description: "任務著色器剔除球體執行個體,將保留的索引傳給負責產生幾何體的網格著色器。建立管線前,渲染器檢查 {contextCapabilitiesMeshShadingSupported}。" samples.meshShading.details: "{meshShadingRendererCs} · {meshShadingSlang}" -samples.meshShading.title: 網格著色(Mesh Shading) -samples.rayTracing.description: 為地面與程序化球體建置底層與頂層加速結構,接著在計算著色器中執行內嵌光線查詢。渲染器在建構工作負載前會檢查 {contextCapabilitiesRayTracingSupported}。此範例適用於加速結構輸入與著色器端光線周遊。 +samples.meshShading.title: "網格著色" +samples.rayTracing.description: "此範例為地面與程序化球體建立底層及頂層加速結構,再於計算著色器內執行內嵌光線查詢。初始化前檢查 {contextCapabilitiesRayTracingSupported}。" samples.rayTracing.details: "{rayTracingRendererCs} · {rayTracingSlang}" -samples.rayTracing.title: 光線追蹤 -samples.title: 範例 -samples.triangle.description: 建立頂點緩衝區與相符的輸入配置,接著透過圖形管線繪製三個頂點。可用於將資源建立與渲染通道中的命令連結起來。 +samples.rayTracing.title: "光線追蹤" +samples.title: "範例" +samples.triangle.description: "三角形範例將頂點緩衝區與對應的輸入佈局關聯,再透過圖形管線繪製三個頂點。" samples.triangle.details: "{helloTriangleRendererCs} · {helloTriangleSlang} · {link}" -samples.triangle.details.link: 完整教學 -samples.triangle.title: Hello Triangle -samples.workloads.description: 主要存放庫的 {link} 包含結合多項功能的應用程式。其專案會參考程式庫原始碼。從 Zenith.NET 的簽出目錄執行所選專案即可,例如: -samples.workloads.description.link: Experiments 目錄 -samples.workloads.details: "視窗化實驗在 Windows、macOS 與 Linux/X11 上使用相同的宿主程式選項。若要在 Avalonia、WinForms、WPF、WinUI/Uno 或 MAUI 中繪製,請參閱 {link} 以取得控制項影格生命週期與實作連結。" -samples.workloads.details.link: 平台整合 +samples.triangle.details.link: "完整教學" +samples.triangle.title: "Hello Triangle" +samples.workloads.description: "主存放庫的{link}包含規模較大的應用程式,這些專案直接參考程式庫原始碼。" +samples.workloads.description.link: "Experiments 目錄" +samples.workloads.details: "視窗實驗專案採用相同的 Windows、macOS 和 Linux/X11 呈現路徑。Avalonia、WinForms、WPF、WinUI/Uno 和 MAUI 控制項的影格生命週期及實作程式碼見{link}。" +samples.workloads.details.link: "平台整合" samples.workloads.table.cornellBox.example: "{link}" -samples.workloads.table.cornellBox.example.link: CornellBox -samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: "路徑追蹤、降噪、色調對應、影像升頻與 ImGui 控制項。需要光線追蹤支援,以及對應桌面後端的著色器編譯環境。" +samples.workloads.table.cornellBox.example.link: "CornellBox" +samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: "路徑追蹤、降噪、色調對應、影像升頻與 ImGui 控制項。需要光線追蹤支援。" samples.workloads.table.fluidTank.example: "{link}" -samples.workloads.table.fluidTank.example.link: FluidTank -samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: "計算流體模擬、模擬各階段之間的相依性,以及多通道表面渲染。需要該桌面後端與著色器編譯器環境。" -samples.workloads.table.headings.example: 範例 -samples.workloads.table.headings.whatItDemonstratesAndRequires: 示範內容與需求 +samples.workloads.table.fluidTank.example.link: "FluidTank" +samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: "計算流體模擬、模擬階段之間的相依關係,以及多通道表面渲染。" +samples.workloads.table.headings.example: "範例" +samples.workloads.table.headings.whatItDemonstratesAndRequires: "技術與執行要求" samples.workloads.table.inkCanvas.example: "{link}" -samples.workloads.table.inkCanvas.example.link: InkCanvas -samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: 在原生視窗中進行 Skia 繪圖與輸入處理。需要目標平台的後端與 Skia 原生程式庫。 +samples.workloads.table.inkCanvas.example.link: "InkCanvas" +samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: "在原生視窗中進行 Skia 繪圖與輸入處理。需要目標平台的後端與 Skia 原生程式庫。" samples.workloads.table.platformDetection.example: "{link}" -samples.workloads.table.platformDetection.example.link: PlatformDetection -samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: 嘗試為每個後端建立圖形上下文並回報裝置功能。若上下文建立失敗,則回報為不支援;該結果也可能代表缺少驅動程式或執行階段相依性。 -samples.workloads.title: 探索更大型的工作負載 -tutorial.context.description: 視窗現在可以開啟,但我們尚未建立將要渲染至其中的 GPU 物件。{graphicsContext} 提供對所選圖形後端及其命令佇列的存取。 -tutorial.context.details: 在{emphasis}插入此區塊: -tutorial.context.details.emphasis: using 指示詞之後、{iWindowWindow} 之前 -tutorial.context.guidance: 分支邏輯會在 Windows 上選取 DirectX 12,在 macOS 上選取 Metal,在 Linux 上選取 Vulkan。後續的渲染程式碼皆使用共用的 Zenith.NET API。我們在開發期間要求啟用驗證,並列印透過 {validationMessage} 回報的訊息。診斷資訊取決於後端以及電腦上可用的驗證元件。 -tutorial.context.title: 建立圖形上下文 -tutorial.description: 建置一個 .NET 主控台應用程式,開啟視窗並繪製帶有平滑色彩漸層的三角形。您將學習頂點資料、著色器與管線狀態如何協同運作,接著記錄並提交產生影像的命令。 -tutorial.details: 請依序閱讀各章節。您將先開啟空白視窗,接著顯示背景色彩,最後繪製三角形。在新增下一部分之前,每個檢查點都會確認應用程式的一部分正常運作。初始化僅執行一次;渲染回呼每次被叫用時都會記錄新的影格。 +samples.workloads.table.platformDetection.example.link: "PlatformDetection" +samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: "嘗試為每個後端建立上下文,並回報裝置功能。建立失敗時顯示為不支援,原因可能是裝置、驅動程式或缺少執行時所需的元件。" +samples.workloads.title: "綜合應用" +tutorial.context.description: "{graphicsContext} 透過後端連接應用程式與 GPU,並提供建立渲染資源的方法。" +tutorial.context.details: "在{emphasis}插入上下文初始化程式碼:" +tutorial.context.details.emphasis: "using 指示詞之後、{iWindowWindow} 之前" +tutorial.context.guidance: "各分支為目前平台選擇後端並要求啟用驗證。{validationMessage} 訊息會輸出到主控台。" +tutorial.context.imports: "在 {programCs} 頂端加入以下 using 指示詞:" +tutorial.context.title: "圖形上下文" +tutorial.description: "本教學從空白的 .NET 主控台專案開始,逐步建立視窗,並在其中繪製一個彩色三角形。" +tutorial.details: "本教學分三個階段確認結果:空白視窗、單色背景,以及彩色三角形。每完成一個階段,先執行程式檢查畫面,再繼續下一步。" tutorial.draw.context: "{draw} 的引數如下:" -tutorial.draw.description: 在 {windowRender} 回呼中,在 {beginRenderPass} 與 {endRenderPass} 之間,將 {addTheTriangleDrawCommandsHereLater} 取代為下列三個命令: -tutorial.draw.details: "{setPipeline} 選取我們剛建立的著色器與狀態。請在繫結頂點資料之前設定它:後端會使用管線的輸入配置來解譯繫結。" -tutorial.draw.guidance: "{setVertexBufferVertexBuffer} 將從位元組位移 0 開始的緩衝區繫結至輸入插槽 0。該插槽對應於 {inputLayouts} 中的單一項目。它不會再次複製或上傳資料。" -tutorial.draw.notes: 此時命令仍僅處於已記錄狀態。已位於渲染回呼結尾的 {submitWait} 與 {present} 呼叫會執行工作並顯示其結果。清除操作依然必要,因為三角形只覆蓋影像的一部分;背景在每個影格中也必須接收定義好的色彩。 -tutorial.draw.table.firstInstance.meaning: 執行個體編號從零開始。 -tutorial.draw.table.firstVertex.meaning: 從緩衝區中的第一個頂點開始。 -tutorial.draw.table.headings.argument: 引數 -tutorial.draw.table.headings.description: 值 -tutorial.draw.table.headings.meaning: 意義 -tutorial.draw.table.instanceCount.meaning: 繪製三角形的一個複本。 -tutorial.draw.table.vertexCount.meaning: 讀取三個頂點。 -tutorial.draw.title: 在通道內繪製三角形 -tutorial.execution.description: 從 {firstTriangle} 目錄建置並執行: -tutorial.execution.details: 視窗應顯示一個三角形,在深色背景下具有紅色的上頂點、綠色的右下角與藍色的左下角。內部應顯示這些色彩之間的平滑漸層。 -tutorial.execution.guidance: 調整視窗大小。調整大小回呼會更新畫面緩衝區尺寸並調整交換鏈的大小。渲染通道會建立符合該影像的視口。由於頂點位置保持為標準化座標,三角形保持視窗寬度與高度的相同比例;變更外觀比例可能會拉伸其形狀。保留物件的外觀比例需要投影或視口原則,這超出了此初次繪製的範疇。 -tutorial.execution.title: 執行、調整大小與關閉 -tutorial.frame.commands.context: 在 {endRenderPass} 之後,第二次轉換會準備影像以供呈現。{submit} 結束記錄並提交命令緩衝區;{wait} 等待 GPU 完成該提交。接著 {present} 要求顯示渲染完成的影像。 -tutorial.frame.commands.description: 渲染通道(render pass)將使用相同附件的繪製操作分組在一起。在此,色彩附件是交換鏈的輸出紋理,即接收繪圖的影像。{colorAttachmentClear} 會建立描述,指示通道清除為指定的 RGBA 色彩,並在通道結束時保留結果。{beginRenderPass} 記錄這些指示;GPU 會在命令提交後執行清除。 -tutorial.frame.commands.details: 中括號內包含我們唯一的色彩附件。{null} 引數代表沒有深度/樣板附件,該附件通常會儲存用於深度與樣板測試的深度值與樣板遮罩。 -tutorial.frame.commands.guidance: "{beginRenderPass} 會設定涵蓋附件的視口與裁剪區域。視口將渲染座標對應至像素,而裁剪區域則限制可寫入的像素。這些預設值涵蓋整個輸出紋理,這正是繪製此三角形所需的。" -tutorial.frame.commands.title: 清除、提交與呈現 -tutorial.frame.description: 首先以單一背景色彩填滿影像。此操作稱為清除(clear)。若該色彩出現在視窗中,即表示原生呈現目標、命令提交與呈現路徑正常協同運作。此檢查點可讓您在新增幾何體與著色器之前先驗證影格迴圈。 -tutorial.frame.details: 渲染回呼是 Silk.NET 在需要繪製影格時叫用的程式碼。此回呼不需要事件的經過時間引數,因此命名為 {value}。在{emphasis}註冊它: +tutorial.draw.description: "在 {windowRender} 回呼中,用以下命令替換 {addTheTriangleDrawCommandsHereLater},位置保持在 {beginRenderPass} 與 {endRenderPass} 之間:" +tutorial.draw.details: "{setPipeline} 選擇著色器和渲染狀態。後端按管線的輸入佈局解釋頂點繫結,因此這一步必須先於頂點繫結。" +tutorial.draw.guidance: "{setVertexBufferVertexBuffer} 從緩衝區的位元組位移 0 開始,將已上傳的頂點資料繫結到輸入槽 0,對應 {inputLayouts} 中唯一的項目。" +tutorial.draw.notes: "這些呼叫記錄繪製命令。既有的 {submitWait} 提交命令並等待 GPU 完成,接著由 {present} 要求顯示完成的影像。保留通道開始時的清除操作,讓三角形以外的區域也有確定的背景色。" +tutorial.draw.table.firstInstance.meaning: "執行個體編號從零開始。" +tutorial.draw.table.firstVertex.meaning: "從緩衝區中的第一個頂點開始。" +tutorial.draw.table.headings.argument: "引數" +tutorial.draw.table.headings.description: "值" +tutorial.draw.table.headings.meaning: "意義" +tutorial.draw.table.instanceCount.meaning: "繪製一個三角形執行個體。" +tutorial.draw.table.vertexCount.meaning: "讀取三個頂點。" +tutorial.draw.title: "繪製命令" +tutorial.execution.description: "建置並執行 {firstTriangle} 專案。" +tutorial.execution.details: "視窗中應出現一個三角形:上方為紅色,右下方為綠色,左下方為藍色,背景為深色。頂點色彩經過內插,在三角形內形成平滑的漸層。" +tutorial.execution.guidance: "調整視窗大小時,影像的像素尺寸會改變,頂點座標則維持不變。視口將這些座標對應到新的寬度與高度,因此改變視窗的寬高比會拉伸三角形。" +tutorial.execution.title: "執行應用程式" +tutorial.frame.commands.context: "{endRenderPass} 之後的第二次轉換讓輸出紋理進入可呈現的佈局。{submit} 結束記錄並提交命令緩衝區,{wait} 阻塞至本次提交完成,隨後 {present} 請求顯示渲染結果。" +tutorial.frame.commands.description: "渲染通道將寫入同一組附件的繪製操作放在一起。本通道使用交換鏈的輸出紋理接收色彩結果。{colorAttachmentClear} 指定以 RGBA 色彩初始化附件,並在通道結束時保留內容。{beginRenderPass} 依這些設定記錄通道的開始命令。" +tutorial.frame.commands.details: "集合中有一個色彩附件。{null} 表示此通道不使用深度/樣板附件。" +tutorial.frame.commands.guidance: "{beginRenderPass} 預設讓視口與裁剪區域覆蓋整個附件。視口將渲染座標映射為像素位置,裁剪區域則限制可以寫入的範圍。" +tutorial.frame.commands.title: "清除、提交與呈現" +tutorial.frame.description: "先將視窗填滿單一背景色,這個操作稱為清除。背景正常顯示後,就能確認呈現目標、命令提交與呈現流程已連接完成,接著再加入三角形的頂點與著色器。" +tutorial.frame.details: "Silk.NET 在需要繪製一個影格時呼叫渲染回呼。本範例不使用回呼傳入的時間間隔,因此將該引數命名為 {value}。在{emphasis}註冊回呼:" tutorial.frame.details.emphasis: "{windowRun} 之前" -tutorial.frame.target.description: "{graphicsQueueCommandBuffer} 會取得已開始記錄的命令緩衝區。記錄是為 GPU 描述工作;它不會立即執行該工作。" -tutorial.frame.target.details: 第一個 {transition} 會準備輸出紋理以供色彩附件存取。{default} 選取 Mip 層級 0 與陣列層 0。我們使用 {undefined} 作為前一個配置,因為我們將清除整個影像並捨棄先前的內容。需要保留現有內容的通道則必須改用其實際的前一個配置。 -tutorial.frame.target.guidance: 每個影格請使用交換鏈目前的輸出紋理。呈現操作可能會變更可用的影像,因此從較早影格儲存的紋理並非永久的視窗渲染目標。 -tutorial.frame.target.title: 準備輸出紋理 -tutorial.frame.title: 顯示背景色彩 -tutorial.geometry.data.description: 在{emphasis}新增此陣列。後續的資源建立步驟也依所示順序位於該回呼之前。 +tutorial.frame.target.description: "{graphicsQueueCommandBuffer} 傳回可直接記錄的命令緩衝區。記錄描述 GPU 工作,提交後才開始執行。" +tutorial.frame.target.details: "紋理佈局描述操作如何存取紋理。第一次 {transition} 讓輸出紋理準備好作為色彩附件。這裡的 {default} 選擇 mip 級別 0 與陣列層 0,也就是輸出紋理的基本影像。由於這個通道會清除整張影像,可以指定 {undefined},允許丟棄先前內容。" +tutorial.frame.target.guidance: "呈現後可能換用另一張影像,因此每個影格都要重新取得目前的輸出紋理。" +tutorial.frame.target.title: "準備輸出紋理" +tutorial.frame.title: "第一個影格" +tutorial.geometry.data.description: "在{emphasis}新增頂點陣列。後續資源初始化也放在該回呼之前,順序如下。" tutorial.geometry.data.description.emphasis: "{windowRender} 之前" -tutorial.geometry.data.details: 每個陣列項目建立一個 {vertex}。內部的兩個 {new} 運算式建立其 {vector3} 位置與 {vector4} 色彩。頂點描述了頂部、右下角與左下角。頂點著色器將提供第四個位置座標 {w}。當 w 等於 1 時,x 與 y 直接描述標準化裝置座標:-1 與 +1 是影像邊緣,0 是中心。這些座標與視窗的像素尺寸無關。 -tutorial.geometry.data.guidance: "每種色彩包含紅、綠、藍與 Alpha 分量。三個頂點的 Alpha 皆為 1,且位置的 z 座標皆為 0,因此位於同一平面上。這些位置已經直接描述要渲染的座標,無需相機或變換矩陣。對於這個單一平面三角形,我們還會停用混合與深度測試,並省略深度緩衝區。" -tutorial.geometry.data.title: 選擇頂點位置 -tutorial.geometry.description: "頂點由一個位置以及繪製時使用的資料組成。我們的三角形有三個頂點,每個角各一個。每個頂點都包含位置與色彩。GPU 會對色彩進行插補,計算三角形內部各處的中間值。" -tutorial.geometry.format.description: 在{emphasis}附加此宣告: +tutorial.geometry.data.details: "每個條目構造一個 {vertex},內部的兩個 {new} 表示式分別提供 {vector3} 位置和 {vector4} 顏色。三個位置對應上角、右下角和左下角。頂點著色器將 {w} 作為第四個位置座標;w 為 1 時,x、y 也就是正規化裝置座標,-1 與 +1 對應影像邊界,0 對應中心,與像素尺寸無關。" +tutorial.geometry.data.guidance: "每個色彩包含紅、綠、藍與 alpha 分量,alpha 設為 1。三個頂點的 z 座標均為 0,位於同一平面。" +tutorial.geometry.data.title: "頂點位置與顏色" +tutorial.geometry.description: "三角形的每個頂點都有位置與色彩。GPU 依三個位置決定三角形的形狀,再對頂點色彩內插,算出內部各處的色彩。" +tutorial.geometry.format.description: "在{emphasis}追加頂點宣告:" tutorial.geometry.format.description.emphasis: "{programCs} 的結尾處、清理陳述式之後" -tutorial.geometry.format.details: "{file} 將此型別限制在 {programCs} 內,建構函式初始化其位置與色彩欄位。{layoutKindSequential} 保持欄位依宣告順序排列。{position} 包含三個 32 位元浮點數,{color} 包含四個。在此結構中,位置始於位元組 0,色彩始於位元組 12,完整的頂點佔用 28 個位元組。我們將向圖形管線描述這完全相同的配置。" -tutorial.geometry.format.title: 定義頂點 -tutorial.geometry.title: 向 GPU 提供三個頂點 -tutorial.geometry.upload.context: "{fixed} 可防止記憶體回收行程在使用陣列位址時移動該陣列。對於此 CPU 可寫入的緩衝區,{upload} 在返回之前會對應、複製並取消對應記憶體,因此之後無需保持陣列固定。緩衝區在整個渲染過程中必須保持存活,且上傳只需進行一次,因為頂點不會改變。" -tutorial.geometry.upload.description: 受控陣列是 CPU 資料。{buffer} 提供 GPU 可從中讀取頂點的儲存空間。在陣列之後新增: -tutorial.geometry.upload.details: 總大小為 {sizeofVertexVerticesLength}:每個頂點 28 位元組,三個頂點,總共 84 位元組。{bufferUsagesVertex} 允許頂點輸入存取。{cpuWriteOnly} 允許 CPU 直接初始化此小型緩衝區。描述項的跨距記錄了元素大小;我們稍後建立的輸入配置將指示頂點擷取機制如何讀取個別屬性。 -tutorial.geometry.upload.guidance: 建立緩衝區並不會填入資料。{upload} 會將陣列複製到該配置中,起始於目標位元組位移 0。其來源描述提供指標與要複製的位元組數。 -tutorial.geometry.upload.notes: 在 {programCs} 底部的清理程式碼中,緊接在 {swapChainDispose} 之前新增 {vertexBufferDispose}。對於較大型的靜態幾何體,{link}解釋了何時應選擇僅 GPU 記憶體並改用傳輸上傳。 -tutorial.geometry.upload.notes.link: 資源管理 -tutorial.geometry.upload.title: 配置緩衝區並上傳陣列 -tutorial.input.description: 頂點位元組與著色器皆已就緒。接下來描述 GPU 應該如何讀取每個頂點。屬性是單一值,例如位置或色彩。輸入配置賦予每個屬性格式與位元組位移;跨距提供從一個頂點到下一個頂點的位元組距離。在建立著色器後新增此初始化區塊: -tutorial.input.details: "{inputLayoutAdd} 會在目前跨距處附加元素,並將該跨距增加該元素的大小。它不會檢查 C# 結構。在此處它產生了 CPU 記憶體與著色器輸入之間的下列協議:" -tutorial.input.guidance: "變更 C# 欄位順序或填補而未更新此描述會使 GPU 讀取錯誤的位元組。預設的 {semanticIndex} 為零,符合 {pOSITION0} 與 {cOLOR0}。兩個元素屬於同一個緩衝區,因此管線將包含一個輸入配置,且我們會將該緩衝區繫結至插槽 0。" -tutorial.input.table.headings.byteOffset: 位元組位移 +tutorial.geometry.format.details: "{file} 將型別的使用範圍限定在 {programCs},{layoutKindSequential} 則保留欄位的宣告順序。{position} 包含三個 32 位元浮點數,位元組位移為 0;{color} 包含四個,位元組位移為 12。因此,每個頂點占 28 位元組。稍後會透過輸入佈局描述這個排列,讓 GPU 正確讀取各欄位。" +tutorial.geometry.format.imports: "在 {programCs} 頂端加入以下 using 指示詞,以使用向量型別與結構佈局屬性:" +tutorial.geometry.format.title: "頂點表示" +tutorial.geometry.title: "頂點資料" +tutorial.geometry.upload.context: "{fixed} 可避免記憶體回收行程在位址使用期間移動陣列。對於這個 CPU 可寫緩衝區,{upload} 會映射記憶體、複製資料,再解除映射後返回,因此只需在呼叫期間固定陣列。頂點資料在初始化時上傳一次即可;緩衝區則必須保留到渲染結束。" +tutorial.geometry.upload.description: "將頂點存入 {buffer},供 GPU 在繪製時讀取。緊接在頂點陣列之後,加入配置與上傳程式碼:" +tutorial.geometry.upload.details: "配置大小為 {sizeofVertexVerticesLength},即三個 28 位元組頂點,共 84 位元組。{bufferUsagesVertex} 宣告頂點輸入用途,{cpuWriteOnly} 允許 CPU 直接初始化。描述中的跨距記錄元素大小,隨後定義的輸入佈局指定 GPU 如何讀取各個頂點屬性。" +tutorial.geometry.upload.guidance: "配置空間不會初始化緩衝區內容。{upload} 使用資料描述中的來源指標與位元組數,將陣列複製到目標位元組位移 0。" +tutorial.geometry.upload.imports: "在 {programCs} 頂端的 using 指示詞中加入 {bufferAlias},以區分 Zenith.NET 的緩衝區型別與 {systemBuffer}。" +tutorial.geometry.upload.notes: "在 {programCs} 結尾的清理程式碼中,緊接在 {swapChainDispose} 之前加入 {vertexBufferDispose}。較大型靜態幾何體所需的 GPU 專用儲存與上傳方式,見{link}。" +tutorial.geometry.upload.notes.link: "資源管理" +tutorial.geometry.upload.title: "緩衝區配置與上傳" +tutorial.input.description: "GPU 需要知道位置、色彩等頂點屬性儲存在哪裡。輸入佈局指定各屬性的格式與位元組位移,並以跨距表示兩個相鄰頂點相隔多少位元組。在建立著色器之後加入以下程式碼:" +tutorial.input.details: "{inputLayoutAdd} 將屬性依序排列,並將每個屬性的大小加到跨距中。位移是根據這裡提供的格式計算,不是透過檢查 C# 結構取得。這兩個欄位的佈局如下:" +tutorial.input.guidance: "{semanticIndex} 預設為 0,對應著色器中的 {pOSITION0} 與 {cOLOR0}。位置與色彩存放在同一個頂點緩衝區,因此管線只需在槽 0 使用一個輸入佈局。若 C# 結構的欄位順序或填充改變,也要一併調整此佈局。" +tutorial.input.table.headings.byteOffset: "位元組位移" tutorial.input.table.headings.cField: "C# 欄位" -tutorial.input.table.headings.format: 格式 -tutorial.input.table.headings.shaderInput: 著色器輸入 -tutorial.input.table.nextVertex.cField: 下一個頂點 -tutorial.input.table.nextVertex.format: 總跨距:28 位元組 -tutorial.input.table.nextVertex.shaderInput: 下一筆輸入記錄 +tutorial.input.table.headings.format: "格式" +tutorial.input.table.headings.shaderInput: "著色器輸入" +tutorial.input.table.nextVertex.cField: "下一個頂點" +tutorial.input.table.nextVertex.format: "總跨距:28 位元組" +tutorial.input.table.nextVertex.shaderInput: "下一筆輸入記錄" tutorial.input.table.vertexColor.format: "{float4}(16 位元組)" tutorial.input.table.vertexPosition.format: "{float3}(12 位元組)" -tutorial.input.title: 描述頂點輸入配置 -tutorial.lifecycle.description: 完成的應用程式會重複此順序: -tutorial.lifecycle.details: 關閉視窗會從 {run} 返回。每個渲染完成的影格都已等待其 GPU 工作完成,因此我們現在可以處置它所使用的資源。{windowRun} 之後的清理程式碼應為: -tutorial.lifecycle.guidance: "在銷毀原生視窗前釋放交換鏈,並在釋放所有資源後釋放圖形上下文。佇列擁有並回收提交的命令緩衝區,交換鏈擁有其輸出紋理。因此,本應用程式不需要個別對這些命令緩衝區或輸出紋理呼叫 {dispose}。" -tutorial.lifecycle.title: 追蹤單一影格的生命週期 -tutorial.pipeline.behavior: 在輸入配置之後新增: -tutorial.pipeline.context: "{cullNone} 會填滿三角形而不捨棄任何面朝向。其頂點的順序決定了面的環繞方向,因此停用剔除可防止該順序隱藏我們第一個三角形。" -tutorial.pipeline.description: 我們現在擁有頂點資料、輸入配置與兩個著色器。{graphicsPipeline} 將它們連接起來,並指定 GPU 如何將頂點組裝為基本圖元並將結果寫入附件。 -tutorial.pipeline.details: 管線將可程式化著色器階段與固定功能設定結合,後者控制諸如三角形組裝、面剔除與混合等 GPU 操作。對於此三角形,請選取下列設定: -tutorial.pipeline.guidance: 色彩格式取自 {swapChainDescFormat}。它必須符合渲染通道所使用的影像。{count1} 代表每個像素一個取樣。 -tutorial.pipeline.item: "{triangleList} 會將每組連續的三個頂點組裝成一個三角形。我們將提供三個頂點並繪製一次,因此不需要索引緩衝區。" -tutorial.pipeline.notes: "{depthNone} 會停用深度測試與寫入,符合沒有深度附件的通道。" -tutorial.pipeline.reference: "{opaque} 會停用混合,因此片元著色器的色彩會取代三角形內部的背景。" -tutorial.pipeline.title: 連接著色器與頂點配置 -tutorial.pipeline.usage: 著色器物件可在建立管線後釋放,正如範例渲染器中所做的那樣。對於使用該管線進行繪製的每個影格,請保持管線本身存活。在清理程式碼中將 {pipelineDispose} 加入 {vertexBufferDispose} 之前。管線建立是渲染回呼前的最後一個初始化步驟。 -tutorial.pipeline.validation: 管線描述宣告了附件設定;它不會建立另一個影像。{inputLayouts} 只有一個項目,因為位置與色彩一起儲存在單一緩衝區中。 -tutorial.presentation.title: 將 GPU 連接至視窗 -tutorial.project.context: 在專案建置設定中啟用{emphasis}({allowUnsafeBlocks})。我們將用它將頂點資料傳遞給 GPU,並用於視窗協助程式的原生呼叫。 -tutorial.project.context.emphasis: 允許不安全的程式碼 -tutorial.project.description: 建立專案並進入其目錄: -tutorial.project.details: 安裝套件: -tutorial.project.guidance: "{zenithNET} 提供共用渲染 API。這三個後端套件讓同一個程式能選擇適合其平台的實作。{zenithNETCompiler} 會針對該實作編譯 Slang 著色器(我們稍後將編寫的小型 GPU 程式)。Silk.NET 提供視窗與事件迴圈。" -tutorial.project.title: 建立主控台專案 -tutorial.requirements.context: 您可以從空白專案開始跟隨本頁操作。{link}與其{detail}可作為此處使用之渲染與視窗 API 的參考。 +tutorial.input.title: "頂點輸入佈局" +tutorial.lifecycle.description: "每個影格依次執行以下操作:" +tutorial.lifecycle.details: "關閉視窗後,{run} 返回,程式繼續執行清理程式碼。每個影格都已等待其提交完成,因此現在可以釋放這些命令使用的資源。{windowRun} 之後完整的清理程式碼如下:" +tutorial.lifecycle.guidance: "先釋放交換鏈,再銷毀其原生視窗;先釋放應用程式資源,再釋放上下文。已提交的命令緩衝區由佇列回收,輸出紋理由交換鏈管理,兩者都不需要單獨呼叫 {dispose}。" +tutorial.lifecycle.title: "影格生命週期與清理" +tutorial.pipeline.behavior: "在輸入佈局之後建立管線:" +tutorial.pipeline.context: "{cullNone} 關閉面剔除,因此無論頂點在畫面中呈順時針或逆時針排列,三角形都會被繪製。" +tutorial.pipeline.description: "{graphicsPipeline} 將頂點佈局、兩個著色器,以及圖元組裝和附件輸出所需的設定組合在一起。" +tutorial.pipeline.details: "著色器負責處理頂點與片元。其餘管線設定決定圖元如何組裝、是否剔除特定朝向的面,以及如何執行深度測試和色彩混合:" +tutorial.pipeline.guidance: "管線顏色格式必須匹配渲染通道附件,因此直接取自 {swapChainDescFormat}。{count1} 表示每像素一個取樣點。" +tutorial.pipeline.item: "{triangleList} 將每組連續的三個頂點組裝成一個三角形。" +tutorial.pipeline.notes: "{depthNone} 關閉深度測試和深度寫入,與通道沒有深度附件的設定一致。" +tutorial.pipeline.reference: "{opaque} 關閉混合,因此片元著色器輸出直接替換三角形內部的背景色。" +tutorial.pipeline.title: "圖形管線" +tutorial.pipeline.usage: "管線建立完成後即可釋放著色器物件。渲染期間保留管線,在清理程式碼中將 {pipelineDispose} 放在 {vertexBufferDispose} 之前。" +tutorial.presentation.title: "圖形上下文與呈現" +tutorial.project.context: "在專案建置設定中啟用{emphasis}({allowUnsafeBlocks})。視窗輔助程式碼的原生呼叫和頂點上傳需要不安全程式碼。" +tutorial.project.context.emphasis: "允許不安全的程式碼" +tutorial.project.description: "建立名為 {firstTriangle} 的 C# 主控台專案,目標框架設為 .NET 10。" +tutorial.project.details: "為專案加入以下 NuGet 套件:" +tutorial.project.guidance: "{zenithNET} 提供統一渲染 API,三個後端套件提供各平台的實作。{zenithNETCompiler} 為所選後端編譯稍後介紹的 Slang 著色器。Silk.NET 負責視窗建立與事件處理。" +tutorial.project.title: "專案設定" +tutorial.requirements.context: "{link}及其{detail}提供了本教學的參考實作。" tutorial.requirements.context.detail: "共用宿主程式" -tutorial.requirements.context.link: Hello Triangle 範例 -tutorial.requirements.description: "您需要 {emphasis}、程式碼編輯器或 IDE,以及配備 Zenith.NET 後端所支援之 GPU 與驅動程式的桌上型電腦。具備基礎 C# 知識即可;圖形概念會在初次使用時一併介紹。這是一個標準的 {net10} 主控台專案。後端負責將 Zenith.NET 操作轉譯為對圖形 API(例如 DirectX 12、Metal 或 Vulkan)的呼叫。應用程式在啟動時選擇其一:" -tutorial.requirements.description.emphasis: .NET 10 SDK -tutorial.requirements.details: 在此處使用的視窗路徑中,Linux 需要與 X11 相容的視窗工作階段。此三角形不需要選用的光線追蹤與網格著色(mesh shading)功能。 -tutorial.requirements.guidance: Zenith.NET 會渲染至應用程式提供的表面。Silk.NET.Windowing 將建立桌面視窗並處理其事件。在 macOS 上,呈現目標為 Metal 圖層({cAMetalLayerCs});教學的視窗協助程式會為我們附加該圖層。 -tutorial.requirements.table.headings.graphicsBackend: 圖形後端 -tutorial.requirements.table.headings.platform: 平台 -tutorial.requirements.table.headings.windowSurface: 視窗表面 -tutorial.requirements.table.linux.graphicsBackend: Vulkan 1.4 -tutorial.requirements.table.linux.platform: Linux -tutorial.requirements.table.linux.windowSurface: X11 視窗與顯示;XWayland 亦適用 -tutorial.requirements.table.macOS.graphicsBackend: Metal 4 -tutorial.requirements.table.macOS.platform: macOS -tutorial.requirements.table.macOS.windowSurface: 附加至視窗的 Metal 圖層 -tutorial.requirements.table.windows.graphicsBackend: DirectX 12 -tutorial.requirements.table.windows.platform: Windows -tutorial.requirements.table.windows.windowSurface: Win32 視窗控制代碼 -tutorial.requirements.title: 開始之前 -tutorial.resize.context: 再次執行 {dotnetRun}。視窗現在應該具有均勻的深色背景,並在調整大小後繼續填滿視窗。請保留此回呼:三角形將繪製在其現有的渲染通道內。 -tutorial.resize.description: 交換鏈的影像必須遵循畫面緩衝區的尺寸。使用 {framebufferResize} 回應像素大小的變更,包括因顯示比例調整而引起的變更。在渲染回呼之後、仍處於 {windowRun} 之前新增: -tutorial.resize.details: Silk.NET 會區分視窗大小變更與{link}。我們需要後者,因為交換鏈儲存的是像素。最小化的視窗可能具有零大小的畫面緩衝區。在這種情況下,兩個回呼都會略過其 GPU 工作。調整大小後,渲染通道將使用新的附件尺寸作為其視口與裁剪區域。 -tutorial.resize.details.link: 畫面緩衝區大小變更 -tutorial.resize.guidance: 我們在每次提交後都會等待,因此當調整大小處理常式取代影像時,沒有較早的影格仍在使用這些影像。目前的 {present} 實作也會在圖形佇列上等待。這個簡單的迴圈確保前一個影格的工作完成後下一個影格才會開始;{link}涵蓋了更進階的排程方式。 -tutorial.resize.guidance.link: 同步 -tutorial.resize.title: 回應視窗大小調整 -tutorial.shaders.compilation.context: 編譯會在初始化期間執行一次。{appContextBaseDirectory} 負責在可執行檔旁找出複製的著色器,而與目前工作目錄無關。這些著色器僅使用頂點輸入,因此目前尚無常數緩衝區、紋理或資源控制代碼需要繫結。 -tutorial.shaders.compilation.description: "在 {triangleSlang} 的檔案屬性中,將{emphasis}設為{detail}。建置時會將著色器複製到可執行檔旁。" -tutorial.shaders.compilation.description.detail: 有更新時才複製 -tutorial.shaders.compilation.description.emphasis: 複製到輸出目錄 -tutorial.shaders.compilation.details: 返回 {programCs}。在頂點上傳之後、渲染回呼之前新增這些初始化陳述式: -tutorial.shaders.compilation.guidance: "{zenithCompiler} 會傳回包含所要求圖形 API 程式碼的著色器描述。{createShader} 會建立對應的後端物件。圖形 API 與進入點名稱皆至關重要:使用 {contextGraphicsApi},並將 {vSMain} 與 {fSMain} 拼寫得與 Slang 檔案完全相同。" -tutorial.shaders.compilation.title: 針對選取的後端進行編譯 -tutorial.shaders.context: "{fSInput} 連接頂點著色器的輸出與片元著色器的輸入。由頂點著色器寫入時,{sVPOSITION} 提供裁剪空間位置,即 GPU 用來判斷哪些內容位於可見影像範圍內的四個座標。{cOLOR0} 傳遞要在頂點之間插補的色彩。兩個階段使用的型別與語意必須一致。" -tutorial.shaders.description: 著色器是由 GPU 執行的程式。本次繪圖需要一個頂點著色器來定位頂點,以及一個片元著色器來產生三角形內部的色彩。我們將使用 Slang 著色器語言編寫它們,並從同一個檔案編譯兩個進入點。進入點是著色器階段開始執行的函式。 -tutorial.shaders.details: 建立 {triangleSlang},從以下兩個結構開始: -tutorial.shaders.fragment.description: 將片元進入點附加至同一個檔案: -tutorial.shaders.fragment.details: 光柵化決定三角形涵蓋哪些影像位置。它會產生片元(由片元著色器處理的資料),頂點色彩在涵蓋區域內進行插補。{fSMain} 透過識別第一個色彩附件的 {sVTARGET} 傳回此插補色彩。 -tutorial.shaders.fragment.guidance: 頂點色彩插補與附件混合是獨立分開的。混合會將片元的輸出與附件中已儲存的色彩結合。我們的不透明混合狀態停用了該結合,因此插補色彩會直接取代三角形內部的背景。 -tutorial.shaders.fragment.title: 為片元著色 -tutorial.shaders.guidance: "{vSInput} 描述頂點著色器從頂點緩衝區接收的內容。語意 {pOSITION0} 與 {cOLOR0} 識別輸入;僅憑 C# 欄位名稱無法建立該對應。" -tutorial.shaders.title: 編寫兩個著色器階段 -tutorial.shaders.vertex.description: 將頂點進入點附加至 {triangleSlang}: -tutorial.shaders.vertex.details: GPU 會針對每個輸入頂點叫用此進入點。它將齊次座標 {w} 加入位置並轉發色彩。在頂點階段之後,位置會除以 w;在此處該除法保持 x、y 與 z 不變。這就是為何上方選擇的位置可以直接理解為標準化裝置座標的原因。 -tutorial.shaders.vertex.title: 定位每個頂點 -tutorial.surface.description: 圖形上下文還需要知道要在何處顯示其輸出。在{emphasis}新增下列內容: +tutorial.requirements.context.link: "Hello Triangle 範例" +tutorial.requirements.description: "需要 {emphasis},並具備基礎 C# 知識。應用程式以 {net10} 為目標框架。GPU 與驅動程式須支援所在平台選用的後端:" +tutorial.requirements.description.emphasis: ".NET 10 SDK" +tutorial.requirements.guidance: "Zenith.NET 渲染到應用程式提供的原生呈現目標。Silk.NET.Windowing 建立視窗並處理事件。macOS 使用由 {cAMetalLayerCs} 表示的 Metal 圖層,視窗輔助程式碼負責將它連接到視窗。" +tutorial.requirements.table.headings.graphicsBackend: "圖形後端" +tutorial.requirements.table.headings.platform: "平台" +tutorial.requirements.table.linux.graphicsBackend: "Vulkan 1.4" +tutorial.requirements.table.linux.platform: "Linux(X11 或 XWayland)" +tutorial.requirements.table.macOS.graphicsBackend: "Metal 4" +tutorial.requirements.table.macOS.platform: "macOS" +tutorial.requirements.table.windows.graphicsBackend: "DirectX 12" +tutorial.requirements.table.windows.platform: "Windows" +tutorial.requirements.title: "準備事項" +tutorial.resize.context: "再次建置並執行程式。調整視窗大小後,背景應繼續填滿整個視窗:每次開始新的渲染通道時,視口與裁剪區域都會依附件的新尺寸設定。保留渲染回呼,稍後將在這個通道內繪製三角形。" +tutorial.resize.description: "畫面緩衝區尺寸改變時,交換鏈也要跟著調整。在渲染回呼之後、{windowRun} 之前註冊 {framebufferResize} 回呼:" +tutorial.resize.details: "這裡接收的是以像素為單位的{link},而不是視窗邏輯尺寸的變化。視窗最小化時,畫面緩衝區的寬度或高度可能變成零。此時,尺寸變更回呼保留現有交換鏈,不進行調整。渲染回呼也會在任一尺寸為零時直接返回,直到畫面緩衝區恢復有效尺寸後才繼續繪製。" +tutorial.resize.details.link: "畫面緩衝區大小變更" +tutorial.resize.guidance: "渲染回呼會等待目前影格的提交完成,再呼叫 {present}。因此,尺寸變更回呼替換交換鏈影像時,先前影格的工作已經結束。完成狀態與資源生命週期的要求,詳見{link}。" +tutorial.resize.guidance.link: "同步" +tutorial.resize.title: "視窗尺寸變化" +tutorial.shaders.compilation.context: "{appContextBaseDirectory} 讓程式從輸出目錄載入已複製的著色器。即使從其他工作目錄啟動程式,尋找檔案的位置也不會改變。" +tutorial.shaders.compilation.description: "將 {triangleSlang} 的檔案屬性{emphasis}設為{detail},建置時便會將著色器複製到執行檔所在目錄。" +tutorial.shaders.compilation.description.detail: "有更新時才複製" +tutorial.shaders.compilation.description.emphasis: "複製到輸出目錄" +tutorial.shaders.compilation.details: "回到 {programCs},在頂點上傳之後、渲染回呼之前加入著色器初始化:" +tutorial.shaders.compilation.guidance: "{zenithCompiler} 為 {contextGraphicsApi} 指定的後端編譯原始碼,{createShader} 再依編譯後的描述建立著色器物件。進入點名稱 {vSMain} 與 {fSMain} 分別選取 Slang 檔案中定義的兩個函式。" +tutorial.shaders.compilation.title: "編譯著色器" +tutorial.shaders.context: "{fSInput} 連接兩個著色器階段。頂點著色器將裁剪空間位置寫入 {sVPOSITION},GPU 據此判斷三角形的可見部分。{cOLOR0} 欄位傳遞頂點色彩,經過三角形內部的內插後再交給片元著色器。兩個階段必須採用相同的色彩型別與語義。" +tutorial.shaders.description: "著色器是在 GPU 上執行的程式。頂點著色器決定每個頂點的位置,片元著色器則決定影像中被覆蓋位置的色彩。接下來會將兩個階段寫在同一個 Slang 檔案,並分別定義進入點,也就是各階段開始執行的函式。" +tutorial.shaders.details: "建立 {triangleSlang},先定義輸入與輸出結構:" +tutorial.shaders.fragment.description: "在同一檔案中追加片元進入點:" +tutorial.shaders.fragment.details: "光柵化判定三角形在影像中的覆蓋範圍,並在這些位置產生片元。每個片元的色彩由三個頂點的色彩內插而得。{fSMain} 傳回這個色彩,{sVTARGET} 則將結果送到第一個色彩附件。" +tutorial.shaders.fragment.title: "片元著色" +tutorial.shaders.guidance: "{vSInput} 定義頂點著色器輸入。{pOSITION0} 和 {cOLOR0} 按語義識別屬性,C# 欄位名稱本身不建立這一映射。" +tutorial.shaders.title: "著色器階段" +tutorial.shaders.vertex.description: "在 {triangleSlang} 中追加頂點進入點:" +tutorial.shaders.vertex.details: "GPU 為每個輸入頂點呼叫這一進入點,補充齊次座標 {w} 並傳遞顏色。頂點處理結束後,位置要除以 w。本例 w 為 1,x、y、z 保持不變,可直接解釋為正規化裝置座標。" +tutorial.shaders.vertex.title: "頂點著色" +tutorial.surface.description: "在{emphasis}指定原生呈現目標:" tutorial.surface.description.emphasis: "{windowCenter} 之後、{windowRun} 之前" -tutorial.surface.details: "{surface} 描述原生呈現目標及其像素尺寸。畫面緩衝區是與視窗關聯的像素影像。{framebufferSize} 以像素為單位提供其尺寸;啟用顯示比例縮放時,視窗的邏輯尺寸可能會有所不同。" -tutorial.surface.guidance: 此表面與上方選取的後端相符。Windows 提供視窗控制代碼,Linux 提供 X11 顯示與視窗,macOS 協助程式則提供附加的 Metal 圖層。這是將視窗連接至渲染流程中唯一與平台相關的部分。 -tutorial.surface.title: 描述原生呈現目標 -tutorial.swapChain.context: 交換鏈同時使用圖形上下文與原生視窗。將 {programCs} 底部的 {windowDispose} 行取代為以下清理順序: -tutorial.swapChain.description: 使用表面描述來建立將要呈現的影像。緊接在表面區塊之後新增: -tutorial.swapChain.details: "{swapChain} 管理視窗中顯示的影像。在每個影格中,{drawable} 會以影像資料 API 型別 {texture} 的形式為我們提供目前影像。繪製後,{present} 會要求顯示結果並前進至下一個 drawable。" -tutorial.swapChain.guidance: "{b8G8R8A8UNorm} 依藍、綠、紅與 Alpha 順序儲存四個 8 位元色彩通道。{uNorm} 表示 0 到 255 的整數值對應 0 到 1 的數值。著色器仍會傳回邏輯 RGBA 值;此格式決定這些通道在影像中的儲存方式。稍後圖形管線將使用 {swapChainDescFormat} 來匹配此附件。" -tutorial.swapChain.title: 建立交換鏈 -tutorial.title: 第一個三角形 -tutorial.troubleshooting.description: 先閱讀主控台中的任何錯誤,然後使用先前的檢查點來找出失敗的階段: -tutorial.troubleshooting.details: "使用 {link} 與 {detail} 來比較頂點資料、輸入配置與繪製操作。該範例將視窗處理與提交放入共用宿主程式;本教學則將應用程式流程保留在 {programCs} 中。請繼續閱讀 {context} 以學習索引繪製、變換與深度測試。" -tutorial.troubleshooting.details.context: 旋轉立方體 -tutorial.troubleshooting.details.detail: Slang 著色器 -tutorial.troubleshooting.details.link: 範例渲染器 -tutorial.troubleshooting.table.backend.check: 檢查選取的後端是否受到裝置與已安裝的圖形驅動程式支援。 -tutorial.troubleshooting.table.backend.symptom: 後端建立失敗 -tutorial.troubleshooting.table.drawing.check: 檢查上傳大小、輸入配置、管線選取,以及渲染通道內部繪製命令的位置。 -tutorial.troubleshooting.table.drawing.symptom: 背景出現但三角形未出現 -tutorial.troubleshooting.table.headings.check: 檢查項目 -tutorial.troubleshooting.table.headings.symptom: 徵狀 -tutorial.troubleshooting.table.input.check: 檢查 28 位元組跨距以及 0 與 12 的位置/色彩位移。 -tutorial.troubleshooting.table.input.symptom: 頂點位置或色彩損毀 -tutorial.troubleshooting.table.shaders.check: 檢查複製的 {triangleSlang}、進入點拼寫,以及編譯器回報的診斷資訊。 -tutorial.troubleshooting.table.shaders.symptom: 清除色彩步驟運作正常,但著色器載入失敗 -tutorial.troubleshooting.table.window.check: 確認 .NET 專案可成功建置,且僅含視窗的步驟可在桌面工作階段中執行。在 Linux 上,檢查 X11 或 XWayland 是否可用。 -tutorial.troubleshooting.table.window.symptom: 沒有開啟任何視窗 -tutorial.troubleshooting.title: 檢查失敗的階段 -tutorial.window.context: "{usingZenithTutorials} 會匯入協助程式的命名空間。每個 C# 檔案都使用各自的一般 using 指示詞,因此兩個檔案都需要互通性匯入。別名 {buffer} 是指 Zenith.NET 緩衝區型別,並將其與 {systemBuffer} 區分開來。" -tutorial.window.description: 將 {cocoaHelperCs} 新增至專案,並保留其命名空間。在該檔案頂端、其命名空間宣告之前新增 {interopUsing}。該協助程式會在 macOS 上將 Metal 圖層附加至視窗;其他平台分支不會呼叫它。 -tutorial.window.details: 將產生的 {programCs} 取代為下列程式碼。它使用最上層陳述式,依序執行而無需明確的 {main} 方法。後續小節將說明在此同一個檔案中新增程式碼的位置: -tutorial.window.guidance: "{graphicsAPINone} 要求 Silk.NET 建立沒有自身圖形上下文的視窗。我們將使用 Zenith.NET 建立該上下文。{initialize} 建立原生視窗並提供其控制代碼。控制代碼是由視窗系統提供的識別碼。{center} 使視窗置中,而 {run} 會處理事件直到視窗關閉。接著執行會繼續進行至 {dispose},釋放視窗。" -tutorial.window.notes: 執行 {dotnetRun}。應該會開啟一個空白視窗,並能回應移動、調整大小與關閉操作。由於我們尚未提交任何渲染命令,其內容尚未定義。請先將其關閉再繼續。 -tutorial.window.title: 開啟視窗 -ui.action.copy: 複製 -ui.action.navigate: 巡覽 -ui.action.open: 開啟 -ui.action.source: 檢視原始碼 -ui.api.browse: 瀏覽命名空間與型別。 -ui.api.clearTypeSearch: 清除型別搜尋 -ui.api.findType: 尋找型別 -ui.api.loadError: 無法載入型別。重新載入此頁面以重試。 -ui.api.loadingNamespaces: 正在載入命名空間… -ui.api.loadingTypes: 正在載入型別… -ui.api.matchingTypes: 相符的型別 -ui.api.namespace: 命名空間 -ui.api.namespaces: 命名空間 -ui.api.noNamespaceTypes: 此命名空間中沒有型別。 -ui.api.noTypes: 沒有相符的型別。 -ui.api.types: 型別 -ui.content.reference: 參考 -ui.content.source: 原始碼 -ui.content.tutorial: 教學 -ui.contents.close: 關閉目錄 -ui.contents.open: 開啟目錄 -ui.contents.title: 目錄 -ui.footer.caption: 適用於 .NET 的現代 RHI。 -ui.footer.label: 頁尾 -ui.language.label: 語言 -ui.language.unavailable: 未翻譯 -ui.members.clear: 清除成員搜尋 -ui.members.close: 關閉成員尋找工具 -ui.members.empty: 沒有相符的成員。 -ui.members.open: 前往成員 -ui.members.placeholder: 名稱或簽章… -ui.members.search: 搜尋成員 -ui.members.title: 尋找成員 -ui.members.undeclared: 此型別沒有宣告的成員。 -ui.navigation.api: API -ui.navigation.concepts: 概念 -ui.navigation.home: 首頁 -ui.navigation.label: 主要導覽 -ui.navigation.toggle: 切換導覽 -ui.outline.title: 本頁內容 -ui.reference.assembly: 組件 -ui.reference.classes: 類別 -ui.reference.constructors: 建構函式 +tutorial.surface.details: "畫面緩衝區是視窗用來顯示的像素影像。{surface} 描述原生呈現目標及其尺寸,{framebufferSize} 則提供像素大小。啟用顯示縮放時,這個大小可能與視窗的邏輯尺寸不同。" +tutorial.surface.guidance: "呈現目標提供後端所需的原生控制代碼:Windows 使用 Win32 視窗,Linux 使用 X11 顯示與視窗,macOS 使用已連接的 Metal 圖層。" +tutorial.surface.title: "原生呈現目標" +tutorial.swapChain.context: "交換鏈需要上下文與視窗才能運作。將 {programCs} 結尾的 {windowDispose} 換成以下釋放順序:" +tutorial.swapChain.description: "緊接呈現目標描述,建立交換鏈:" +tutorial.swapChain.details: "{swapChain} 管理視窗呈現的影像。{drawable} 以影像資源 {texture} 的形式提供目前影像。渲染後,{present} 請求顯示該影像,並推進到下一個輸出紋理。" +tutorial.swapChain.guidance: "{b8G8R8A8UNorm} 按藍、綠、紅和 alpha 順序儲存四個 8 位元通道。{uNorm} 將整數 0–255 對應到 0–1。著色器仍輸出邏輯 RGBA 值,格式只規定儲存表示;管線透過 {swapChainDescFormat} 匹配附件。" +tutorial.swapChain.title: "交換鏈" +tutorial.title: "第一個三角形" +tutorial.troubleshooting.description: "結合主控台診斷與三個檢查點定位失敗階段:" +tutorial.troubleshooting.details: "{link}與{detail}可用於核對頂點資料、輸入佈局和繪製操作。該範例將視窗與提交邏輯放入共用宿主程式,本教學則保留在 {programCs} 中。{context}進一步介紹索引繪製、變換與深度測試。" +tutorial.troubleshooting.details.context: "旋轉立方體" +tutorial.troubleshooting.details.detail: "Slang 著色器" +tutorial.troubleshooting.details.link: "範例渲染器" +tutorial.troubleshooting.table.backend.check: "檢查選取的後端是否受到裝置與已安裝的圖形驅動程式支援。" +tutorial.troubleshooting.table.backend.symptom: "後端建立失敗" +tutorial.troubleshooting.table.drawing.check: "檢查上傳大小、輸入佈局、管線選擇,以及繪製命令是否位於渲染通道內。" +tutorial.troubleshooting.table.drawing.symptom: "背景出現但三角形未出現" +tutorial.troubleshooting.table.headings.check: "檢查項目" +tutorial.troubleshooting.table.headings.symptom: "徵狀" +tutorial.troubleshooting.table.input.check: "檢查跨距是否為 28 位元組,位置與色彩是否分別從位移 0 和 12 位元組開始。" +tutorial.troubleshooting.table.input.symptom: "頂點位置或色彩異常" +tutorial.troubleshooting.table.shaders.check: "檢查複製的 {triangleSlang}、進入點拼寫,以及編譯器回報的診斷資訊。" +tutorial.troubleshooting.table.shaders.symptom: "背景色正常顯示,但著色器載入失敗" +tutorial.troubleshooting.table.window.check: "確認 .NET 專案可成功建置,且僅含視窗的步驟可在桌面工作階段中執行。在 Linux 上,檢查 X11 或 XWayland 是否可用。" +tutorial.troubleshooting.table.window.symptom: "視窗未開啟" +tutorial.troubleshooting.title: "問題排查" +tutorial.window.description: "將 {cocoaHelperCs} 下載至專案中。此輔助類別負責將 Metal 圖層連接到 macOS 視窗。" +tutorial.window.details: "將自動產生的 {programCs} 內容換成以下程式碼。它使用最上層陳述式,依書寫順序執行,不需要明確撰寫 {main} 方法。後續各節會指出新程式碼應加入的位置:" +tutorial.window.guidance: "{graphicsAPINone} 將圖形上下文的建立交給 Zenith.NET。{initialize} 建立原生視窗,讓程式取得視窗系統的控制代碼;{center} 把視窗放在螢幕中央。{run} 持續處理事件直到視窗關閉,之後再執行 {dispose} 釋放視窗。" +tutorial.window.notes: "建置並執行程式,確認視窗可以開啟、移動、調整大小及關閉。此時尚未提交渲染命令,視窗內容還沒有定義。關閉視窗後再繼續。" +tutorial.window.title: "建立視窗" +ui.action.copy: "複製" +ui.action.navigate: "巡覽" +ui.action.open: "開啟" +ui.action.source: "檢視原始碼" +ui.api.browse: "瀏覽命名空間與型別。" +ui.api.clearTypeSearch: "清除型別搜尋" +ui.api.findType: "尋找型別" +ui.api.loadError: "無法載入型別。重新載入此頁面以重試。" +ui.api.loadingNamespaces: "正在載入命名空間…" +ui.api.loadingTypes: "正在載入型別…" +ui.api.matchingTypes: "相符的型別" +ui.api.namespace: "命名空間" +ui.api.namespaces: "命名空間" +ui.api.noNamespaceTypes: "此命名空間中沒有型別。" +ui.api.noTypes: "沒有相符的型別。" +ui.api.types: "型別" +ui.content.reference: "參考" +ui.content.source: "原始碼" +ui.content.tutorial: "教學" +ui.contents.close: "關閉目錄" +ui.contents.open: "開啟目錄" +ui.contents.title: "目錄" +ui.footer.caption: "面向 .NET 的現代 RHI" +ui.footer.label: "頁尾" +ui.language.label: "語言" +ui.language.unavailable: "未翻譯" +ui.members.clear: "清除成員搜尋" +ui.members.close: "關閉成員尋找工具" +ui.members.empty: "沒有相符的成員。" +ui.members.open: "前往成員" +ui.members.placeholder: "名稱或簽章…" +ui.members.search: "搜尋成員" +ui.members.title: "尋找成員" +ui.members.undeclared: "此型別沒有宣告的成員。" +ui.navigation.api: "API" +ui.navigation.concepts: "概念" +ui.navigation.home: "首頁" +ui.navigation.label: "主要導覽" +ui.navigation.toggle: "切換導覽" +ui.outline.title: "本頁內容" +ui.reference.assembly: "組件" +ui.reference.classes: "類別" +ui.reference.constructors: "建構函式" ui.reference.declaration: "C# 型別宣告" -ui.reference.delegates: 委派 -ui.reference.derived: 衍生型別 -ui.reference.enums: 列舉 -ui.reference.events: 事件 -ui.reference.examples: 範例 -ui.reference.exceptions: 例外狀況 -ui.reference.extensionMethods: 擴充方法 -ui.reference.fields: 欄位 -ui.reference.implementations: 明確介面實作 -ui.reference.implements: 實作 -ui.reference.inheritance: 繼承 -ui.reference.inheritedMembers: 繼承的成員 -ui.reference.interfaces: 介面 -ui.reference.metadata: 型別中繼資料 -ui.reference.methods: 方法 -ui.reference.namespace: 命名空間 -ui.reference.open: 開啟 {name} 的參考 -ui.reference.operators: 運算子 -ui.reference.parameters: 參數 -ui.reference.properties: 屬性 -ui.reference.related: 請參閱 -ui.reference.relationships: 繼承與中繼資料 -ui.reference.remarks: 備註 -ui.reference.returns: 傳回 -ui.reference.structs: 結構 -ui.reference.typeParameters: 型別參數 -ui.reference.value: 值 -ui.reference.values: 值 -ui.search.close: 關閉搜尋 -ui.search.empty: 找不到「{query}」的結果。 -ui.search.hint: 搜尋教學、概念、範例與 API 參考。 -ui.search.loading: 正在載入搜尋… -ui.search.more: 顯示更多結果 -ui.search.pending: 正在搜尋… -ui.search.placeholder: 您在尋找什麼? -ui.search.resultCount: 結果:{count} -ui.search.title: 搜尋文件 -ui.search.unavailable: 無法使用搜尋功能。您仍然可以開啟下方頁面。 +ui.reference.delegates: "委派" +ui.reference.derived: "衍生型別" +ui.reference.enums: "列舉" +ui.reference.events: "事件" +ui.reference.examples: "範例" +ui.reference.exceptions: "例外狀況" +ui.reference.extensionMethods: "擴充方法" +ui.reference.fields: "欄位" +ui.reference.implementations: "明確介面實作" +ui.reference.implements: "實作" +ui.reference.inheritance: "繼承" +ui.reference.inheritedMembers: "繼承的成員" +ui.reference.interfaces: "介面" +ui.reference.metadata: "型別中繼資料" +ui.reference.methods: "方法" +ui.reference.namespace: "命名空間" +ui.reference.open: "開啟 {name} 的參考" +ui.reference.operators: "運算子" +ui.reference.parameters: "參數" +ui.reference.properties: "屬性" +ui.reference.related: "請參閱" +ui.reference.relationships: "繼承與中繼資料" +ui.reference.remarks: "備註" +ui.reference.returns: "傳回" +ui.reference.structs: "結構" +ui.reference.typeParameters: "型別參數" +ui.reference.value: "值" +ui.reference.values: "值" +ui.search.close: "關閉搜尋" +ui.search.empty: "找不到「{query}」的結果。" +ui.search.hint: "搜尋教學、概念、範例與 API 參考。" +ui.search.loading: "正在載入搜尋…" +ui.search.more: "顯示更多結果" +ui.search.pending: "正在搜尋…" +ui.search.placeholder: "輸入搜尋內容" +ui.search.resultCount: "結果:{count}" +ui.search.title: "搜尋文件" +ui.search.unavailable: "搜尋暫時無法使用,可直接開啟下方頁面。" diff --git a/documents/locales/zh-TW/translation.md b/documents/locales/zh-TW/translation.md index a92c46b7..328a0ccc 100644 --- a/documents/locales/zh-TW/translation.md +++ b/documents/locales/zh-TW/translation.md @@ -8,6 +8,16 @@ 翻譯僅修改本目錄 `strings.yml` 的值。鍵集合必須與英文完全一致,不得自行新增、刪除或重新命名鍵,包括看似相同或尚未遇到的介面文字。如果原文有問題,請向維護者指出資源鍵及問題,先統一修正英文與共用頁面,再同步譯文。 +## 文風與上下文 + +採用嚴謹、自然的技術教材文風,先說明操作之間的關係,再交代條件與限制。教學保留明確的步驟及可觀察的結果。學術風格不代表必須增加被動句、抽象名詞或長句。 + +依文章的閱讀順序審校,搭配前後段落、表格與程式碼理解內容。資源鍵只是儲存邊界,不是獨立的翻譯單位。將連結標籤與強調片段放回完整句子,檢查語意與銜接,避免逐詞翻譯和重複要求讀者操作。 + +標題、介面標籤、首頁可見的簡短介紹與頁尾文案不加句末句號;正文、診斷訊息及無障礙操作說明保留正常標點。每個概念使用一種通行譯法,不只為部分術語附加英文括注。API 識別字、檔名與實際設定項目的名稱保持準確;括號可用於必要解釋,不作為例行的雙語標示。 + +判斷一句話是否需要保留,應看它是否說明目前操作、設計選擇、可觀察結果或正確使用的條件。刪去未使用功能的羅列、籠統的環境提醒與重複前提。標題及跨樣式的短語也須整體翻譯,不照搬英文語序。首頁標題的 `{accent}` 與 `{lineBreak}` 可依中文調整位置,樣式和換行不能決定語序。正文刪改由維護者先統一更新英文、共用繫結與各語言鍵集合,再同步譯文。 + ## 文字與預留位置 使用自然、簡潔的臺灣繁體中文,以完整句子或段落為單位翻譯,保留前提、否定、單位、操作順序及生命週期限制。不要逐字拼接譯文,也不要加入原文沒有的技術保證、平台需求、套件版本或版本說明。產品名稱、套件名稱、檔名、C#/Slang 識別項及大小寫保持原樣。 @@ -49,7 +59,7 @@ docfx serve documents/_site --hostname 127.0.0.1 --port 8080 本語言已註冊,完整字典建置成功後即可使用,無須修改設定。缺鍵、多餘鍵、空值、非字串值或預留位置名稱不符都會使建置失敗。建置不會判斷譯文是否準確或是否仍留有未翻譯的英文,必須人工通讀。 -各語言共用頁面路徑,以 `?lang=zh-TW` 選擇語言,切換時保留路徑與錨點。未明確指定語言時,依序採用已儲存的手動選擇、瀏覽器語言偏好、英文。此譯本尚未發布,或字典載入/頁面資源驗證失敗時,頁面回復為英文,而非逐句混用語言。語言清單依語言代碼排序。 +各語言共用頁面路徑,以 `?lang=zh-TW` 選擇語言,切換時保留路徑與錨點。未明確指定語言時,依序採用已儲存的手動選擇、瀏覽器語言偏好、英文。若此譯本尚未發布,或字典載入/頁面資源驗證失敗時,頁面回復為英文,而非逐句混用語言。語言清單依語言代碼排序。 交付前核對鍵與預留位置,並在桌面及 320 像素寬度檢查首頁、Learn 入口、三角形教學、概念頁、範例頁與 API 介面。依初學者的順序通讀教學,檢查術語、按鈕、搜尋、程式碼複製、API 跳轉,以及切換語言後的目前章節位置。識別項、宣告與程式碼仍使用共用原文;僅翻譯字典提供的介面與正文。測試字典及暫存檢查檔案放在儲存庫外,不提交暫代譯文。 @@ -59,7 +69,7 @@ docfx serve documents/_site --hostname 127.0.0.1 --port 8080 | --- | --- | | API / GPU / RHI | 保留縮寫,首次依原文說明 | | barrier | 屏障 | -| bindless | 無綁定(bindless) | +| bindless | 無繫結 | | buffer | 緩衝區;`Buffer` 不變 | | color attachment | 色彩附件 | | command buffer | 命令緩衝區 | @@ -73,7 +83,7 @@ docfx serve documents/_site --hostname 127.0.0.1 --port 8080 | pipeline | 管線;依情境區分圖形或計算管線 | | rasterization | 光柵化 | | readback | 從 GPU 回讀資料;下載檔案另用「下載」 | -| render pass | 渲染通道(render pass) | +| render pass | 渲染通道 | | render target | 渲染目標 | | resource | 資源 | | resource ownership / lifetime | 資源所有權/生命週期 | @@ -89,3 +99,5 @@ docfx serve documents/_site --hostname 127.0.0.1 --port 8080 | vertex / fragment | 頂點/片元 | | view | 資源檢視;與 UI 檢視區分 | | viewport / scissor | 視口/裁剪區域 | + +列與行的用法依臺灣慣例:row 譯為「列」,column 譯為「行」。row-major 為「列優先」,row stride 為「列跨距」。記憶體配置與資料佈局須依語境區分。 diff --git a/documents/templates/conceptual.extension.js b/documents/templates/conceptual.extension.js index f5a0b30c..ca72eb09 100644 --- a/documents/templates/conceptual.extension.js +++ b/documents/templates/conceptual.extension.js @@ -1,8 +1,10 @@ const resources = require('./resources.common.js'); exports.postTransform = function (model) { const strings = resources.prepare(model); + const templates = []; model._isLanding = model._layout === 'landing'; - model.rawTitle = resources.bind(model.rawTitle || '', strings); - model.conceptual = resources.bind(model.conceptual, strings); + model.rawTitle = resources.bind(model.rawTitle || '', strings, templates); + model.conceptual = resources.bind(model.conceptual, strings, templates); + model._resourceTemplates = templates.join(''); return model; }; diff --git a/documents/templates/layout/_master.tmpl b/documents/templates/layout/_master.tmpl index ded36419..37277f7c 100644 --- a/documents/templates/layout/_master.tmpl +++ b/documents/templates/layout/_master.tmpl @@ -62,6 +62,9 @@ {{/_disableAffix}} + {{! Keep translation slot templates outside the article indexed by DocFX.}} + {{{_resourceTemplates}}} + {{>partials/site.member-finder}} {{>partials/site.search}} diff --git a/documents/templates/public/resources.js b/documents/templates/public/resources.js index cbad4724..64cbab4e 100644 --- a/documents/templates/public/resources.js +++ b/documents/templates/public/resources.js @@ -5,6 +5,7 @@ let strings = resourceState.strings; export const getStrings = () => strings; const has = (dictionary, key) => Object.prototype.hasOwnProperty.call(dictionary, key); const format = globalThis.zenithResourceFormat; +const slotTemplate = element => element.dataset.resourceSlots ? document.getElementById(element.dataset.resourceSlots) : null; // Validate before changing the DOM: an old or incomplete download must not mix languages. export function setStrings(value) { @@ -22,10 +23,10 @@ export function setStrings(value) { }; for (const [key, slots] of Object.entries(resourceState.placeholders)) requireKey(key, slots); for (const element of document.querySelectorAll('[data-resource]')) { - const slots = element.querySelector(':scope > template[data-resource-slots]')?.content.children || []; + const slots = slotTemplate(element)?.content.children || []; requireKey(element.dataset.resource, [...slots].map(slot => slot.dataset.slot)); } - for (const attribute of ['label', 'title', 'placeholder']) { + for (const attribute of ['label', 'title', 'placeholder', 'alt']) { for (const element of document.querySelectorAll(`[data-resource-${attribute}]`)) requireKey(element.getAttribute(`data-resource-${attribute}`), []); } for (const meta of document.querySelectorAll('meta[name="resource:title"], meta[name="resource:description"]')) requireKey(meta.content, []); @@ -40,7 +41,7 @@ export function t(key, values = {}) { function bind(element) { const key = element.dataset.resource; if (!has(strings, key)) return; - const template = element.querySelector(':scope > template[data-resource-slots]'); + const template = slotTemplate(element); const slots = new Map(); for (const slot of template?.content.children || []) { const content = document.createDocumentFragment(); @@ -59,7 +60,6 @@ function bind(element) { } } element.replaceChildren(content); - if (template) element.append(template); } export function applyResources(code) { @@ -67,7 +67,7 @@ export function applyResources(code) { for (const element of document.querySelectorAll('[data-resource]')) { if (element.isConnected) bind(element); } - for (const [attribute, target] of [['label', 'aria-label'], ['title', 'title'], ['placeholder', 'placeholder']]) { + for (const [attribute, target] of [['label', 'aria-label'], ['title', 'title'], ['placeholder', 'placeholder'], ['alt', 'alt']]) { for (const element of document.querySelectorAll(`[data-resource-${attribute}]`)) { const key = element.getAttribute(`data-resource-${attribute}`); if (has(strings, key)) element.setAttribute(target, t(key)); diff --git a/documents/templates/resources.common.js b/documents/templates/resources.common.js index 3bdd9308..ef650a07 100644 --- a/documents/templates/resources.common.js +++ b/documents/templates/resources.common.js @@ -73,7 +73,7 @@ exports.prepare = function (model) { }; // Only the two authored binding tags are parsed. All other HTML is opaque shared markup. -exports.bind = function (html, dictionary) { +exports.bind = function (html, dictionary, templates) { const root = { children: [] }; const stack = [root]; let offset = 0; @@ -108,8 +108,13 @@ exports.bind = function (html, dictionary) { throw new Error(`Binding slots differ: ${node.name}`); } const content = format.parts(value).map(part => part.text !== undefined ? escape(part.text) : slots[part.slot]).join(''); - const template = Object.keys(slots).length ? `` : ''; - return `${content}${template}`; + let reference = ''; + if (Object.keys(slots).length) { + const id = `resource-slots-${templates.length}`; + templates.push(``); + reference = ` data-resource-slots="${id}"`; + } + return `${content}`; }; - return renderChildren(root).replace(/(aria-label|title|placeholder)="@([^"]+)"/g, (_, attribute, key) => `${attribute}="${escape(exports.get(dictionary, key))}"`); + return renderChildren(root).replace(/(aria-label|title|placeholder|alt)="@([^"]+)"/g, (_, attribute, key) => `${attribute}="${escape(exports.get(dictionary, key))}"`); }; From 347c86f805fe6b31fe829c520a08c0284cf6ebe0 Mon Sep 17 00:00:00 2001 From: qian-o <1324771795@qq.com> Date: Mon, 21 Sep 2026 17:50:45 +0800 Subject: [PATCH 20/35] Add UTF-8 BOM to source files; update toc.yml structure Added a UTF-8 BOM to the start of various source files (JavaScript, CSS, HTML, YAML, Markdown, JSON, etc.) to ensure proper encoding and compatibility for multilingual content. No functional changes were made. Also expanded the first entry in toc.yml to include href and items, making the table of contents structure explicit. --- README.md | 2 +- documents/api/index.md | 2 +- documents/authoring.md | 2 +- documents/docfx.json | 2 +- documents/index.md | 2 +- documents/learn/concepts/execution-model.md | 2 +- documents/learn/concepts/platform-integration.md | 2 +- documents/learn/concepts/resource-management.md | 2 +- documents/learn/concepts/shader-data-and-binding.md | 2 +- documents/learn/concepts/synchronization.md | 2 +- documents/learn/first-triangle.md | 2 +- documents/learn/index.md | 2 +- documents/learn/samples.md | 2 +- documents/locales/de-DE/strings.yml | 2 +- documents/locales/de-DE/translation.md | 2 +- documents/locales/en-US/strings.yml | 2 +- documents/locales/es-ES/strings.yml | 2 +- documents/locales/es-ES/translation.md | 2 +- documents/locales/fr-FR/strings.yml | 2 +- documents/locales/fr-FR/translation.md | 2 +- documents/locales/ja-JP/strings.yml | 2 +- documents/locales/ja-JP/translation.md | 2 +- documents/locales/ko-KR/strings.yml | 2 +- documents/locales/ko-KR/translation.md | 2 +- documents/locales/pt-BR/strings.yml | 2 +- documents/locales/pt-BR/translation.md | 2 +- documents/locales/ru-RU/strings.yml | 2 +- documents/locales/ru-RU/translation.md | 2 +- documents/locales/zh-CN/strings.yml | 2 +- documents/locales/zh-CN/translation.md | 2 +- documents/locales/zh-TW/strings.yml | 2 +- documents/locales/zh-TW/translation.md | 2 +- documents/templates/ManagedReference.extension.js | 2 +- documents/templates/ManagedReference.html.primary.tmpl | 2 +- documents/templates/Resources.json.primary.js | 2 +- documents/templates/Resources.json.primary.tmpl | 2 +- documents/templates/conceptual.extension.js | 2 +- documents/templates/conceptual.html.primary.tmpl | 2 +- documents/templates/layout/_master.tmpl | 2 +- documents/templates/partials/api.code.tmpl.partial | 2 +- documents/templates/partials/api.enum.tmpl.partial | 2 +- documents/templates/partials/api.header.tmpl.partial | 2 +- documents/templates/partials/api.member-launcher.tmpl.partial | 2 +- documents/templates/partials/api.namespace.tmpl.partial | 2 +- documents/templates/partials/api.relationships.tmpl.partial | 2 +- documents/templates/partials/api.seealso.tmpl.partial | 2 +- documents/templates/partials/api.signature.tmpl.partial | 2 +- documents/templates/partials/api.source.tmpl.partial | 2 +- documents/templates/partials/api.type.tmpl.partial | 2 +- documents/templates/partials/site.footer.tmpl.partial | 2 +- documents/templates/partials/site.header.tmpl.partial | 2 +- documents/templates/partials/site.language.tmpl.partial | 2 +- documents/templates/partials/site.member-finder.tmpl.partial | 2 +- documents/templates/partials/site.search.tmpl.partial | 2 +- documents/templates/partials/site.sidebar.tmpl.partial | 2 +- documents/templates/public/api.css | 2 +- documents/templates/public/api.js | 2 +- documents/templates/public/code-links.js | 2 +- documents/templates/public/content.css | 2 +- documents/templates/public/dialog.js | 2 +- documents/templates/public/home.css | 2 +- documents/templates/public/home.js | 2 +- documents/templates/public/languages.js | 2 +- documents/templates/public/layout.css | 2 +- documents/templates/public/main.css | 2 +- documents/templates/public/main.js | 2 +- documents/templates/public/member-finder.js | 2 +- documents/templates/public/motion.css | 2 +- documents/templates/public/motion.js | 2 +- documents/templates/public/navigation.js | 2 +- documents/templates/public/outline.js | 2 +- documents/templates/public/resource-format.js | 2 +- documents/templates/public/resources.js | 2 +- documents/templates/public/search.css | 2 +- documents/templates/public/search.js | 2 +- documents/templates/public/signature-links.js | 2 +- documents/templates/public/site.js | 2 +- documents/templates/public/syntax.js | 2 +- documents/templates/public/theme.css | 2 +- documents/templates/resources.common.js | 2 +- documents/templates/schemas/Resources.schema.json | 2 +- documents/templates/toc.extension.js | 2 +- documents/toc.yml | 2 +- 83 files changed, 83 insertions(+), 83 deletions(-) diff --git a/README.md b/README.md index 5ce58b74..59b05e5e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -

    +

    Zenith.NET icon

    diff --git a/documents/api/index.md b/documents/api/index.md index 510434a9..6e027cbc 100644 --- a/documents/api/index.md +++ b/documents/api/index.md @@ -1,4 +1,4 @@ ---- +--- title: '@reference.title' description: '@reference.meta.description' --- diff --git a/documents/authoring.md b/documents/authoring.md index 175e3725..a7ca8447 100644 --- a/documents/authoring.md +++ b/documents/authoring.md @@ -1,4 +1,4 @@ -# Documentation authoring and maintenance +# Documentation authoring and maintenance This is the handoff reference for filling in the documentation. It is excluded from the published site and its navigation. diff --git a/documents/docfx.json b/documents/docfx.json index 1d338be8..8c2389be 100644 --- a/documents/docfx.json +++ b/documents/docfx.json @@ -1,4 +1,4 @@ -{ +{ "$schema": "https://raw.githubusercontent.com/dotnet/docfx/main/schemas/docfx.schema.json", "metadata": [{ "src": [{"src": "../sources", "files": "**/*.csproj", "exclude": "Experiments/**"}], diff --git a/documents/index.md b/documents/index.md index f96697d9..255b90e6 100644 --- a/documents/index.md +++ b/documents/index.md @@ -1,4 +1,4 @@ ---- +--- title: '@home.title' description: '@home.meta.description' _layout: landing diff --git a/documents/learn/concepts/execution-model.md b/documents/learn/concepts/execution-model.md index 45c04078..0e188ccf 100644 --- a/documents/learn/concepts/execution-model.md +++ b/documents/learn/concepts/execution-model.md @@ -1,4 +1,4 @@ ---- +--- title: '@concepts.execution.title' --- diff --git a/documents/learn/concepts/platform-integration.md b/documents/learn/concepts/platform-integration.md index 7008c2a8..680a5a7a 100644 --- a/documents/learn/concepts/platform-integration.md +++ b/documents/learn/concepts/platform-integration.md @@ -1,4 +1,4 @@ ---- +--- title: '@concepts.platforms.title' --- diff --git a/documents/learn/concepts/resource-management.md b/documents/learn/concepts/resource-management.md index 22042388..bc8d5f0b 100644 --- a/documents/learn/concepts/resource-management.md +++ b/documents/learn/concepts/resource-management.md @@ -1,4 +1,4 @@ ---- +--- title: '@concepts.resources.title' --- diff --git a/documents/learn/concepts/shader-data-and-binding.md b/documents/learn/concepts/shader-data-and-binding.md index 777b3169..81de72b2 100644 --- a/documents/learn/concepts/shader-data-and-binding.md +++ b/documents/learn/concepts/shader-data-and-binding.md @@ -1,4 +1,4 @@ ---- +--- title: '@concepts.shaders.title' --- diff --git a/documents/learn/concepts/synchronization.md b/documents/learn/concepts/synchronization.md index 1d845064..14e7b2e0 100644 --- a/documents/learn/concepts/synchronization.md +++ b/documents/learn/concepts/synchronization.md @@ -1,4 +1,4 @@ ---- +--- title: '@concepts.synchronization.title' --- diff --git a/documents/learn/first-triangle.md b/documents/learn/first-triangle.md index 40324dfd..dad3102e 100644 --- a/documents/learn/first-triangle.md +++ b/documents/learn/first-triangle.md @@ -1,4 +1,4 @@ ---- +--- title: '@tutorial.title' --- diff --git a/documents/learn/index.md b/documents/learn/index.md index a57fe349..c6e521bd 100644 --- a/documents/learn/index.md +++ b/documents/learn/index.md @@ -1,4 +1,4 @@ ---- +--- title: '@learning.title' description: '@learning.meta.description' _pageKind: hub diff --git a/documents/learn/samples.md b/documents/learn/samples.md index f7135203..2ddcc6d7 100644 --- a/documents/learn/samples.md +++ b/documents/learn/samples.md @@ -1,4 +1,4 @@ ---- +--- title: '@samples.title' --- diff --git a/documents/locales/de-DE/strings.yml b/documents/locales/de-DE/strings.yml index 81e97805..fd139da6 100644 --- a/documents/locales/de-DE/strings.yml +++ b/documents/locales/de-DE/strings.yml @@ -1,4 +1,4 @@ -### YamlMime:Resources +### YamlMime:Resources concepts.execution.context.description: "Ein {graphicsContext} verbindet die Anwendung über ein bestimmtes Backend mit einem GPU-Gerät und stellt dessen Grafik-, Compute- und Transferwarteschlangen bereit. Gemeinsam verwendete Ressourcen müssen demselben Kontext angehören: Puffer, Texturen, Shader, Pipelines und ihre Handles lassen sich nicht über Kontextgrenzen hinweg binden." concepts.execution.context.details: "{capabilities} liefert den Gerätenamen und die unterstützten Funktionen. Prüfen Sie mit {rayTracingSupported} und {meshShadingSupported}, ob die jeweilige Funktion verfügbar ist, bevor Sie ihre Ressourcen erstellen. Die Beispiele für {link} und {detail} zeigen diese Prüfung bei der Initialisierung." concepts.execution.context.details.detail: Mesh-Shading diff --git a/documents/locales/de-DE/translation.md b/documents/locales/de-DE/translation.md index 243dac9d..1dc3769d 100644 --- a/documents/locales/de-DE/translation.md +++ b/documents/locales/de-DE/translation.md @@ -1,4 +1,4 @@ -# Übersetzungsrichtlinien für Deutsch +# Übersetzungsrichtlinien für Deutsch ## Ressourcen und Aufbau diff --git a/documents/locales/en-US/strings.yml b/documents/locales/en-US/strings.yml index 5ca2bb34..2145670c 100644 --- a/documents/locales/en-US/strings.yml +++ b/documents/locales/en-US/strings.yml @@ -1,4 +1,4 @@ -### YamlMime:Resources +### YamlMime:Resources concepts.execution.context.description: A {graphicsContext} connects the application to a GPU device through a particular backend and provides its graphics, compute, and transfer queues. Resources used together must belong to the same context; buffers, textures, shaders, pipelines, and their handles cannot be bound across contexts. diff --git a/documents/locales/es-ES/strings.yml b/documents/locales/es-ES/strings.yml index e0bd4966..d5518926 100644 --- a/documents/locales/es-ES/strings.yml +++ b/documents/locales/es-ES/strings.yml @@ -1,4 +1,4 @@ -### YamlMime:Resources +### YamlMime:Resources concepts.execution.context.description: "Un {graphicsContext} conecta la aplicación con un dispositivo GPU mediante un backend concreto y proporciona sus colas gráfica, de cálculo y de transferencia. Los recursos que se utilizan juntos deben pertenecer al mismo contexto; no se pueden enlazar búferes, texturas, sombreadores, canalizaciones ni sus identificadores entre contextos distintos." concepts.execution.context.details: "{capabilities} indica el nombre del dispositivo y las funciones que admite. Compruebe {rayTracingSupported} y {meshShadingSupported} antes de crear los recursos que necesitan esas funciones. Los ejemplos de {link} y {detail} realizan estas comprobaciones durante la inicialización." concepts.execution.context.details.detail: "sombreado de mallas" diff --git a/documents/locales/es-ES/translation.md b/documents/locales/es-ES/translation.md index 92822bd5..e766d010 100644 --- a/documents/locales/es-ES/translation.md +++ b/documents/locales/es-ES/translation.md @@ -1,4 +1,4 @@ -# Criterios de traducción al español +# Criterios de traducción al español ## Recursos y estructura diff --git a/documents/locales/fr-FR/strings.yml b/documents/locales/fr-FR/strings.yml index d05da25f..43e42557 100644 --- a/documents/locales/fr-FR/strings.yml +++ b/documents/locales/fr-FR/strings.yml @@ -1,4 +1,4 @@ -### YamlMime:Resources +### YamlMime:Resources concepts.execution.context.description: "Un {graphicsContext} relie l’application à un périphérique GPU par un backend donné et fournit ses files graphiques, de calcul et de transfert. Les ressources utilisées ensemble doivent appartenir au même contexte : tampons, textures, shaders, pipelines et handles ne peuvent pas être liés d’un contexte à un autre." concepts.execution.context.details: "{capabilities} indique le nom du périphérique et les fonctions prises en charge. Vérifiez {rayTracingSupported} et {meshShadingSupported} avant de créer les ressources nécessaires à ces fonctions. Les exemples de {link} et de {detail} effectuent ces vérifications à l’initialisation." concepts.execution.context.details.detail: mesh shading diff --git a/documents/locales/fr-FR/translation.md b/documents/locales/fr-FR/translation.md index 694b098b..7321670a 100644 --- a/documents/locales/fr-FR/translation.md +++ b/documents/locales/fr-FR/translation.md @@ -1,4 +1,4 @@ -# Consignes de traduction en français +# Consignes de traduction en français ## Ressources et structure diff --git a/documents/locales/ja-JP/strings.yml b/documents/locales/ja-JP/strings.yml index 2bb6213d..33d075d0 100644 --- a/documents/locales/ja-JP/strings.yml +++ b/documents/locales/ja-JP/strings.yml @@ -1,4 +1,4 @@ -### YamlMime:Resources +### YamlMime:Resources concepts.execution.context.description: "{graphicsContext} は特定のバックエンドを介してアプリケーションを GPU デバイスに接続し、描画、計算、転送のキューを提供します。一緒に使うリソースは同じコンテキストに属している必要があります。バッファー、テクスチャ、シェーダー、パイプラインとそのハンドルを、コンテキストをまたいでバインドすることはできません。" concepts.execution.context.details: "{capabilities} はデバイス名と対応機能を提供します。レイトレーシングやメッシュシェーディング用のリソースを作成する前に、{rayTracingSupported} と {meshShadingSupported} で対応を確認します。{link}と{detail}のサンプルでは、初期化時にこの確認を行っています。" concepts.execution.context.details.detail: "メッシュシェーディング" diff --git a/documents/locales/ja-JP/translation.md b/documents/locales/ja-JP/translation.md index 4cd5a0a4..70baf9a1 100644 --- a/documents/locales/ja-JP/translation.md +++ b/documents/locales/ja-JP/translation.md @@ -1,4 +1,4 @@ -# 日本語翻訳ガイド +# 日本語翻訳ガイド ## リソースと構成 diff --git a/documents/locales/ko-KR/strings.yml b/documents/locales/ko-KR/strings.yml index 552de82c..8777e44d 100644 --- a/documents/locales/ko-KR/strings.yml +++ b/documents/locales/ko-KR/strings.yml @@ -1,4 +1,4 @@ -### YamlMime:Resources +### YamlMime:Resources concepts.execution.context.description: "{graphicsContext}는 특정 백엔드를 통해 애플리케이션을 GPU 장치에 연결하고 그래픽스, 컴퓨트, 전송 큐를 제공합니다. 함께 사용하는 리소스는 같은 컨텍스트에 속해야 합니다. 버퍼, 텍스처, 셰이더, 파이프라인과 그 핸들은 서로 다른 컨텍스트 사이에서 바인딩할 수 없습니다." concepts.execution.context.details: "{capabilities}는 장치 이름과 지원 기능을 알려 줍니다. 해당 기능의 리소스를 만들기 전에 {rayTracingSupported}와 {meshShadingSupported}로 지원 여부를 확인합니다. {link} 및 {detail} 예제는 초기화 과정에서 이 검사를 수행합니다." concepts.execution.context.details.detail: 메시 셰이딩 diff --git a/documents/locales/ko-KR/translation.md b/documents/locales/ko-KR/translation.md index 9bdb1a42..4c550407 100644 --- a/documents/locales/ko-KR/translation.md +++ b/documents/locales/ko-KR/translation.md @@ -1,4 +1,4 @@ -# 한국어 번역 지침 +# 한국어 번역 지침 ## 리소스와 구조 diff --git a/documents/locales/pt-BR/strings.yml b/documents/locales/pt-BR/strings.yml index 93ac29ae..517678e5 100644 --- a/documents/locales/pt-BR/strings.yml +++ b/documents/locales/pt-BR/strings.yml @@ -1,4 +1,4 @@ -### YamlMime:Resources +### YamlMime:Resources concepts.execution.context.description: "Um {graphicsContext} conecta a aplicação a um dispositivo GPU por meio de um backend específico e fornece suas filas gráfica, de computação e de transferência. Recursos usados em conjunto devem pertencer ao mesmo contexto; buffers, texturas, shaders, pipelines e seus identificadores não podem ser vinculados entre contextos diferentes." concepts.execution.context.details: "{capabilities} informa o nome do dispositivo e as funcionalidades disponíveis. Consulte {rayTracingSupported} e {meshShadingSupported} antes de criar os recursos necessários a essas operações. Os exemplos de {link} e {detail} fazem essas verificações durante a inicialização." concepts.execution.context.details.detail: "sombreamento de malha" diff --git a/documents/locales/pt-BR/translation.md b/documents/locales/pt-BR/translation.md index 829bf443..71505a78 100644 --- a/documents/locales/pt-BR/translation.md +++ b/documents/locales/pt-BR/translation.md @@ -1,4 +1,4 @@ -# Diretrizes de tradução para português brasileiro +# Diretrizes de tradução para português brasileiro ## Recursos e estrutura diff --git a/documents/locales/ru-RU/strings.yml b/documents/locales/ru-RU/strings.yml index e3848961..bc4708eb 100644 --- a/documents/locales/ru-RU/strings.yml +++ b/documents/locales/ru-RU/strings.yml @@ -1,4 +1,4 @@ -### YamlMime:Resources +### YamlMime:Resources concepts.execution.context.description: "{graphicsContext} связывает приложение с устройством GPU через определённый бэкенд и предоставляет его графическую, вычислительную и передающую очереди. Совместно используемые ресурсы должны принадлежать одному контексту: буферы, текстуры, шейдеры, конвейеры и их дескрипторы нельзя привязывать между разными контекстами." concepts.execution.context.details: "{capabilities} сообщает имя устройства и поддерживаемые возможности. Перед созданием ресурсов для трассировки лучей или меш-шейдинга проверяйте соответственно {rayTracingSupported} и {meshShadingSupported}. Такие проверки при инициализации показаны в примерах {link} и {detail}." concepts.execution.context.details.detail: "меш-шейдинга" diff --git a/documents/locales/ru-RU/translation.md b/documents/locales/ru-RU/translation.md index e8afe164..dae0b27a 100644 --- a/documents/locales/ru-RU/translation.md +++ b/documents/locales/ru-RU/translation.md @@ -1,4 +1,4 @@ -# Правила перевода на русский язык +# Правила перевода на русский язык ## Ресурсы и структура diff --git a/documents/locales/zh-CN/strings.yml b/documents/locales/zh-CN/strings.yml index 562c2cba..4afc8b5e 100644 --- a/documents/locales/zh-CN/strings.yml +++ b/documents/locales/zh-CN/strings.yml @@ -1,4 +1,4 @@ -### YamlMime:Resources +### YamlMime:Resources concepts.execution.context.description: "{graphicsContext} 通过特定后端连接应用程序与 GPU 设备,并提供图形、计算和传输队列。配合使用的资源必须属于同一上下文;缓冲区、纹理、着色器、管线及其句柄不能跨上下文绑定。" concepts.execution.context.details: "{capabilities} 提供设备名称与支持的功能。创建光线追踪或网格着色所需的资源前,分别通过 {rayTracingSupported} 和 {meshShadingSupported} 检查支持情况。{link}与{detail}示例展示了初始化时的检查方式。" concepts.execution.context.details.detail: "网格着色" diff --git a/documents/locales/zh-CN/translation.md b/documents/locales/zh-CN/translation.md index 9fa07d83..a79a4251 100644 --- a/documents/locales/zh-CN/translation.md +++ b/documents/locales/zh-CN/translation.md @@ -1,4 +1,4 @@ -# 简体中文翻译约定 +# 简体中文翻译约定 ## 资源与结构 diff --git a/documents/locales/zh-TW/strings.yml b/documents/locales/zh-TW/strings.yml index 95b8b5f8..7c43909c 100644 --- a/documents/locales/zh-TW/strings.yml +++ b/documents/locales/zh-TW/strings.yml @@ -1,4 +1,4 @@ -### YamlMime:Resources +### YamlMime:Resources concepts.execution.context.description: "{graphicsContext} 透過特定後端連接應用程式與 GPU 裝置,並提供圖形、計算與傳輸佇列。一起使用的資源必須屬於同一上下文;緩衝區、紋理、著色器、管線及其控制代碼不能跨上下文繫結。" concepts.execution.context.details: "{capabilities} 提供裝置名稱與支援的功能。建立光線追蹤或網格著色所需的資源前,分別透過 {rayTracingSupported} 與 {meshShadingSupported} 確認支援情況。{link}與{detail}範例展示了初始化時的檢查方式。" concepts.execution.context.details.detail: "網格著色" diff --git a/documents/locales/zh-TW/translation.md b/documents/locales/zh-TW/translation.md index 328a0ccc..e0f22b6f 100644 --- a/documents/locales/zh-TW/translation.md +++ b/documents/locales/zh-TW/translation.md @@ -1,4 +1,4 @@ -# 繁體中文翻譯約定 +# 繁體中文翻譯約定 ## 資源與結構 diff --git a/documents/templates/ManagedReference.extension.js b/documents/templates/ManagedReference.extension.js index 5a4e5b21..ba8aea37 100644 --- a/documents/templates/ManagedReference.extension.js +++ b/documents/templates/ManagedReference.extension.js @@ -1,4 +1,4 @@ -const resources = require('./resources.common.js'); +const resources = require('./resources.common.js'); const relationshipKeys = ['inheritance', 'implements', 'derivedClasses', 'inheritedMembers', 'extensionMethods']; function prepareSignature(syntax, strings) { diff --git a/documents/templates/ManagedReference.html.primary.tmpl b/documents/templates/ManagedReference.html.primary.tmpl index 0139a5ff..ca828994 100644 --- a/documents/templates/ManagedReference.html.primary.tmpl +++ b/documents/templates/ManagedReference.html.primary.tmpl @@ -1,4 +1,4 @@ -{{!master(layout/_master.tmpl)}} +{{!master(layout/_master.tmpl)}}
    {{>partials/api.header}} {{#isNamespace}}{{>partials/api.namespace}}{{/isNamespace}} diff --git a/documents/templates/Resources.json.primary.js b/documents/templates/Resources.json.primary.js index d2c6b033..0490adbf 100644 --- a/documents/templates/Resources.json.primary.js +++ b/documents/templates/Resources.json.primary.js @@ -1,3 +1,3 @@ -const resources = require('./resources.common.js'); +const resources = require('./resources.common.js'); exports.getOptions = () => ({ isShared: true }); exports.transform = model => ({ content: JSON.stringify(resources.validate(model)) }); diff --git a/documents/templates/Resources.json.primary.tmpl b/documents/templates/Resources.json.primary.tmpl index af14dc2f..9e1fd712 100644 --- a/documents/templates/Resources.json.primary.tmpl +++ b/documents/templates/Resources.json.primary.tmpl @@ -1 +1 @@ -{{{content}}} +{{{content}}} diff --git a/documents/templates/conceptual.extension.js b/documents/templates/conceptual.extension.js index ca72eb09..83ebff62 100644 --- a/documents/templates/conceptual.extension.js +++ b/documents/templates/conceptual.extension.js @@ -1,4 +1,4 @@ -const resources = require('./resources.common.js'); +const resources = require('./resources.common.js'); exports.postTransform = function (model) { const strings = resources.prepare(model); const templates = []; diff --git a/documents/templates/conceptual.html.primary.tmpl b/documents/templates/conceptual.html.primary.tmpl index 01424efc..bf8ad30a 100644 --- a/documents/templates/conceptual.html.primary.tmpl +++ b/documents/templates/conceptual.html.primary.tmpl @@ -1,3 +1,3 @@ -{{!master(layout/_master.tmpl)}} +{{!master(layout/_master.tmpl)}} {{{rawTitle}}} {{{conceptual}}} diff --git a/documents/templates/layout/_master.tmpl b/documents/templates/layout/_master.tmpl index 37277f7c..7baad27e 100644 --- a/documents/templates/layout/_master.tmpl +++ b/documents/templates/layout/_master.tmpl @@ -1,4 +1,4 @@ -{{!Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license.}} +{{!Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license.}} {{!include(/^public/.*/)}} diff --git a/documents/templates/partials/api.code.tmpl.partial b/documents/templates/partials/api.code.tmpl.partial index 694a439f..166bcbea 100644 --- a/documents/templates/partials/api.code.tmpl.partial +++ b/documents/templates/partials/api.code.tmpl.partial @@ -1,4 +1,4 @@ -{{#syntax.content.0.value}} +{{#syntax.content.0.value}}
    {{syntax.content.0.value}}
    diff --git a/documents/templates/partials/site.header.tmpl.partial b/documents/templates/partials/site.header.tmpl.partial index ad774144..75ed6aef 100644 --- a/documents/templates/partials/site.header.tmpl.partial +++ b/documents/templates/partials/site.header.tmpl.partial @@ -1,5 +1,6 @@ 
    - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + +
    GraphicsQueue
    ComputeQueue
    TransferQueue
    + + + +
    + GraphicsQueue + + + +
    + ComputeQueue + + + +
    + TransferQueue + + + +
    -

    -

    -

    -

    queue.CommandBuffer()CommandBufferSubmit()TimelineValue

    -

    commandBuffer

    +

    + +

    +

    + + + +

    +

    + +

    +

    + + queue.CommandBuffer() + CommandBuffer + Submit() + TimelineValue + +

    +

    + commandBuffer + +

    ```csharp commandBuffer.Submit().Wait(); ``` -

    Submit()Wait()

    -

    queue.CommandBuffer()

    -

    -

    -

    -

    -

    -

    +

    + + Submit() + Wait() + +

    +

    + + queue.CommandBuffer() + +

    +

    + +

    +

    + +

    +

    + +

    +

    + + + + +

    +

    + +

    +

    + +

    - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + +
    SwapChain.Drawable
    + + + +
    + + + +
    + + + +
    + SwapChain.Drawable + + + +
    + + + +
    -

    Dispose()

    -

    -

    +

    + + Dispose() + +

    +

    + +

    +

    + + + +

    diff --git a/documents/learn/concepts/platform-integration.md b/documents/learn/concepts/platform-integration.md index 680a5a7a..679d0eff 100644 --- a/documents/learn/concepts/platform-integration.md +++ b/documents/learn/concepts/platform-integration.md @@ -2,59 +2,164 @@ title: '@concepts.platforms.title' --- -

    -

    -

    -

    -

    SurfaceSwapChain

    -

    +

    + +

    +

    + +

    +

    + +

    +

    + +

    +

    + + + Surface + SwapChain + +

    +

    + +

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Win32HWND
    Wayland
    Xlib
    AndroidANativeWindow
    AppleCAMetalLayer
    + + + + + +
    + + Win32 + + HWND + + +
    + + Wayland + + + + + +
    + + Xlib + + + + + +
    + + Android + + ANativeWindow + + +
    + + Apple + + CAMetalLayer + + +
    -

    App.csSurface.Wayland

    -

    -

    -

    SwapChain.Drawable

    -

    SwapChain.ResizeSwapChain.Refresh

    -

    -

    -

    -

    IZenithViewGraphicsContextUpdateRequestedRenderRequestedRenderEventArgs

    -

    ColorAttachment

    -

    IZenithViewviewusing Zenith.NET;

    +

    + + App.cs + Surface.Wayland + +

    +

    + +

    +

    + +

    +

    + + SwapChain.Drawable + +

    +

    + + SwapChain.Resize + SwapChain.Refresh + +

    +

    + + + +

    +

    + +

    +

    + +

    +

    + + IZenithView + GraphicsContext + UpdateRequested + RenderRequested + RenderEventArgs + +

    +

    + + ColorAttachment + +

    +

    + + IZenithView + view + using Zenith.NET; + +

    ```csharp view.RenderRequested += (_, args) => @@ -65,51 +170,144 @@ view.RenderRequested += (_, args) => }; ``` -

    ColorAttachment

    -

    Undefined

    -

    ZenithViewHelper.DrawableFormat

    -

    Desc.WidthDesc.HeightDesc.FormatDesc.SampleCount

    -

    -

    +

    + + ColorAttachment + +

    +

    + + Undefined + +

    +

    + + ZenithViewHelper.DrawableFormat + +

    +

    + + Desc.Width + Desc.Height + Desc.Format + Desc.SampleCount + +

    +

    + +

    +

    + +

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    WriteableBitmapZenithView.csSurface.cs
    HWNDZenithView.cs
    D3DImageSurface.cs
    SwapChainPanelZenithView.WinUI.cs
    WriteableBitmapZenithView.Uno.cs
    + + + +
    + + + + WriteableBitmap + ZenithView.cs + Surface.cs + +
    + + + + HWND + ZenithView.cs + +
    + + + + D3DImage + Surface.cs + +
    + + + + SwapChainPanel + ZenithView.WinUI.cs + +
    + + + + WriteableBitmap + ZenithView.Uno.cs + +
    + + + + + +
    -

    RenderRequested

    -

    Zenith.NET.Views.Avalonia

    +

    + + RenderRequested + +

    +

    + + Zenith.NET.Views.Avalonia + +

    -

    UseZenithViewExtensions.cs

    -

    -

    GraphicsContext

    -

    -

    FrameScheduler.cs

    +

    + UseZenithView + Extensions.cs + +

    +

    + +

    +

    + + GraphicsContext + +

    +

    + +

    +

    + + FrameScheduler.cs + +

    diff --git a/documents/learn/concepts/resource-management.md b/documents/learn/concepts/resource-management.md index bc8d5f0b..be4afc4d 100644 --- a/documents/learn/concepts/resource-management.md +++ b/documents/learn/concepts/resource-management.md @@ -2,167 +2,404 @@ title: '@concepts.resources.title' --- -

    -

    -

    -

    BufferUsagesTextureUsagesBufferDesc.UsagesTextureDesc.Usages|

    -

    +

    + +

    +

    + +

    +

    + +

    +

    + + BufferUsages + TextureUsages + BufferDesc.Usages + TextureDesc.Usages + | + +

    +

    + +

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    None
    Vertex
    Index
    Indirect
    Constant
    StorageReadOnly
    StorageReadWrite
    TransferSrc
    TransferDst
    + + + +
    + None + + + +
    + Vertex + + + +
    + Index + + + +
    + Indirect + + + +
    + Constant + + + +
    + StorageReadOnly + + + +
    + StorageReadWrite + + + +
    + TransferSrc + + + +
    + TransferDst + + + +
    -

    +

    + +

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    None
    Sampled
    Storage
    ColorAttachment
    DepthStencilAttachment
    TransferSrc
    TransferDst
    + + + +
    + None + + + +
    + Sampled + + + +
    + Storage + + + +
    + ColorAttachment + + + +
    + + DepthStencilAttachment + + + +
    + TransferSrc + + + +
    + TransferDst + + + +
    -

    -

    -

    -

    -

    BufferDescResidency

    +

    + +

    +

    + + + +

    +

    + +

    +

    + +

    +

    + + BufferDesc + Residency + +

    - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + +
    GpuOnly
    CpuReadOnly
    CpuWriteOnly
    + + + + + +
    + GpuOnly + + + + + +
    + CpuReadOnly + + + + + +
    + CpuWriteOnly + + + + + +
    -

    CpuWriteOnly

    -

    TextureDesc

    -

    Map()Unmap()

    -

    -

    +

    + + CpuWriteOnly + +

    +

    + + TextureDesc + +

    +

    + + Map() + Unmap() + +

    +

    + +

    +

    + +

    - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + +
    Buffer.UploadCpuWriteOnly
    Buffer.DownloadCpuReadOnly
    Texture.UploadTexture.Download
    + + + +
    + + Buffer.Upload + + + + CpuWriteOnly + +
    + + Buffer.Download + + + + CpuReadOnly + +
    + + Texture.Upload + Texture.Download + + + +
    -

    -

    CommandBuffer.UploadCommandBuffer.Download

    +

    + +

    +

    + + CommandBuffer.Upload + CommandBuffer.Download + +

    -

    -

    -

    Heap

    -

    context.GetSizeAndAlignment

    -

    -

    -

    -

    -

    BufferViewTextureView

    -

    +

    + + + +

    +

    + +

    +

    + + Heap + +

    +

    + + context.GetSizeAndAlignment + +

    +

    + +

    +

    + +

    +

    + +

    +

    + +

    +

    + + BufferView + TextureView + +

    +

    + + + +

    diff --git a/documents/learn/concepts/shader-data-and-binding.md b/documents/learn/concepts/shader-data-and-binding.md index 81de72b2..d059bd98 100644 --- a/documents/learn/concepts/shader-data-and-binding.md +++ b/documents/learn/concepts/shader-data-and-binding.md @@ -2,11 +2,26 @@ title: '@concepts.shaders.title' --- -

    -

    -

    -

    ZenithCompilerShaderDescGraphicsApi

    -

    context

    +

    + +

    +

    + +

    +

    + +

    +

    + + ZenithCompiler + ShaderDesc + GraphicsApi + +

    +

    + context + +

    ```csharp string shaderPath = Path.Combine(AppContext.BaseDirectory, "Triangle.slang"); @@ -14,13 +29,41 @@ string shaderPath = Path.Combine(AppContext.BaseDirectory, "Triangle.slang"); Shader vertexShader = context.CreateShader(ZenithCompiler.CompileFromFile(context.GraphicsApi, shaderPath, "VSMain")); ``` -

    VSMain

    -

    -

    -

    InputLayoutFloat3Float4InputLayout.Add

    -

    InputLayoutfloat3

    -

    -

    System.Runtime.InteropServicesZenith.NET

    +

    + VSMain + + +

    +

    + +

    +

    + +

    +

    + + InputLayout + Float3 + Float4 + InputLayout.Add + +

    +

    + + InputLayout + float3 + +

    +

    + +

    +

    + + + System.Runtime.InteropServices + Zenith.NET + +

    ```csharp [StructLayout(LayoutKind.Explicit, Size = 256)] @@ -40,7 +83,11 @@ file struct Constants } ``` -

    ComputeShader.slang

    +

    + + ComputeShader.slang + +

    ```slang struct Constants @@ -57,14 +104,37 @@ struct Constants ConstantBuffer constants; ``` -

    -

    -

    Matrix4x4mul(vector, matrix)

    -

    -

    -

    -

    SetConstantBuffer

    -

    +

    + +

    +

    + +

    +

    + + + Matrix4x4 + + mul(vector, matrix) + +

    +

    + +

    +

    + +

    +

    + +

    +

    + + SetConstantBuffer + +

    +

    + +

    ```csharp commandBuffer.SetPipeline(computePipeline); @@ -72,46 +142,111 @@ commandBuffer.SetConstantBuffer(constantBuffer, 0); commandBuffer.Dispatch(groupCountX, groupCountY, 1); ``` -

    commandBuffercomputePipelineconstantBufferBufferUsages.Constant

    -

    InputinputTexture.SampledHandleOutputoutputTexture.StorageHandleDescriptorHandle

    +

    + commandBuffer + computePipeline + constantBuffer + BufferUsages.Constant + +

    +

    + Input + inputTexture.SampledHandle + Output + outputTexture.StorageHandle + DescriptorHandle + +

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    texture.SampledHandleDescriptorHandle<Texture2D>
    texture.StorageHandleDescriptorHandle<RWTexture2D<float4>>
    buffer.StorageReadOnlyHandleDescriptorHandle<StructuredBuffer<T>>T
    buffer.StorageReadWriteHandleDescriptorHandle<RWStructuredBuffer<T>>T
    sampler.HandleDescriptorHandle<SamplerState>
    + + + + + +
    texture.SampledHandle + DescriptorHandle<Texture2D> + + +
    texture.StorageHandle + DescriptorHandle<RWTexture2D<float4>> + + +
    buffer.StorageReadOnlyHandle + DescriptorHandle<StructuredBuffer<T>> + + + T + +
    buffer.StorageReadWriteHandle + DescriptorHandle<RWStructuredBuffer<T>> + + + T + +
    sampler.Handle + DescriptorHandle<SamplerState> + + +
    -

    ResourceHandle

    -

    -

    -

    Dispatch[numthreads(16, 16, 1)]

    -

    ShaderDesc.ThreadGroupSizeDispatchComputeShaderRenderer.cs

    +

    + + ResourceHandle + +

    +

    + + + +

    +

    + +

    +

    + + Dispatch + [numthreads(16, 16, 1)] + +

    +

    + + ShaderDesc.ThreadGroupSize + Dispatch + ComputeShaderRenderer.cs + + +

    diff --git a/documents/learn/concepts/synchronization.md b/documents/learn/concepts/synchronization.md index 14e7b2e0..01397cbc 100644 --- a/documents/learn/concepts/synchronization.md +++ b/documents/learn/concepts/synchronization.md @@ -2,67 +2,173 @@ title: '@concepts.synchronization.title' --- -

    -

    -

    -

    -

    +

    + +

    +

    + +

    +

    + +

    +

    + +

    +

    + +

    - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + +
    CommandBuffer.Barrier
    CommandBuffer.Transition
    TimelineValueSubmit
    Wait()
    + + + +
    + + + + CommandBuffer.Barrier + +
    + + + + CommandBuffer.Transition + +
    + + + + TimelineValue + Submit + +
    + + + + Wait() + +
    -

    -

    -

    -

    +

    + +

    +

    + +

    +

    + +

    +

    + +

    ```csharp commandBuffer.Barrier(BarrierStages.ComputeShading, BarrierStages.ComputeShading); ``` -

    -

    -

    BarrierStages.All

    -

    -

    -

    TextureLayoutStorage

    +

    + +

    +

    + + + +

    +

    + + BarrierStages.All + +

    +

    + +

    +

    + +

    +

    + + TextureLayout + Storage + +

    ```csharp commandBuffer.Transition(outputTexture, default, TextureLayout.Storage, TextureLayout.Sampled); ``` -

    outputTextureSampled | StorageStoragedefault

    -

    Transition

    -

    Undefined

    -

    -

    TransitionBarrier

    -

    -

    -

    -

    Submit()TimelineValueValue

    -

    producerconsumer

    +

    + + outputTexture + Sampled | Storage + Storage + default + +

    +

    + + Transition + +

    +

    + + Undefined + +

    +

    + +

    +

    + + Transition + Barrier + +

    +

    + + + +

    +

    + +

    +

    + +

    +

    + + Submit() + TimelineValue + Value + +

    +

    + producer + consumer + +

    ```csharp TimelineValue produced = producer.Submit(); @@ -70,19 +176,60 @@ TimelineValue produced = producer.Submit(); TimelineValue consumed = consumer.Submit(produced); ``` -

    produced.Wait()consumed

    -

    +

    + + produced.Wait() + consumed + +

    +

    + +

    ```csharp consumed.Wait(); ``` -

    Wait()queue.Timeline.Signal()Signal()

    -

    -

    IsCompleted

    -

    CommandBuffer.DownloadWait()

    -

    IsCompleted

    -

    -

    -

    SwapChain.Resize

    -

    SwapChain.Present()

    +

    + + Wait() + queue.Timeline.Signal() + Signal() + +

    +

    + +

    +

    + + IsCompleted + +

    +

    + + CommandBuffer.Download + Wait() + +

    +

    + + IsCompleted + + +

    +

    + +

    +

    + +

    +

    + + SwapChain.Resize + +

    +

    + + SwapChain.Present() + +

    diff --git a/documents/learn/first-triangle.md b/documents/learn/first-triangle.md index dad3102e..e114091f 100644 --- a/documents/learn/first-triangle.md +++ b/documents/learn/first-triangle.md @@ -2,54 +2,127 @@ title: '@tutorial.title' --- -

    -

    -

    -

    -

    1.

    -

    net10.0

    +

    + +

    +

    + +

    +

    + +

    +

    + +

    +

    1. +

    +

    + + + net10.0 + +

    - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + +
    + + + +
    + + + +
    + + + +
    + + + +
    -

    CAMetalLayer.cs

    -

    -

    -

    2.

    -

    FirstTriangle

    -

    +

    + + CAMetalLayer.cs + +

    +

    + + + + +

    +

    + +

    +

    2. +

    +

    + FirstTriangle + +

    +

    + +

      -
    • Silk.NET.Windowing
    • -
    • Zenith.NET
    • -
    • Zenith.NET.Compiler
    • -
    • Zenith.NET.DirectX12
    • -
    • Zenith.NET.Metal
    • -
    • Zenith.NET.Vulkan
    • +
    • Silk.NET.Windowing +
    • +
    • Zenith.NET +
    • +
    • Zenith.NET.Compiler +
    • +
    • Zenith.NET.DirectX12 +
    • +
    • Zenith.NET.Metal +
    • +
    • Zenith.NET.Vulkan +
    -

    Zenith.NETZenith.NET.Compiler

    -

    AllowUnsafeBlocks

    -

    -

    3.

    -

    CocoaHelper.cs

    -

    Program.csMain

    +

    + Zenith.NET + Zenith.NET.Compiler + +

    +

    + + + AllowUnsafeBlocks + +

    +

    + +

    +

    3. +

    +

    + + CocoaHelper.cs + +

    +

    + Program.cs + Main + +

    ```csharp using Silk.NET.Windowing; @@ -68,13 +141,32 @@ window.Run(); window.Dispose(); ``` -

    GraphicsAPI.NoneInitialize()Center()Run()Dispose()

    -

    -

    -

    4.

    -

    -

    GraphicsContext

    -

    Program.cs

    +

    + GraphicsAPI.None + Initialize()Center() + Run()Dispose() + +

    +

    + +

    +

    + +

    +

    4. +

    +

    + +

    +

    + + GraphicsContext + +

    +

    + Program.cs + +

    ```csharp using Zenith.NET; @@ -83,7 +175,14 @@ using Zenith.NET.Metal; using Zenith.NET.Vulkan; ``` -

    IWindow window

    +

    + + IWindow window + + + + +

    ```csharp GraphicsContext context; @@ -103,9 +202,23 @@ else context.ValidationMessage += static (_, args) => Console.WriteLine($"[{args.Severity}] {args.Message}"); ``` -

    ValidationMessage

    -

    -

    window.Center()window.Run()

    +

    + + ValidationMessage + +

    +

    + +

    +

    + + window.Center() + window.Run() + + + + +

    ```csharp uint width = (uint)window.FramebufferSize.X; @@ -126,10 +239,21 @@ else } ``` -

    SurfaceFramebufferSize

    -

    -

    -

    +

    + + Surface + FramebufferSize + +

    +

    + +

    +

    + +

    +

    + +

    ```csharp SwapChain swapChain = context.CreateSwapChain(new() @@ -139,9 +263,26 @@ SwapChain swapChain = context.CreateSwapChain(new() }); ``` -

    SwapChainDrawableTexturePresent()

    -

    B8G8R8A8UNormUNormswapChain.Desc.Format

    -

    window.Dispose();Program.cs

    +

    + + SwapChain + Drawable + Texture + Present() + +

    +

    + + B8G8R8A8UNorm + UNorm + swapChain.Desc.Format + +

    +

    + window.Dispose(); + Program.cs + +

    ```csharp swapChain.Dispose(); @@ -150,10 +291,22 @@ window.Dispose(); context.Dispose(); ``` -

    -

    5.

    -

    -

    _window.Run();

    +

    + +

    +

    5. +

    +

    + +

    +

    + _ + window.Run(); + + + + +

    ```csharp window.Render += _ => @@ -181,17 +334,58 @@ window.Render += _ => }; ``` -

    -

    GraphicsQueue.CommandBuffer()

    -

    TransitiondefaultUndefined

    -

    -

    -

    ColorAttachment.ClearBeginRenderPass

    -

    null

    -

    BeginRenderPass

    -

    EndRenderPassSubmit()Wait()Present()

    -

    -

    FramebufferResizewindow.Run();

    +

    + +

    +

    + + GraphicsQueue.CommandBuffer() + +

    +

    + + Transition + default + Undefined + +

    +

    + +

    +

    + +

    +

    + + ColorAttachment.Clear + BeginRenderPass + +

    +

    + null + +

    +

    + + BeginRenderPass + +

    +

    + + EndRenderPass + Submit() + Wait() + Present() + +

    +

    + +

    +

    + FramebufferResize + window.Run(); + +

    ```csharp window.FramebufferResize += _ => @@ -208,21 +402,49 @@ window.FramebufferResize += _ => }; ``` -

    -

    Present()

    -

    -

    -

    6.

    -

    -

    -

    Program.cs

    +

    + + + +

    +

    + + Present() + + +

    +

    + +

    +

    + +

    +

    6. +

    +

    + +

    +

    + +

    +

    + Program.cs + +

    ```csharp using System.Numerics; using System.Runtime.InteropServices; ``` -

    Program.cs

    +

    + + Program.cs + + + + +

    ```csharp [StructLayout(LayoutKind.Sequential)] @@ -234,9 +456,24 @@ file struct Vertex(Vector3 position, Vector4 color) } ``` -

    fileProgram.csLayoutKind.SequentialPositionColor

    -

    -

    window.Render += _ =>

    +

    + file + Program.cs + LayoutKind.Sequential + PositionColor + +

    +

    + +

    +

    + + window.Render += _ => + + + + +

    ```csharp Vertex[] vertices = @@ -247,11 +484,29 @@ Vertex[] vertices = ]; ``` -

    VertexnewVector3Vector4w = 1

    -

    -

    -

    Program.csusing Buffer = Zenith.NET.Buffer;System.Buffer

    -

    Buffer

    +

    + Vertex + newVector3 + Vector4w = 1 + +

    +

    + +

    +

    + +

    +

    + Program.cs + using Buffer = Zenith.NET.Buffer; + System.Buffer + +

    +

    + + Buffer + +

    ```csharp Buffer vertexBuffer; @@ -277,14 +532,43 @@ unsafe } ``` -

    sizeof(Vertex) * vertices.LengthBufferUsages.VertexCpuWriteOnly

    -

    Upload

    -

    fixedUpload

    -

    vertexBuffer.Dispose();swapChain.Dispose();Program.cs

    -

    -

    7.

    -

    -

    Triangle.slang

    +

    + + sizeof(Vertex) * vertices.Length + BufferUsages.Vertex + CpuWriteOnly + +

    +

    + + Upload + +

    +

    + fixed + Upload + +

    +

    + + vertexBuffer.Dispose(); + swapChain.Dispose(); + Program.cs + + +

    +

    + +

    +

    7. +

    +

    + +

    +

    + Triangle.slang + +

    ```slang struct VSInput @@ -302,10 +586,23 @@ struct FSInput }; ``` -

    VSInputPOSITION0COLOR0

    -

    FSInputSV_POSITIONCOLOR0

    -

    -

    Triangle.slang

    +

    + VSInput + POSITION0COLOR0 + +

    +

    + FSInput + SV_POSITIONCOLOR0 + +

    +

    + +

    +

    + Triangle.slang + +

    ```slang [shader("vertex")] @@ -319,9 +616,16 @@ FSInput VSMain(VSInput input) } ``` -

    w = 1

    -

    -

    +

    + w = 1 + +

    +

    + +

    +

    + +

    ```slang [shader("fragment")] @@ -331,10 +635,25 @@ float4 FSMain(FSInput input) : SV_TARGET } ``` -

    FSMainSV_TARGET

    -

    -

    Triangle.slang

    -

    Program.cs

    +

    + FSMain + SV_TARGET + +

    +

    + +

    +

    + + Triangle.slang + + + +

    +

    + Program.cs + +

    ```csharp string shaderPath = Path.Combine(AppContext.BaseDirectory, "Triangle.slang"); @@ -343,11 +662,27 @@ Shader vertexShader = context.CreateShader(ZenithCompiler.CompileFromFile(contex Shader fragmentShader = context.CreateShader(ZenithCompiler.CompileFromFile(context.GraphicsApi, shaderPath, "FSMain")); ``` -

    ZenithCompilerCreateShadercontext.GraphicsApiVSMainFSMain

    -

    AppContext.BaseDirectory

    -

    -

    8.

    -

    +

    + + ZenithCompiler + CreateShader + context.GraphicsApi + VSMainFSMain + +

    +

    + + AppContext.BaseDirectory + +

    +

    + +

    +

    8. +

    +

    + +

    ```csharp InputLayout inputLayout = new(); @@ -355,50 +690,117 @@ inputLayout.Add(new() { Format = ElementFormat.Float3, Semantic = ElementSemanti inputLayout.Add(new() { Format = ElementFormat.Float4, Semantic = ElementSemantic.Color }); ``` -

    InputLayout.Add

    +

    + + InputLayout.Add + +

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Vertex.Position0Float3POSITION0
    Vertex.Color12Float4COLOR0
    28
    + + + + + + + +
    Vertex.Position + 0 + + Float3 + + POSITION0 +
    Vertex.Color + 12 + + Float4 + + COLOR0 +
    + + 28 + + + +
    -

    SemanticIndexPOSITION0COLOR0

    -

    -

    9.

    -

    GraphicsPipeline

    -

    +

    + + SemanticIndex + POSITION0COLOR0 + +

    +

    + +

    +

    9. +

    +

    + + GraphicsPipeline + +

    +

    + +

    -

    +

    + +

    ```csharp GraphicsPipeline pipeline = context.CreateGraphicsPipeline(new() @@ -424,10 +826,24 @@ vertexShader.Dispose(); fragmentShader.Dispose(); ``` -

    pipeline.Dispose();vertexBuffer.Dispose();

    -

    -

    10.

    -

    window.Render// Add the triangle draw commands here later.BeginRenderPassEndRenderPass

    +

    + + pipeline.Dispose(); + vertexBuffer.Dispose(); + +

    +

    + +

    +

    10. +

    +

    + window.Render + // Add the triangle draw commands here later. + BeginRenderPass + EndRenderPass + +

    ```csharp commandBuffer.SetPipeline(pipeline); @@ -436,49 +852,99 @@ commandBuffer.SetVertexBuffer(vertexBuffer, 0, 0); commandBuffer.Draw(3, 1, 0, 0); ``` -

    SetPipeline

    -

    SetVertexBuffer(vertexBuffer, 0, 0)InputLayouts

    -

    Draw

    +

    + + SetPipeline + +

    +

    + + SetVertexBuffer(vertexBuffer, 0, 0) + InputLayouts + +

    +

    + + Draw + +

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    vertexCount3
    instanceCount1
    firstVertex0
    firstInstance0
    + + + + + +
    vertexCount + 3 + +
    instanceCount + 1 + +
    firstVertex + 0 + +
    firstInstance + 0 + +
    -

    Submit().Wait()Present()

    -

    -

    11.

    -

    FirstTriangle

    - -

    -

    -

    -

    +

    + + Submit().Wait() + Present() + +

    +

    + +

    +

    11. +

    +

    + FirstTriangle + +

    + +

    + +

    +

    + +

    +

    + +

    +

    + +

    ```text Get the current drawable @@ -494,7 +960,11 @@ Submit and wait Present ``` -

    Runwindow.Run();

    +

    + Run + window.Run(); + +

    ```csharp pipeline.Dispose(); @@ -505,37 +975,78 @@ window.Dispose(); context.Dispose(); ``` -

    Dispose()

    -

    -

    +

    + + Dispose() + +

    +

    + +

    +

    + +

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Triangle.slang
    + + + +
    + + + +
    + + + +
    + + + + Triangle.slang + +
    + + + +
    + + + +
    -

    Program.cs

    +

    + + + + Program.cs + + +

    diff --git a/documents/learn/index.md b/documents/learn/index.md index c6e521bd..92c27f42 100644 --- a/documents/learn/index.md +++ b/documents/learn/index.md @@ -6,36 +6,125 @@ _disableAffix: true --- diff --git a/documents/learn/samples.md b/documents/learn/samples.md index 2ddcc6d7..9a5eca9b 100644 --- a/documents/learn/samples.md +++ b/documents/learn/samples.md @@ -2,66 +2,237 @@ title: '@samples.title' --- -

    -

    -

    -

    -

    -

    -

    -

    @samples.triangle.title

    -

    HelloTriangleRenderer.csHelloTriangle.slang

    -

    -

    D32FloatS8UInt

    -

    @samples.cube.title

    -

    SpinningCubeRenderer.csSpinningCube.slang

    -

    -

    Assets/Textures/shoko.png

    -

    @samples.computeShader.title

    -

    ComputeShaderRenderer.csComputeShader.slang

    -

    -

    -

    @samples.indirectDrawing.title

    -

    IndirectDrawingRenderer.csIndirectDrawing.slang

    -

    -

    context.Capabilities.RayTracingSupported

    -

    @samples.rayTracing.title

    -

    RayTracingRenderer.csRayTracing.slang

    -

    -

    context.Capabilities.MeshShadingSupported

    -

    @samples.meshShading.title

    -

    MeshShadingRenderer.csMeshShading.slang

    -

    -

    App.csIRenderer.cs

    -

    TexturePresenter.csPresentTexture.slang

    -

    -

    -

    +

    + +

    +

    + + + +

    +

    + +

    +

    + +

    +

    + + + +

    +

    + +

    +

    + +

    +

    + + @samples.triangle.title + +

    +

    + + HelloTriangleRenderer.cs + HelloTriangle.slang + + +

    +

    + +

    +

    + + D32FloatS8UInt + +

    +

    + + @samples.cube.title + +

    +

    + + SpinningCubeRenderer.cs + SpinningCube.slang + +

    +

    + +

    +

    + + Assets/Textures/shoko.png + +

    +

    + + @samples.computeShader.title + +

    +

    + + ComputeShaderRenderer.cs + ComputeShader.slang + +

    +

    + +

    +

    + +

    +

    + + @samples.indirectDrawing.title + +

    +

    + + IndirectDrawingRenderer.cs + IndirectDrawing.slang + +

    +

    + +

    +

    + + context.Capabilities.RayTracingSupported + +

    +

    + + @samples.rayTracing.title + +

    +

    + + RayTracingRenderer.cs + RayTracing.slang + +

    +

    + +

    +

    + + context.Capabilities.MeshShadingSupported + +

    +

    + + @samples.meshShading.title + +

    +

    + + MeshShadingRenderer.cs + MeshShading.slang + +

    +

    + +

    +

    + + App.cs + IRenderer.cs + +

    +

    + + TexturePresenter.cs + PresentTexture.slang + +

    +

    + +

    +

    + +

    +

    + + + +

    - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    + + + + + +
    + + + + + +
    + + + + + +
    + + + + + +
    -

    +

    + + + +

    diff --git a/documents/locales/de-DE/strings.yml b/documents/locales/de-DE/strings.yml index 43f5e038..c4dea822 100644 --- a/documents/locales/de-DE/strings.yml +++ b/documents/locales/de-DE/strings.yml @@ -1,91 +1,91 @@ ### YamlMime:Resources -concepts.execution.context.description: "Ein {graphicsContext} verbindet die Anwendung über ein bestimmtes Backend mit einem GPU-Gerät und stellt dessen Grafik-, Compute- und Transferwarteschlangen bereit. Gemeinsam verwendete Ressourcen müssen demselben Kontext angehören: Puffer, Texturen, Shader, Pipelines und ihre Handles lassen sich nicht über Kontextgrenzen hinweg binden." -concepts.execution.context.details: "{capabilities} liefert den Gerätenamen und die unterstützten Funktionen. Prüfen Sie mit {rayTracingSupported} und {meshShadingSupported}, ob die jeweilige Funktion verfügbar ist, bevor Sie ihre Ressourcen erstellen. Die Beispiele für {link} und {detail} zeigen diese Prüfung bei der Initialisierung." +concepts.execution.context.description: 'Ein {graphicsContext} verbindet die Anwendung über ein bestimmtes Backend mit einem GPU-Gerät und stellt dessen Grafik-, Compute- und Transferwarteschlangen bereit. Gemeinsam verwendete Ressourcen müssen demselben Kontext angehören: Puffer, Texturen, Shader, Pipelines und ihre Handles lassen sich nicht über Kontextgrenzen hinweg binden.' +concepts.execution.context.details: '{capabilities} liefert den Gerätenamen und die unterstützten Funktionen. Prüfen Sie mit {rayTracingSupported} und {meshShadingSupported}, ob die jeweilige Funktion verfügbar ist, bevor Sie ihre Ressourcen erstellen. Die Beispiele für {link} und {detail} zeigen diese Prüfung bei der Initialisierung.' concepts.execution.context.details.detail: Mesh-Shading concepts.execution.context.details.link: Raytracing -concepts.execution.context.title: "Grafikkontext" -concepts.execution.description: "GPU-Arbeit beginnt auf der CPU: Die Anwendung erstellt Ressourcen, zeichnet Befehle zu ihrer Verwendung auf und reicht diese bei einer Warteschlange ein. Danach kann die CPU weiterarbeiten, während die GPU die Befehle ausführt. Die benötigten Ressourcen müssen bis zum Ende dieser Ausführung verfügbar bleiben." -concepts.execution.ownership.description: "Der Besitz legt fest, wer ein Objekt freigibt; der GPU-Abschluss bestimmt, wann dies zulässig ist. {dispose} gibt native Ressourcen auch dann frei, wenn noch C#-Referenzen auf das Objekt bestehen. Das Einreichen von Befehlen überträgt den Besitz ihrer Ressourcen nicht an die Warteschlange." -concepts.execution.ownership.details: "Stoppen Sie beim Beenden neue Einreichungen und warten Sie auf die letzte Ressourcennutzung in allen beteiligten Warteschlangen. Geben Sie danach die Anwendungsressourcen und zuletzt den Kontext frei. Der Kontext gibt seine Warteschlangen und internen Hilfsobjekte frei; dieser Schritt muss deshalb nach Abschluss der Anwendungsarbeit erfolgen." -concepts.execution.ownership.guidance: "Verfolgen Sie während des Renderings den Abschluss aller Zugriffe auf Daten, die überschrieben, oder Ressourcen, die ersetzt werden sollen. Warten Sie auf diese Zugriffe, bevor Sie den betreffenden Speicher ändern oder freigeben. Wie Ansichten und ihre zugrunde liegenden Ressourcen in dieses Lebensdauermodell passen, beschreibt {link}." +concepts.execution.context.title: 'Grafikkontext' +concepts.execution.description: 'GPU-Arbeit beginnt auf der CPU: Die Anwendung erstellt Ressourcen, zeichnet Befehle zu ihrer Verwendung auf und reicht diese bei einer Warteschlange ein. Danach kann die CPU weiterarbeiten, während die GPU die Befehle ausführt. Die benötigten Ressourcen müssen bis zum Ende dieser Ausführung verfügbar bleiben.' +concepts.execution.ownership.description: 'Der Besitz legt fest, wer ein Objekt freigibt; der GPU-Abschluss bestimmt, wann dies zulässig ist. {dispose} gibt native Ressourcen auch dann frei, wenn noch C#-Referenzen auf das Objekt bestehen. Das Einreichen von Befehlen überträgt den Besitz ihrer Ressourcen nicht an die Warteschlange.' +concepts.execution.ownership.details: 'Stoppen Sie beim Beenden neue Einreichungen und warten Sie auf die letzte Ressourcennutzung in allen beteiligten Warteschlangen. Geben Sie danach die Anwendungsressourcen und zuletzt den Kontext frei. Der Kontext gibt seine Warteschlangen und internen Hilfsobjekte frei; dieser Schritt muss deshalb nach Abschluss der Anwendungsarbeit erfolgen.' +concepts.execution.ownership.guidance: 'Verfolgen Sie während des Renderings den Abschluss aller Zugriffe auf Daten, die überschrieben, oder Ressourcen, die ersetzt werden sollen. Warten Sie auf diese Zugriffe, bevor Sie den betreffenden Speicher ändern oder freigeben. Wie Ansichten und ihre zugrunde liegenden Ressourcen in dieses Lebensdauermodell passen, beschreibt {link}.' concepts.execution.ownership.guidance.link: Ressourcenverwaltung concepts.execution.ownership.table.applicationResources.object: Von der Anwendung erstellte Ressourcen concepts.execution.ownership.table.applicationResources.ownership: Die Anwendung gibt sie nach ihrer letzten GPU-Verwendung frei. concepts.execution.ownership.table.commandBuffers.object: Geliehene Befehlspuffer concepts.execution.ownership.table.commandBuffers.ownership: Die Warteschlange verwaltet und recycelt sie. concepts.execution.ownership.table.headings.object: Objekt -concepts.execution.ownership.table.headings.ownership: "Verantwortung für die Freigabe" -concepts.execution.ownership.table.queues.object: "Kontextwarteschlangen und ihre Timelines" +concepts.execution.ownership.table.headings.ownership: 'Verantwortung für die Freigabe' +concepts.execution.ownership.table.queues.object: 'Kontextwarteschlangen und ihre Timelines' concepts.execution.ownership.table.queues.ownership: Der Kontext und die Warteschlangen verwalten sie. concepts.execution.ownership.table.swapChainDrawable.ownership: Die Swapchain verwaltet sie. -concepts.execution.ownership.title: "Besitz und Lebensdauer" -concepts.execution.pipelines.description: "Eine Grafikpipeline legt Shader, Vertex-Eingabelayout, Primitivzusammensetzung, Attachment-Formate und Renderzustand für Zeichenbefehle fest. Wählen Sie die Pipeline, bevor Sie Vertex-, Index- oder Konstantendaten binden. Attachment-Formate und Sample-Anzahl müssen mit dem Renderpass übereinstimmen." -concepts.execution.pipelines.details: "Eine Compute-Pipeline wählt den Shader-Einstiegspunkt für einen Dispatch. Binden Sie Pipeline und Konstanten vor dem Dispatch, außerhalb eines Grafik-Renderpasses." -concepts.execution.pipelines.guidance: "Der {link} zeigt die Grafiksequenz. Das {detail} ergänzt einen Compute-Dispatch vor dem Grafikpass, der dessen Ausgabe darstellt." +concepts.execution.ownership.title: 'Besitz und Lebensdauer' +concepts.execution.pipelines.description: 'Eine Grafikpipeline legt Shader, Vertex-Eingabelayout, Primitivzusammensetzung, Attachment-Formate und Renderzustand für Zeichenbefehle fest. Wählen Sie die Pipeline, bevor Sie Vertex-, Index- oder Konstantendaten binden. Attachment-Formate und Sample-Anzahl müssen mit dem Renderpass übereinstimmen.' +concepts.execution.pipelines.details: 'Eine Compute-Pipeline wählt den Shader-Einstiegspunkt für einen Dispatch. Binden Sie Pipeline und Konstanten vor dem Dispatch, außerhalb eines Grafik-Renderpasses.' +concepts.execution.pipelines.guidance: 'Der {link} zeigt die Grafiksequenz. Das {detail} ergänzt einen Compute-Dispatch vor dem Grafikpass, der dessen Ausgabe darstellt.' concepts.execution.pipelines.guidance.detail: Compute-Beispiel concepts.execution.pipelines.guidance.link: Render-Callback des Dreiecks -concepts.execution.pipelines.title: "Pipeline-Zustand" -concepts.execution.queues.description: "{graphicsQueue} ist der übliche Ausgangspunkt für Frames mit Zeichnen, Berechnungen und Kopien. Abhängige Operationen auf einer Warteschlange lassen sich einfacher anordnen." -concepts.execution.queues.details: "Mit getrennten Warteschlangen lassen sich unabhängige Aufgaben getrennt einreichen. Daraus folgt jedoch nicht, dass ihnen unabhängige Hardwareeinheiten zugeordnet sind. Zusätzliche Warteschlangen sind sinnvoll, wenn Aufgaben von einer überlappenden Ausführung profitieren. Verwendet eine Warteschlange Daten aus einer anderen, benötigen ihre Einreichungen eine explizite Abhängigkeit." -concepts.execution.queues.guidance: "Auch innerhalb einer Warteschlange können abhängige Operationen Barrieren oder Texturübergänge benötigen, damit spätere Zugriffe die Ergebnisse früherer Schreibvorgänge sehen. Diese Speicherabhängigkeiten sind von der Einreichungsreihenfolge zu unterscheiden. Wie sie angegeben werden, erläutert {link}." +concepts.execution.pipelines.title: 'Pipeline-Zustand' +concepts.execution.queues.description: '{graphicsQueue} ist der übliche Ausgangspunkt für Frames mit Zeichnen, Berechnungen und Kopien. Abhängige Operationen auf einer Warteschlange lassen sich einfacher anordnen.' +concepts.execution.queues.details: 'Mit getrennten Warteschlangen lassen sich unabhängige Aufgaben getrennt einreichen. Daraus folgt jedoch nicht, dass ihnen unabhängige Hardwareeinheiten zugeordnet sind. Zusätzliche Warteschlangen sind sinnvoll, wenn Aufgaben von einer überlappenden Ausführung profitieren. Verwendet eine Warteschlange Daten aus einer anderen, benötigen ihre Einreichungen eine explizite Abhängigkeit.' +concepts.execution.queues.guidance: 'Auch innerhalb einer Warteschlange können abhängige Operationen Barrieren oder Texturübergänge benötigen, damit spätere Zugriffe die Ergebnisse früherer Schreibvorgänge sehen. Diese Speicherabhängigkeiten sind von der Einreichungsreihenfolge zu unterscheiden. Wie sie angegeben werden, erläutert {link}.' concepts.execution.queues.guidance.link: Synchronisation concepts.execution.queues.table.computeQueue.workToRecord: Compute-Dispatches und kompatible Transferarbeiten, ohne Grafik-Renderpässe. -concepts.execution.queues.table.graphicsQueue.workToRecord: "Renderpässe, Zeichenbefehle sowie Compute- und Transferoperationen." +concepts.execution.queues.table.graphicsQueue.workToRecord: 'Renderpässe, Zeichenbefehle sowie Compute- und Transferoperationen.' concepts.execution.queues.table.headings.queue: Warteschlange -concepts.execution.queues.table.headings.workToRecord: "Unterstützte Operationen" +concepts.execution.queues.table.headings.workToRecord: 'Unterstützte Operationen' concepts.execution.queues.table.transferQueue.workToRecord: Upload-, Download- und Kopierarbeiten, ohne Zeichnen oder Compute-Dispatches. -concepts.execution.queues.title: "Wahl der Warteschlange" -concepts.execution.recording.context: "Die Warteschlange nimmt abgeschlossene Befehlspuffer zur Wiederverwendung zurück. Fordern Sie für jede Aufzeichnung mit {queueCommandBuffer} einen Puffer an, zeichnen Sie jeweils nur von einem Thread aus auf und reichen Sie den Puffer einmal ein. Nach der Einreichung übernimmt die Warteschlange seine Verwaltung; ändern Sie ihn nicht mehr, reichen Sie ihn nicht erneut ein und geben Sie ihn nicht selbst frei." -concepts.execution.recording.description: "{queueCommandBuffer} liefert einen {commandBuffer} mit bereits begonnener Aufzeichnung. Zeichnen Sie die Operationen und ihre Abhängigkeiten auf und rufen Sie anschließend einmal {submit} auf. Dadurch endet die Aufzeichnung; der zurückgegebene {timelineValue} bezeichnet den Abschlusspunkt in dieser Warteschlange." -concepts.execution.recording.details: "Nach der Aufzeichnung eines Frames in {commandBuffer} reicht das Dreieck-Tutorial die Befehle ein und wartet:" -concepts.execution.recording.guidance: "Die Aufzeichnung legt die Befehlsfolge fest; {submit} plant deren Ausführung ein. Ein anschließender Aufruf von {wait} blockiert den CPU-Thread bis zum Abschluss der Einreichung. Im Dreieck-Tutorial bleibt der Frame-Ablauf dadurch übersichtlich: Ein Frame ist abgeschlossen, bevor der nächste beginnt." -concepts.execution.recording.title: "Aufzeichnung und Einreichung" +concepts.execution.queues.title: 'Wahl der Warteschlange' +concepts.execution.recording.context: 'Die Warteschlange nimmt abgeschlossene Befehlspuffer zur Wiederverwendung zurück. Fordern Sie für jede Aufzeichnung mit {queueCommandBuffer} einen Puffer an, zeichnen Sie jeweils nur von einem Thread aus auf und reichen Sie den Puffer einmal ein. Nach der Einreichung übernimmt die Warteschlange seine Verwaltung; ändern Sie ihn nicht mehr, reichen Sie ihn nicht erneut ein und geben Sie ihn nicht selbst frei.' +concepts.execution.recording.description: '{queueCommandBuffer} liefert einen {commandBuffer} mit bereits begonnener Aufzeichnung. Zeichnen Sie die Operationen und ihre Abhängigkeiten auf und rufen Sie anschließend einmal {submit} auf. Dadurch endet die Aufzeichnung; der zurückgegebene {timelineValue} bezeichnet den Abschlusspunkt in dieser Warteschlange.' +concepts.execution.recording.details: 'Nach der Aufzeichnung eines Frames in {commandBuffer} reicht das Dreieck-Tutorial die Befehle ein und wartet:' +concepts.execution.recording.guidance: 'Die Aufzeichnung legt die Befehlsfolge fest; {submit} plant deren Ausführung ein. Ein anschließender Aufruf von {wait} blockiert den CPU-Thread bis zum Abschluss der Einreichung. Im Dreieck-Tutorial bleibt der Frame-Ablauf dadurch übersichtlich: Ein Frame ist abgeschlossen, bevor der nächste beginnt.' +concepts.execution.recording.title: 'Aufzeichnung und Einreichung' concepts.execution.title: Ausführungsmodell -concepts.platforms.description: "Die Präsentation übernimmt entweder die Anwendung oder ein UI-Steuerelement. Damit steht fest, wer die Ausgabetextur des Frames abruft, Befehle aufzeichnet und einreicht und das Ergebnis präsentiert. Diese Ausgabetextur heißt Drawable." -concepts.platforms.frame.context: "Zeichnen Sie Pipeline-Bindungen und Zeichenbefehle innerhalb des Passes auf und beenden Sie ihn, bevor der Handler zurückkehrt. Das Steuerelement reicht die Befehle ein und präsentiert das Ergebnis. Der Handler darf weder den Befehlspuffer einreichen noch eines der beiden bereitgestellten Objekte freigeben. Ändert er das Texturlayout, muss er vor seiner Rückkehr {colorAttachment} wiederherstellen, damit das Steuerelement den abschließenden Übergang ausführen kann." -concepts.platforms.frame.description: "Die Steuerelemente implementieren {iZenithView}. Die Anwendung weist {graphicsContext} zu, aktualisiert die Szene in {updateRequested} und zeichnet in {renderRequested} anhand der übergebenen {renderEventArgs} auf." -concepts.platforms.frame.details: "Für jeden Frame bezieht das Steuerelement eine Ausgabetextur und einen Befehlspuffer, überführt die Textur nach {colorAttachment} und ruft die Update- und Render-Handler auf. Anschließend reicht es die aufgezeichneten Befehle ein und zeigt das Bild über den Präsentationsmechanismus des Frameworks an." -concepts.platforms.frame.guidance: "Ergänzen Sie {usingZenithNET} in der Datei. Für ein initialisiertes {iZenithView} namens {view} mit zugewiesenem Grafikkontext registrieren Sie diesen Handler, der die Ausgabetextur mit einer Farbe füllt:" -concepts.platforms.frame.notes: "Der anfängliche Übergang verwendet {undefined} und erlaubt damit, den bisherigen Bildinhalt zu verwerfen. Füllen oder zeichnen Sie deshalb in jedem Frame das gesamte Bild neu. Speichern Sie akkumulierte oder zwischengespeicherte Ergebnisse in einer anwendungseigenen Textur und zeichnen Sie diese anschließend in die Ausgabetextur des Steuerelements." -concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat} liefert das Standardfarbformat dieser Integrationen." -concepts.platforms.frame.title: "Rendering über UI-Steuerelemente" -concepts.platforms.integration.context: "WinForms, WPF und die Windows-Integration von WinUI laufen unter Windows. Installieren Sie für MAUI die Workload der Zielplattform und registrieren Sie den Steuerelement-Handler mit {useZenithView}, wie in {extensionsCs} gezeigt." -concepts.platforms.integration.description: "Die Ereignisschnittstelle ist gemeinsam, der Präsentationsmechanismus hängt jedoch vom Framework ab:" -concepts.platforms.integration.details: "Die Implementierungen unterscheiden sich darin, wie das GPU-Bild in die Oberfläche gelangt. Beim Bitmap-Rücklesen werden die Pixel vor der Anzeige in CPU-Speicher kopiert. Interop über gemeinsam genutzte Texturen vermeidet diese CPU-Kopie, kann aber weiterhin GPU-Kopien und Synchronisation erfordern. Berücksichtigen Sie bei der Wahl der Integration neben dem gemeinsamen Ereignis {renderRequested} auch diesen Präsentationsweg." -concepts.platforms.integration.guidance: "Fügen Sie das Integrationspaket für Ihr UI-Framework über NuGet hinzu. Für Avalonia verwenden Sie {avaloniaPackage}." +concepts.platforms.description: 'Die Präsentation übernimmt entweder die Anwendung oder ein UI-Steuerelement. Damit steht fest, wer die Ausgabetextur des Frames abruft, Befehle aufzeichnet und einreicht und das Ergebnis präsentiert. Diese Ausgabetextur heißt Drawable.' +concepts.platforms.frame.context: 'Zeichnen Sie Pipeline-Bindungen und Zeichenbefehle innerhalb des Passes auf und beenden Sie ihn, bevor der Handler zurückkehrt. Das Steuerelement reicht die Befehle ein und präsentiert das Ergebnis. Der Handler darf weder den Befehlspuffer einreichen noch eines der beiden bereitgestellten Objekte freigeben. Ändert er das Texturlayout, muss er vor seiner Rückkehr {colorAttachment} wiederherstellen, damit das Steuerelement den abschließenden Übergang ausführen kann.' +concepts.platforms.frame.description: 'Die Steuerelemente implementieren {iZenithView}. Die Anwendung weist {graphicsContext} zu, aktualisiert die Szene in {updateRequested} und zeichnet in {renderRequested} anhand der übergebenen {renderEventArgs} auf.' +concepts.platforms.frame.details: 'Für jeden Frame bezieht das Steuerelement eine Ausgabetextur und einen Befehlspuffer, überführt die Textur nach {colorAttachment} und ruft die Update- und Render-Handler auf. Anschließend reicht es die aufgezeichneten Befehle ein und zeigt das Bild über den Präsentationsmechanismus des Frameworks an.' +concepts.platforms.frame.guidance: 'Ergänzen Sie {usingZenithNET} in der Datei. Für ein initialisiertes {iZenithView} namens {view} mit zugewiesenem Grafikkontext registrieren Sie diesen Handler, der die Ausgabetextur mit einer Farbe füllt:' +concepts.platforms.frame.notes: 'Der anfängliche Übergang verwendet {undefined} und erlaubt damit, den bisherigen Bildinhalt zu verwerfen. Füllen oder zeichnen Sie deshalb in jedem Frame das gesamte Bild neu. Speichern Sie akkumulierte oder zwischengespeicherte Ergebnisse in einer anwendungseigenen Textur und zeichnen Sie diese anschließend in die Ausgabetextur des Steuerelements.' +concepts.platforms.frame.reference: '{zenithViewHelperDrawableFormat} liefert das Standardfarbformat dieser Integrationen.' +concepts.platforms.frame.title: 'Rendering über UI-Steuerelemente' +concepts.platforms.integration.context: 'WinForms, WPF und die Windows-Integration von WinUI laufen unter Windows. Installieren Sie für MAUI die Workload der Zielplattform und registrieren Sie den Steuerelement-Handler mit {useZenithView}, wie in {extensionsCs} gezeigt.' +concepts.platforms.integration.description: 'Die Ereignisschnittstelle ist gemeinsam, der Präsentationsmechanismus hängt jedoch vom Framework ab:' +concepts.platforms.integration.details: 'Die Implementierungen unterscheiden sich darin, wie das GPU-Bild in die Oberfläche gelangt. Beim Bitmap-Rücklesen werden die Pixel vor der Anzeige in CPU-Speicher kopiert. Interop über gemeinsam genutzte Texturen vermeidet diese CPU-Kopie, kann aber weiterhin GPU-Kopien und Synchronisation erfordern. Berücksichtigen Sie bei der Wahl der Integration neben dem gemeinsamen Ereignis {renderRequested} auch diesen Präsentationsweg.' +concepts.platforms.integration.guidance: 'Fügen Sie das Integrationspaket für Ihr UI-Framework über NuGet hinzu. Für Avalonia verwenden Sie {avaloniaPackage}.' concepts.platforms.integration.table.avalonia.integration: Avalonia -concepts.platforms.integration.table.avalonia.presentation: "Rendert in eine Textur und liest die Pixel in {writeableBitmap} zurück. Implementierung: {zenithViewCs} und {surfaceCs}." +concepts.platforms.integration.table.avalonia.presentation: 'Rendert in eine Textur und liest die Pixel in {writeableBitmap} zurück. Implementierung: {zenithViewCs} und {surfaceCs}.' concepts.platforms.integration.table.headings.integration: Integration -concepts.platforms.integration.table.headings.presentation: "Präsentationsmechanismus" +concepts.platforms.integration.table.headings.presentation: 'Präsentationsmechanismus' concepts.platforms.integration.table.maui.integration: .NET MAUI -concepts.platforms.integration.table.maui.presentation: "Verwendet native Oberflächen unter Android, iOS und Mac Catalyst sowie Komposition über gemeinsam genutzte Texturen unter Windows. Siehe die {link}." +concepts.platforms.integration.table.maui.presentation: 'Verwendet native Oberflächen unter Android, iOS und Mac Catalyst sowie Komposition über gemeinsam genutzte Texturen unter Windows. Siehe die {link}.' concepts.platforms.integration.table.maui.presentation.link: Plattformimplementierungen concepts.platforms.integration.table.uno.integration: Uno-Pfad -concepts.platforms.integration.table.uno.presentation: "Liest Pixel in {writeableBitmap} zurück. Implementierung: {zenithViewUnoCs}." +concepts.platforms.integration.table.uno.presentation: 'Liest Pixel in {writeableBitmap} zurück. Implementierung: {zenithViewUnoCs}.' concepts.platforms.integration.table.winForms.integration: WinForms -concepts.platforms.integration.table.winForms.presentation: "Erstellt eine Zenith.NET-Swapchain für das Fensterhandle {hWND} des Steuerelements. Implementierung: {zenithViewCs}." +concepts.platforms.integration.table.winForms.presentation: 'Erstellt eine Zenith.NET-Swapchain für das Fensterhandle {hWND} des Steuerelements. Implementierung: {zenithViewCs}.' concepts.platforms.integration.table.winUI.integration: WinUI unter Windows -concepts.platforms.integration.table.winUI.presentation: "Rendert in eine importierte, gemeinsam genutzte Direct3D 11-Textur und kopiert das Ergebnis in eine an {swapChainPanel} angebundene Kompositions-Swapchain. Siehe {zenithViewWinUICs}." +concepts.platforms.integration.table.winUI.presentation: 'Rendert in eine importierte, gemeinsam genutzte Direct3D 11-Textur und kopiert das Ergebnis in eine an {swapChainPanel} angebundene Kompositions-Swapchain. Siehe {zenithViewWinUICs}.' concepts.platforms.integration.table.wpf.integration: WPF -concepts.platforms.integration.table.wpf.presentation: "Importiert eine gemeinsam genutzte Direct3D 11-Textur und kopiert ihren Inhalt über Direct3D-Interop in eine von {d3DImage} angezeigte Oberfläche. Siehe {surfaceCs}." -concepts.platforms.integration.title: "Framework und Präsentationspfad" -concepts.platforms.lifecycle.context: "Verwenden Sie {descWidth}, {descHeight}, {descFormat} und {descSampleCount} der im Render-Ereignis bereitgestellten Ausgabetextur, um passende Attachments zu erstellen. Diese Textur liefert die tatsächlichen Maße des Renderziels. Richten Sie sich nach diesen Maßen, statt sie aus der Layoutgröße des Steuerelements oder der Anzeigeskalierung zu berechnen." -concepts.platforms.lifecycle.description: "Die Swapchain verwendet Breite und Höhe des Framebuffers in Pixeln. Bei Anzeigeskalierung können sie von den logischen Fenstermaßen abweichen. Verschieben Sie Rendering und Swapchain-Größenanpassung, solange eine Abmessung null ist. Beziehen Sie {swapChainDrawable} für jeden Frame neu: Diese Textur gehört der Swapchain und kann nach Präsentation oder Größenänderung ersetzt werden." -concepts.platforms.lifecycle.details: "Ändern sich die Framebuffer-Maße, warten Sie vor {swapChainResize} auf alle noch laufenden GPU-Zugriffe auf die alten Bilder. Soll das native Präsentationsziel ersetzt werden, übergeben Sie nach Abschluss dieser Zugriffe seine neue Beschreibung und Handles an {swapChainRefresh}. Geben Sie beim Beenden die Swapchain vor ihrem nativen Präsentationsziel frei." -concepts.platforms.lifecycle.guidance: "Richten sich anwendungseigene Tiefen- oder Offscreen-Texturen nach der Fenstergröße, erstellen Sie sie bei einer Größenänderung neu und aktualisieren Sie Konstanten mit ihren Handles. Die Pipeline bleibt verwendbar, solange Attachment-Formate und Sample-Anzahlen weiterhin übereinstimmen. Der {link} zeigt, wie angepasste Texturen und eine wiederverwendete Pipeline zusammenarbeiten." +concepts.platforms.integration.table.wpf.presentation: 'Importiert eine gemeinsam genutzte Direct3D 11-Textur und kopiert ihren Inhalt über Direct3D-Interop in eine von {d3DImage} angezeigte Oberfläche. Siehe {surfaceCs}.' +concepts.platforms.integration.title: 'Framework und Präsentationspfad' +concepts.platforms.lifecycle.context: 'Verwenden Sie {descWidth}, {descHeight}, {descFormat} und {descSampleCount} der im Render-Ereignis bereitgestellten Ausgabetextur, um passende Attachments zu erstellen. Diese Textur liefert die tatsächlichen Maße des Renderziels. Richten Sie sich nach diesen Maßen, statt sie aus der Layoutgröße des Steuerelements oder der Anzeigeskalierung zu berechnen.' +concepts.platforms.lifecycle.description: 'Die Swapchain verwendet Breite und Höhe des Framebuffers in Pixeln. Bei Anzeigeskalierung können sie von den logischen Fenstermaßen abweichen. Verschieben Sie Rendering und Swapchain-Größenanpassung, solange eine Abmessung null ist. Beziehen Sie {swapChainDrawable} für jeden Frame neu: Diese Textur gehört der Swapchain und kann nach Präsentation oder Größenänderung ersetzt werden.' +concepts.platforms.lifecycle.details: 'Ändern sich die Framebuffer-Maße, warten Sie vor {swapChainResize} auf alle noch laufenden GPU-Zugriffe auf die alten Bilder. Soll das native Präsentationsziel ersetzt werden, übergeben Sie nach Abschluss dieser Zugriffe seine neue Beschreibung und Handles an {swapChainRefresh}. Geben Sie beim Beenden die Swapchain vor ihrem nativen Präsentationsziel frei.' +concepts.platforms.lifecycle.guidance: 'Richten sich anwendungseigene Tiefen- oder Offscreen-Texturen nach der Fenstergröße, erstellen Sie sie bei einer Größenänderung neu und aktualisieren Sie Konstanten mit ihren Handles. Die Pipeline bleibt verwendbar, solange Attachment-Formate und Sample-Anzahlen weiterhin übereinstimmen. Der {link} zeigt, wie angepasste Texturen und eine wiederverwendete Pipeline zusammenarbeiten.' concepts.platforms.lifecycle.guidance.link: Renderer des rotierenden Würfels -concepts.platforms.lifecycle.title: "Swapchain-Abmessungen und Lebensdauer" -concepts.platforms.ownership.description: "Die Anwendung besitzt den zugewiesenen Kontext und ihre Rendering-Ressourcen, das Steuerelement seine Präsentationsressourcen. Ändert sich {graphicsContext} der Ansicht, erstellt der Scheduler die Steuerelement-Ressourcen für den neuen Kontext neu. Auch die Anwendung muss ihre Pipelines, Puffer und Texturen für diesen Kontext neu erstellen." -concepts.platforms.ownership.details: "Halten Sie vor dem Ersetzen von Rendering-Ressourcen die Frame-Verarbeitung der Ansicht an und warten Sie auf die GPU-Arbeit, die diese Ressourcen verwendet. Erst danach dürfen die alten Ressourcen oder der Kontext freigegeben werden. Auch beim Entfernen der Ansicht bleibt die Anwendung für die Freigabe des zugewiesenen Kontexts verantwortlich." -concepts.platforms.ownership.guidance: "Der gemeinsame {frameSchedulerCs} führt die Frame-Handler über den UI-Dispatcher der Ansicht aus. Beschränken Sie diese Handler auf Szenenaktualisierung und Befehlsaufzeichnung; aufwendige CPU-Arbeit verzögert dort auch die Benutzeroberfläche." -concepts.platforms.ownership.title: "Verantwortung von Anwendung und Steuerelement" -concepts.platforms.surface.description: "Das {link} verwendet Silk.NET für Fenstererstellung und Ereignisverarbeitung. Zenith.NET erhält die nativen Fensterhandles und Abmessungen in einer {surface}-Beschreibung und erstellt damit eine {swapChain}. Für das Betriebssystemfenster bleibt die Anwendung verantwortlich." -concepts.platforms.surface.description.link: "Dreieck-Tutorial" -concepts.platforms.surface.details: "Die nativen Handles müssen zum Backend passen:" -concepts.platforms.surface.guidance: "Der Beispielhost in {appCs} unterstützt Windows, macOS und X11. Unter Linux liefert sein Fenster Xlib-Handles; eine Wayland-Sitzung benötigt deshalb XWayland. Eine native Wayland-Anwendung übergibt Display- und Surface-Handles über {surfaceWayland}." +concepts.platforms.lifecycle.title: 'Swapchain-Abmessungen und Lebensdauer' +concepts.platforms.ownership.description: 'Die Anwendung besitzt den zugewiesenen Kontext und ihre Rendering-Ressourcen, das Steuerelement seine Präsentationsressourcen. Ändert sich {graphicsContext} der Ansicht, erstellt der Scheduler die Steuerelement-Ressourcen für den neuen Kontext neu. Auch die Anwendung muss ihre Pipelines, Puffer und Texturen für diesen Kontext neu erstellen.' +concepts.platforms.ownership.details: 'Halten Sie vor dem Ersetzen von Rendering-Ressourcen die Frame-Verarbeitung der Ansicht an und warten Sie auf die GPU-Arbeit, die diese Ressourcen verwendet. Erst danach dürfen die alten Ressourcen oder der Kontext freigegeben werden. Auch beim Entfernen der Ansicht bleibt die Anwendung für die Freigabe des zugewiesenen Kontexts verantwortlich.' +concepts.platforms.ownership.guidance: 'Der gemeinsame {frameSchedulerCs} führt die Frame-Handler über den UI-Dispatcher der Ansicht aus. Beschränken Sie diese Handler auf Szenenaktualisierung und Befehlsaufzeichnung; aufwendige CPU-Arbeit verzögert dort auch die Benutzeroberfläche.' +concepts.platforms.ownership.title: 'Verantwortung von Anwendung und Steuerelement' +concepts.platforms.surface.description: 'Das {link} verwendet Silk.NET für Fenstererstellung und Ereignisverarbeitung. Zenith.NET erhält die nativen Fensterhandles und Abmessungen in einer {surface}-Beschreibung und erstellt damit eine {swapChain}. Für das Betriebssystemfenster bleibt die Anwendung verantwortlich.' +concepts.platforms.surface.description.link: 'Dreieck-Tutorial' +concepts.platforms.surface.details: 'Die nativen Handles müssen zum Backend passen:' +concepts.platforms.surface.guidance: 'Der Beispielhost in {appCs} unterstützt Windows, macOS und X11. Unter Linux liefert sein Fenster Xlib-Handles; eine Wayland-Sitzung benötigt deshalb XWayland. Eine native Wayland-Anwendung übergibt Display- und Surface-Handles über {surfaceWayland}.' concepts.platforms.surface.table.android.backend: Vulkan unter Android. concepts.platforms.surface.table.apple.backend: Metal auf Apple-Plattformen. -concepts.platforms.surface.table.headings.backend: "Backend und Plattform" +concepts.platforms.surface.table.headings.backend: 'Backend und Plattform' concepts.platforms.surface.table.headings.factory: Oberflächen-Factory concepts.platforms.surface.table.headings.handles: Vom Host bereitgestellte Handles concepts.platforms.surface.table.wayland.backend: Vulkan mit einem nativen Wayland-Host. @@ -93,400 +93,400 @@ concepts.platforms.surface.table.wayland.handles: Wayland-Display und -Surface concepts.platforms.surface.table.win32.backend: DirectX 12 oder Vulkan unter Windows. concepts.platforms.surface.table.xlib.backend: Vulkan unter Linux mit X11 oder XWayland. concepts.platforms.surface.table.xlib.handles: X11-Display und -Fenster -concepts.platforms.surface.title: "Native Präsentationsziele" +concepts.platforms.surface.title: 'Native Präsentationsziele' concepts.platforms.title: Plattformintegration -concepts.resources.allocation.context: "Platzierte Ressourcen benötigen den Speicher ihres Heaps während ihrer gesamten Lebensdauer. Warten Sie auf ihre letzte GPU-Nutzung und geben Sie anschließend zuerst die Ressourcen und dann den Heap frei." -concepts.resources.allocation.description: "Verwenden Sie einen {heap}, wenn die Anwendung die Speicherzuteilung selbst verwalten soll. Ressourcen werden darin an expliziten Byte-Offsets platziert. Die Anwendung legt diese Offsets fest und verfolgt die belegten Bereiche." -concepts.resources.allocation.details: "Rufen Sie für jede Ressource {contextGetSizeAndAlignment} mit der Puffer- oder Texturbeschreibung auf, die auch für die Erstellung verwendet wird. Reservieren Sie die zurückgegebene Größe an einem Offset, der ein Vielfaches der angegebenen Ausrichtung ist. Die Allokation muss innerhalb des Heaps liegen und darf keine andere noch aktive Allokation überlappen. Texturgrößen können backendabhängige Auffüllungen enthalten und lassen sich deshalb nicht allein aus Pixelzahl und Bytes pro Pixel berechnen." -concepts.resources.allocation.guidance: "Ein in einem Heap platzierter Puffer muss dieselbe Residenz wie der Heap angeben. Verwenden Sie für Texturen einen Heap mit GPU-only-Residenz." -concepts.resources.allocation.title: "Heap-Allokation" +concepts.resources.allocation.context: 'Platzierte Ressourcen benötigen den Speicher ihres Heaps während ihrer gesamten Lebensdauer. Warten Sie auf ihre letzte GPU-Nutzung und geben Sie anschließend zuerst die Ressourcen und dann den Heap frei.' +concepts.resources.allocation.description: 'Verwenden Sie einen {heap}, wenn die Anwendung die Speicherzuteilung selbst verwalten soll. Ressourcen werden darin an expliziten Byte-Offsets platziert. Die Anwendung legt diese Offsets fest und verfolgt die belegten Bereiche.' +concepts.resources.allocation.details: 'Rufen Sie für jede Ressource {contextGetSizeAndAlignment} mit der Puffer- oder Texturbeschreibung auf, die auch für die Erstellung verwendet wird. Reservieren Sie die zurückgegebene Größe an einem Offset, der ein Vielfaches der angegebenen Ausrichtung ist. Die Allokation muss innerhalb des Heaps liegen und darf keine andere noch aktive Allokation überlappen. Texturgrößen können backendabhängige Auffüllungen enthalten und lassen sich deshalb nicht allein aus Pixelzahl und Bytes pro Pixel berechnen.' +concepts.resources.allocation.guidance: 'Ein in einem Heap platzierter Puffer muss dieselbe Residenz wie der Heap angeben. Verwenden Sie für Texturen einen Heap mit GPU-only-Residenz.' +concepts.resources.allocation.title: 'Heap-Allokation' concepts.resources.bufferUsages.table.constant.role: Shader-Parameter, die über eine Konstantenpuffer-Bindung gelesen werden. -concepts.resources.bufferUsages.table.headings.role: "Rolle" +concepts.resources.bufferUsages.table.headings.role: 'Rolle' concepts.resources.bufferUsages.table.headings.usage: Nutzung concepts.resources.bufferUsages.table.index.role: Indizes, die beim indexierten Zeichnen verwendet werden. -concepts.resources.bufferUsages.table.indirect.role: "Argumente, die indirekte Zeichen- oder Dispatch-Befehle lesen." -concepts.resources.bufferUsages.table.none.role: "Es sind keine Puffernutzungsflags deklariert." -concepts.resources.bufferUsages.table.storageReadOnly.role: "Pufferdaten, auf die über eine schreibgeschützte Shader-Bindung zugegriffen wird." -concepts.resources.bufferUsages.table.storageReadWrite.role: "Pufferdaten, auf die über eine Shader-Bindung mit Lese- und Schreibzugriff zugegriffen wird." -concepts.resources.bufferUsages.table.transferDst.role: "Zielspeicher für eine GPU-Kopie." -concepts.resources.bufferUsages.table.transferSrc.role: "Quelldaten für eine GPU-Kopie." -concepts.resources.bufferUsages.table.vertex.role: "Vertexattribute, die für das Zeichnen abgerufen werden." +concepts.resources.bufferUsages.table.indirect.role: 'Argumente, die indirekte Zeichen- oder Dispatch-Befehle lesen.' +concepts.resources.bufferUsages.table.none.role: 'Es sind keine Puffernutzungsflags deklariert.' +concepts.resources.bufferUsages.table.storageReadOnly.role: 'Pufferdaten, auf die über eine schreibgeschützte Shader-Bindung zugegriffen wird.' +concepts.resources.bufferUsages.table.storageReadWrite.role: 'Pufferdaten, auf die über eine Shader-Bindung mit Lese- und Schreibzugriff zugegriffen wird.' +concepts.resources.bufferUsages.table.transferDst.role: 'Zielspeicher für eine GPU-Kopie.' +concepts.resources.bufferUsages.table.transferSrc.role: 'Quelldaten für eine GPU-Kopie.' +concepts.resources.bufferUsages.table.vertex.role: 'Vertexattribute, die für das Zeichnen abgerufen werden.' concepts.resources.bufferUsages.title: Puffernutzungen -concepts.resources.description: "Die Ressourcenbeschreibung legt fest, wie die Anwendung den Speicher verwenden darf. Soll eine Textur als Renderziel dienen, im Shader abgetastet und zur CPU zurückgelesen werden, benötigt sie die Nutzungsflags für alle drei Vorgänge. Die Speicherplatzierung bestimmt den CPU-Zugriff. Synchronisation und Lebensdauerverwaltung bestimmen dagegen, wann Daten zugänglich sind und Speicher freigegeben werden darf." -concepts.resources.memory.context: "Bei CPU-zugänglichen Puffern liefert {map} die Adresse zum Lesen oder Schreiben der Daten. Weder das Mapping noch {unmap} wartet auf GPU-Arbeit. Vor dem Lesen eines GPU-Ergebnisses muss die Anwendung auf den Schreibvorgang warten. Bevor sie dieselben Bytes verändert, muss sie alle noch ausstehenden GPU-Zugriffe darauf abwarten." -concepts.resources.memory.description: "Das Feld {residency} von {bufferDesc} beschreibt den vorgesehenen CPU-Zugriff auf die Allokation:" -concepts.resources.memory.details: "Die Residenz beschreibt den benötigten CPU-Zugriff, auch auf Systemen mit gemeinsamem physischem CPU- und GPU-Speicher. Das Dreieck verwendet {cpuWriteOnly}, um seinen kleinen Vertexpuffer direkt zu initialisieren. Für größere statische Geometrie kann ein Upload in GPU-only-Speicher geeigneter sein." -concepts.resources.memory.guidance: "Direkt über den Kontext erstellte Texturen verwenden GPU-Speicher. {textureDesc} enthält deshalb kein Residenzfeld; Daten werden über Uploads und Downloads mit dem CPU-Speicher ausgetauscht." -concepts.resources.memory.table.cpuReadOnly.cPUAccess: "Nur Lesen" -concepts.resources.memory.table.cpuReadOnly.typicalRole: "Von der GPU erzeugte Rücklesedaten" -concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "Nur Schreiben" -concepts.resources.memory.table.cpuWriteOnly.typicalRole: "Von der CPU bereitgestellte oder aktualisierte Daten" -concepts.resources.memory.table.gpuOnly.cPUAccess: "Keiner" -concepts.resources.memory.table.gpuOnly.typicalRole: "Statische Geometrie und GPU-Arbeitsdaten" -concepts.resources.memory.table.headings.cPUAccess: "Vorgesehener CPU-Zugriff" +concepts.resources.description: 'Die Ressourcenbeschreibung legt fest, wie die Anwendung den Speicher verwenden darf. Soll eine Textur als Renderziel dienen, im Shader abgetastet und zur CPU zurückgelesen werden, benötigt sie die Nutzungsflags für alle drei Vorgänge. Die Speicherplatzierung bestimmt den CPU-Zugriff. Synchronisation und Lebensdauerverwaltung bestimmen dagegen, wann Daten zugänglich sind und Speicher freigegeben werden darf.' +concepts.resources.memory.context: 'Bei CPU-zugänglichen Puffern liefert {map} die Adresse zum Lesen oder Schreiben der Daten. Weder das Mapping noch {unmap} wartet auf GPU-Arbeit. Vor dem Lesen eines GPU-Ergebnisses muss die Anwendung auf den Schreibvorgang warten. Bevor sie dieselben Bytes verändert, muss sie alle noch ausstehenden GPU-Zugriffe darauf abwarten.' +concepts.resources.memory.description: 'Das Feld {residency} von {bufferDesc} beschreibt den vorgesehenen CPU-Zugriff auf die Allokation:' +concepts.resources.memory.details: 'Die Residenz beschreibt den benötigten CPU-Zugriff, auch auf Systemen mit gemeinsamem physischem CPU- und GPU-Speicher. Das Dreieck verwendet {cpuWriteOnly}, um seinen kleinen Vertexpuffer direkt zu initialisieren. Für größere statische Geometrie kann ein Upload in GPU-only-Speicher geeigneter sein.' +concepts.resources.memory.guidance: 'Direkt über den Kontext erstellte Texturen verwenden GPU-Speicher. {textureDesc} enthält deshalb kein Residenzfeld; Daten werden über Uploads und Downloads mit dem CPU-Speicher ausgetauscht.' +concepts.resources.memory.table.cpuReadOnly.cPUAccess: 'Nur Lesen' +concepts.resources.memory.table.cpuReadOnly.typicalRole: 'Von der GPU erzeugte Rücklesedaten' +concepts.resources.memory.table.cpuWriteOnly.cPUAccess: 'Nur Schreiben' +concepts.resources.memory.table.cpuWriteOnly.typicalRole: 'Von der CPU bereitgestellte oder aktualisierte Daten' +concepts.resources.memory.table.gpuOnly.cPUAccess: 'Keiner' +concepts.resources.memory.table.gpuOnly.typicalRole: 'Statische Geometrie und GPU-Arbeitsdaten' +concepts.resources.memory.table.headings.cPUAccess: 'Vorgesehener CPU-Zugriff' concepts.resources.memory.table.headings.residency: Residenz concepts.resources.memory.table.headings.typicalRole: Typische Rolle -concepts.resources.memory.title: "CPU-Zugriff und Speicherplatzierung" -concepts.resources.textureUsages.description: "Transferflags geben an, ob eine Ressource als Quelle oder Ziel einer GPU-Kopie dient. Ob die CPU direkt auf ihren Speicher zugreifen kann, wird unabhängig davon durch die Speicherplatzierung festgelegt." -concepts.resources.textureUsages.details: "Nutzungsflags geben die vorgesehenen Rollen einer Textur an. Für den Wechsel zwischen diesen Rollen gelten die unter {link} beschriebenen Anforderungen. Außerdem muss das Gerät die gewählten Verwendungszwecke für das Texturformat unterstützen." -concepts.resources.textureUsages.details.link: "Layout und Synchronisation" -concepts.resources.textureUsages.table.colorAttachment.role: "Ein Farb-Attachment in einem Renderpass." -concepts.resources.textureUsages.table.depthStencilAttachment.role: "Ein Tiefen-/Stencil-Attachment in einem Renderpass." -concepts.resources.textureUsages.table.headings.role: "Rolle" +concepts.resources.memory.title: 'CPU-Zugriff und Speicherplatzierung' +concepts.resources.textureUsages.description: 'Transferflags geben an, ob eine Ressource als Quelle oder Ziel einer GPU-Kopie dient. Ob die CPU direkt auf ihren Speicher zugreifen kann, wird unabhängig davon durch die Speicherplatzierung festgelegt.' +concepts.resources.textureUsages.details: 'Nutzungsflags geben die vorgesehenen Rollen einer Textur an. Für den Wechsel zwischen diesen Rollen gelten die unter {link} beschriebenen Anforderungen. Außerdem muss das Gerät die gewählten Verwendungszwecke für das Texturformat unterstützen.' +concepts.resources.textureUsages.details.link: 'Layout und Synchronisation' +concepts.resources.textureUsages.table.colorAttachment.role: 'Ein Farb-Attachment in einem Renderpass.' +concepts.resources.textureUsages.table.depthStencilAttachment.role: 'Ein Tiefen-/Stencil-Attachment in einem Renderpass.' +concepts.resources.textureUsages.table.headings.role: 'Rolle' concepts.resources.textureUsages.table.headings.usage: Nutzung -concepts.resources.textureUsages.table.none.role: "Es sind keine Texturnutzungsflags deklariert." -concepts.resources.textureUsages.table.sampled.role: "Texturdaten, die über eine Bindung für abgetastete Texturen gelesen werden." -concepts.resources.textureUsages.table.storage.role: "Texturdaten, auf die Shader über eine Storage-Textur-Bindung lesend oder schreibend zugreifen." -concepts.resources.textureUsages.table.transferDst.role: "Zielbildspeicher für eine GPU-Kopie." -concepts.resources.textureUsages.table.transferSrc.role: "Quellbilddaten für eine GPU-Kopie." +concepts.resources.textureUsages.table.none.role: 'Es sind keine Texturnutzungsflags deklariert.' +concepts.resources.textureUsages.table.sampled.role: 'Texturdaten, die über eine Bindung für abgetastete Texturen gelesen werden.' +concepts.resources.textureUsages.table.storage.role: 'Texturdaten, auf die Shader über eine Storage-Textur-Bindung lesend oder schreibend zugreifen.' +concepts.resources.textureUsages.table.transferDst.role: 'Zielbildspeicher für eine GPU-Kopie.' +concepts.resources.textureUsages.table.transferSrc.role: 'Quellbilddaten für eine GPU-Kopie.' concepts.resources.textureUsages.title: Texturnutzungen concepts.resources.title: Ressourcenverwaltung -concepts.resources.transfers.context: "Ein Download kopiert GPU-Daten zunächst in einen internen Rücklesespeicher. Wenn die Bibliothek den abgeschlossenen Befehlspuffer zur Wiederverwendung zurücknimmt, kopiert sie die Daten an das bereitgestellte CPU-Ziel. Ein Aufruf von {wait} auf dem Abschlusswert der Download-Einreichung beendet beide Schritte. Bis zur Rückkehr muss der Zielspeicher erhalten und verwalteter Speicher fixiert bleiben." -concepts.resources.transfers.description: "Uploads kopieren CPU-Daten in eine GPU-Ressource, Downloads kopieren Ressourcendaten in CPU-Speicher. Die Methoden auf Puffern und Texturen schließen diesen Transfer vor ihrer Rückkehr ab:" -concepts.resources.transfers.details: "Stellen Sie vor diesen Aufrufen die erforderlichen Abhängigkeiten zu Zugriffen auf anderen Warteschlangen her. Eine Warteoperation innerhalb der Methode deckt nur ihren eigenen Transfer ab; sie stellt keine Abhängigkeit zu einer anderen Warteschlange her. Bei direktem Zugriff auf gemappten Speicher muss der Aufrufer selbst auf GPU-Zugriffe warten, die mit dem Transfer in Konflikt stehen." -concepts.resources.transfers.guidance: "Mit {commandBufferUpload} oder {commandBufferDownload} lassen sich Transfers zusammen mit anderer GPU-Arbeit aufzeichnen und einreichen. Für den Quellspeicher eines Uploads und den Zielspeicher eines Downloads gelten unterschiedliche Anforderungen an die Lebensdauer:" -concepts.resources.transfers.item: "Während des Upload-Aufrufs kopiert die Bibliothek die Quelldaten in einen temporären Upload-Speicher, den Staging-Speicher. Die GPU liest später aus diesem Zwischenspeicher. Der Quellzeiger der Anwendung wird deshalb nur bis zur Rückkehr des Aufrufs benötigt." -concepts.resources.transfers.notes: "Bei Texturtransfers bezeichnet der Zeilen-Stride den Byte-Abstand zwischen aufeinanderfolgenden Zeilen der CPU-Daten, der Schicht-Stride den Abstand zwischen Tiefenschichten. Mithilfe dieser Werte kopiert der Transfer Daten zwischen CPU-Speicher und GPU-Textur. Warum GPU-Abschluss und Bereitstellung am Download-Ziel getrennte Schritte sind, erläutert {link}." +concepts.resources.transfers.context: 'Ein Download kopiert GPU-Daten zunächst in einen internen Rücklesespeicher. Wenn die Bibliothek den abgeschlossenen Befehlspuffer zur Wiederverwendung zurücknimmt, kopiert sie die Daten an das bereitgestellte CPU-Ziel. Ein Aufruf von {wait} auf dem Abschlusswert der Download-Einreichung beendet beide Schritte. Bis zur Rückkehr muss der Zielspeicher erhalten und verwalteter Speicher fixiert bleiben.' +concepts.resources.transfers.description: 'Uploads kopieren CPU-Daten in eine GPU-Ressource, Downloads kopieren Ressourcendaten in CPU-Speicher. Die Methoden auf Puffern und Texturen schließen diesen Transfer vor ihrer Rückkehr ab:' +concepts.resources.transfers.details: 'Stellen Sie vor diesen Aufrufen die erforderlichen Abhängigkeiten zu Zugriffen auf anderen Warteschlangen her. Eine Warteoperation innerhalb der Methode deckt nur ihren eigenen Transfer ab; sie stellt keine Abhängigkeit zu einer anderen Warteschlange her. Bei direktem Zugriff auf gemappten Speicher muss der Aufrufer selbst auf GPU-Zugriffe warten, die mit dem Transfer in Konflikt stehen.' +concepts.resources.transfers.guidance: 'Mit {commandBufferUpload} oder {commandBufferDownload} lassen sich Transfers zusammen mit anderer GPU-Arbeit aufzeichnen und einreichen. Für den Quellspeicher eines Uploads und den Zielspeicher eines Downloads gelten unterschiedliche Anforderungen an die Lebensdauer:' +concepts.resources.transfers.item: 'Während des Upload-Aufrufs kopiert die Bibliothek die Quelldaten in einen temporären Upload-Speicher, den Staging-Speicher. Die GPU liest später aus diesem Zwischenspeicher. Der Quellzeiger der Anwendung wird deshalb nur bis zur Rückkehr des Aufrufs benötigt.' +concepts.resources.transfers.notes: 'Bei Texturtransfers bezeichnet der Zeilen-Stride den Byte-Abstand zwischen aufeinanderfolgenden Zeilen der CPU-Daten, der Schicht-Stride den Abstand zwischen Tiefenschichten. Mithilfe dieser Werte kopiert der Transfer Daten zwischen CPU-Speicher und GPU-Textur. Warum GPU-Abschluss und Bereitstellung am Download-Ziel getrennte Schritte sind, erläutert {link}.' concepts.resources.transfers.notes.link: Synchronisation -concepts.resources.transfers.table.bufferDownload.transfer: "Kopiert bei {cpuReadOnly} direkt aus dem gemappten Speicher. Andernfalls reicht die Methode den Download bei der Transferwarteschlange ein und wartet auf dessen Abschluss." -concepts.resources.transfers.table.bufferUpload.transfer: "Kopiert bei {cpuWriteOnly} direkt in den gemappten Speicher. Andernfalls reicht die Methode den Upload bei der Transferwarteschlange ein und wartet auf dessen Abschluss." +concepts.resources.transfers.table.bufferDownload.transfer: 'Kopiert bei {cpuReadOnly} direkt aus dem gemappten Speicher. Andernfalls reicht die Methode den Download bei der Transferwarteschlange ein und wartet auf dessen Abschluss.' +concepts.resources.transfers.table.bufferUpload.transfer: 'Kopiert bei {cpuWriteOnly} direkt in den gemappten Speicher. Andernfalls reicht die Methode den Upload bei der Transferwarteschlange ein und wartet auf dessen Abschluss.' concepts.resources.transfers.table.headings.method: Methode -concepts.resources.transfers.table.headings.transfer: "Übertragungsverhalten" -concepts.resources.transfers.table.textureTransfers.method: "{textureUpload} / {textureDownload}" -concepts.resources.transfers.table.textureTransfers.transfer: "Reicht die Kopie und ihre Texturübergänge bei der Grafikwarteschlange ein und wartet auf den Abschluss. Die ausgewählte Unterressource bleibt im angeforderten abschließenden Layout." -concepts.resources.transfers.title: "Sofortige und aufgezeichnete Übertragungen" -concepts.resources.usages.description: "{bufferUsages} und {textureUsages} sind Flag-Enums für die vorgesehenen Ressourcenrollen. Sie werden {bufferDescUsages} beziehungsweise {textureDescUsages} zugewiesen. Für mehrere Rollen lassen sich die benötigten Member mit {value} kombinieren." -concepts.resources.usages.title: "Ressourcennutzungen" -concepts.resources.views.description: "Eine {bufferView} beschreibt einen Pufferbereich und die Interpretation seiner Daten. Eine {textureView} wählt einen Unterressourcenbereich sowie einen kompatiblen Texturtyp und ein passendes Format. Beide beziehen sich auf vorhandenen Speicher mit den bei seiner Erstellung angegebenen Nutzungen. Ansichtsbereiche beschreiben den Zugriff, gewährleisten aber keine einheitliche shaderseitige Bereichsprüfung über alle Backends hinweg." -concepts.resources.views.details: "Der eigene Handle einer Ressource stellt ihre Standardansicht bereit. Erstellen Sie eine separate Ansicht, wenn ein anderer Bereich oder eine andere kompatible Interpretation benötigt wird. Ansicht und zugrunde liegende Ressource müssen bis zum Ende ihrer GPU-Nutzung erhalten bleiben; ein Ressourcenhandle hält keines dieser Objekte am Leben. Wird eines ersetzt, aktualisieren Sie alle Konstanten mit dem bisherigen {link}." -concepts.resources.views.details.link: "Ressourcenhandle" -concepts.resources.views.title: "Ansichten und zugrunde liegende Ressourcen" -concepts.shaders.binding.context: "Im Compute-Beispiel erhält {input} den Wert {inputTextureSampledHandle} und {output} den Wert {outputTextureStorageHandle}. In Slang bestimmt der Typparameter von {descriptorHandle} den Ressourcenzugriff:" -concepts.shaders.binding.description: "{setConstantBuffer} wählt einen vorhandenen Puffer und den Byte-Offset, ab dem die aktuelle Pipeline ihre Konstanten liest. Laden Sie die Parameterdaten in diesen Speicher, bevor der Shader darauf zugreift. Liest frühere GPU-Arbeit noch dieselben Bytes, muss sie vor der Aktualisierung abgeschlossen sein." -concepts.shaders.binding.details: "Der Befehlspuffer, die Compute-Pipeline, der mit Daten gefüllte Konstantenpuffer und die Anzahl der Threadgruppen müssen bereits vorliegen. Zeichnen Sie den Dispatch dann in dieser Reihenfolge auf. Wählen Sie zuerst die Pipeline, da die Konstantenpufferbindung für diese Pipeline gilt:" -concepts.shaders.binding.guidance: "Hier zeichnet {commandBuffer} einen Dispatch mit {computePipeline} und den Parametern aus {constantBuffer} auf. Der Puffer benötigt die Nutzung {bufferUsagesConstant}; Offset 0 wählt seinen Anfang. Teilen sich mehrere Konstantendatensätze einen Puffer, muss jeder Anfangsoffset zusätzlich die Bindungsausrichtung des Backends erfüllen. Diese Anforderung gilt unabhängig von der Feldanordnung innerhalb des Datensatzes." -concepts.shaders.binding.notes: "{resourceHandle} enthält zwei 32-Bit-Felder, deren Interpretation vom Backend abhängt. Die Werte gelten nur innerhalb des Kontexts, in dem die Ressource erstellt wurde." -concepts.shaders.binding.reference: "Ressource und zugehörige Ansicht müssen bis zum Abschluss des letzten Shader-Zugriffs erhalten bleiben. Ihr Ersatz erfordert eine Aktualisierung der Konstanten mit alten Handles. Die Besitzregeln erläutert {link}." +concepts.resources.transfers.table.headings.transfer: 'Übertragungsverhalten' +concepts.resources.transfers.table.textureTransfers.method: '{textureUpload} / {textureDownload}' +concepts.resources.transfers.table.textureTransfers.transfer: 'Reicht die Kopie und ihre Texturübergänge bei der Grafikwarteschlange ein und wartet auf den Abschluss. Die ausgewählte Unterressource bleibt im angeforderten abschließenden Layout.' +concepts.resources.transfers.title: 'Sofortige und aufgezeichnete Übertragungen' +concepts.resources.usages.description: '{bufferUsages} und {textureUsages} sind Flag-Enums für die vorgesehenen Ressourcenrollen. Sie werden {bufferDescUsages} beziehungsweise {textureDescUsages} zugewiesen. Für mehrere Rollen lassen sich die benötigten Member mit {value} kombinieren.' +concepts.resources.usages.title: 'Ressourcennutzungen' +concepts.resources.views.description: 'Eine {bufferView} beschreibt einen Pufferbereich und die Interpretation seiner Daten. Eine {textureView} wählt einen Unterressourcenbereich sowie einen kompatiblen Texturtyp und ein passendes Format. Beide beziehen sich auf vorhandenen Speicher mit den bei seiner Erstellung angegebenen Nutzungen. Ansichtsbereiche beschreiben den Zugriff, gewährleisten aber keine einheitliche shaderseitige Bereichsprüfung über alle Backends hinweg.' +concepts.resources.views.details: 'Der eigene Handle einer Ressource stellt ihre Standardansicht bereit. Erstellen Sie eine separate Ansicht, wenn ein anderer Bereich oder eine andere kompatible Interpretation benötigt wird. Ansicht und zugrunde liegende Ressource müssen bis zum Ende ihrer GPU-Nutzung erhalten bleiben; ein Ressourcenhandle hält keines dieser Objekte am Leben. Wird eines ersetzt, aktualisieren Sie alle Konstanten mit dem bisherigen {link}.' +concepts.resources.views.details.link: 'Ressourcenhandle' +concepts.resources.views.title: 'Ansichten und zugrunde liegende Ressourcen' +concepts.shaders.binding.context: 'Im Compute-Beispiel erhält {input} den Wert {inputTextureSampledHandle} und {output} den Wert {outputTextureStorageHandle}. In Slang bestimmt der Typparameter von {descriptorHandle} den Ressourcenzugriff:' +concepts.shaders.binding.description: '{setConstantBuffer} wählt einen vorhandenen Puffer und den Byte-Offset, ab dem die aktuelle Pipeline ihre Konstanten liest. Laden Sie die Parameterdaten in diesen Speicher, bevor der Shader darauf zugreift. Liest frühere GPU-Arbeit noch dieselben Bytes, muss sie vor der Aktualisierung abgeschlossen sein.' +concepts.shaders.binding.details: 'Der Befehlspuffer, die Compute-Pipeline, der mit Daten gefüllte Konstantenpuffer und die Anzahl der Threadgruppen müssen bereits vorliegen. Zeichnen Sie den Dispatch dann in dieser Reihenfolge auf. Wählen Sie zuerst die Pipeline, da die Konstantenpufferbindung für diese Pipeline gilt:' +concepts.shaders.binding.guidance: 'Hier zeichnet {commandBuffer} einen Dispatch mit {computePipeline} und den Parametern aus {constantBuffer} auf. Der Puffer benötigt die Nutzung {bufferUsagesConstant}; Offset 0 wählt seinen Anfang. Teilen sich mehrere Konstantendatensätze einen Puffer, muss jeder Anfangsoffset zusätzlich die Bindungsausrichtung des Backends erfüllen. Diese Anforderung gilt unabhängig von der Feldanordnung innerhalb des Datensatzes.' +concepts.shaders.binding.notes: '{resourceHandle} enthält zwei 32-Bit-Felder, deren Interpretation vom Backend abhängt. Die Werte gelten nur innerhalb des Kontexts, in dem die Ressource erstellt wurde.' +concepts.shaders.binding.reference: 'Ressource und zugehörige Ansicht müssen bis zum Abschluss des letzten Shader-Zugriffs erhalten bleiben. Ihr Ersatz erfordert eine Aktualisierung der Konstanten mit alten Handles. Die Besitzregeln erläutert {link}.' concepts.shaders.binding.reference.link: Ressourcenverwaltung -concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: "Lesen strukturierter Elemente des im Shader verwendeten Datentyps {t}" -concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: "Lesen und Schreiben strukturierter Elemente des im Shader verwendeten Datentyps {t}" +concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: 'Lesen strukturierter Elemente des im Shader verwendeten Datentyps {t}' +concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: 'Lesen und Schreiben strukturierter Elemente des im Shader verwendeten Datentyps {t}' concepts.shaders.binding.table.headings.access: Beabsichtigter Zugriff -concepts.shaders.binding.table.headings.cHandle: "C#-Handle" +concepts.shaders.binding.table.headings.cHandle: 'C#-Handle' concepts.shaders.binding.table.headings.slangFieldType: Slang-Feldtyp -concepts.shaders.binding.table.samplerHandle.access: "Zustand für die Texturabtastung" -concepts.shaders.binding.table.textureSampledHandle.access: "Lesen von Texturdaten" -concepts.shaders.binding.table.textureStorageHandle.access: "Lese- und Schreibzugriff auf Speichertexturen" -concepts.shaders.binding.title: "Konstantenpuffer und Ressourcenhandles" -concepts.shaders.compilation.description: "{zenithCompiler} kompiliert einen benannten Slang-Einstiegspunkt zu einer {shaderDesc}. Die Eigenschaft {graphicsApi} bestimmt das Ziel: DXIL für DirectX 12, eine Metal-Bibliothek für Metal oder SPIR-V für Vulkan." -concepts.shaders.compilation.details: "Mit einem bereits erstellten Grafikkontext namens {context} wird der Dreieck-Shader aus der Kopie neben der ausführbaren Datei kompiliert:" -concepts.shaders.compilation.guidance: "Der Einstiegspunktname {vSMain} muss mit der Deklaration in der Shader-Datei übereinstimmen. Kompilieren Sie Shader und erstellen Sie Pipelines während der Initialisierung; beim Rendering werden die Pipelines wiederverwendet. Nach Abschluss der Pipeline-Erstellung dürfen die Shader-Objekte freigegeben werden, wie im Tutorial {link} gezeigt." +concepts.shaders.binding.table.samplerHandle.access: 'Zustand für die Texturabtastung' +concepts.shaders.binding.table.textureSampledHandle.access: 'Lesen von Texturdaten' +concepts.shaders.binding.table.textureStorageHandle.access: 'Lese- und Schreibzugriff auf Speichertexturen' +concepts.shaders.binding.title: 'Konstantenpuffer und Ressourcenhandles' +concepts.shaders.compilation.description: '{zenithCompiler} kompiliert einen benannten Slang-Einstiegspunkt zu einer {shaderDesc}. Die Eigenschaft {graphicsApi} bestimmt das Ziel: DXIL für DirectX 12, eine Metal-Bibliothek für Metal oder SPIR-V für Vulkan.' +concepts.shaders.compilation.details: 'Mit einem bereits erstellten Grafikkontext namens {context} wird der Dreieck-Shader aus der Kopie neben der ausführbaren Datei kompiliert:' +concepts.shaders.compilation.guidance: 'Der Einstiegspunktname {vSMain} muss mit der Deklaration in der Shader-Datei übereinstimmen. Kompilieren Sie Shader und erstellen Sie Pipelines während der Initialisierung; beim Rendering werden die Pipelines wiederverwendet. Nach Abschluss der Pipeline-Erstellung dürfen die Shader-Objekte freigegeben werden, wie im Tutorial {link} gezeigt.' concepts.shaders.compilation.guidance.link: Erstes Dreieck -concepts.shaders.compilation.title: "Shader-Kompilierung" -concepts.shaders.description: "C#- und Slang-Deklarationen müssen darin übereinstimmen, wo Werte gespeichert werden und wie der Shader darauf zugreift. Vertex-Eingabelayouts beschreiben Vertexattribute, Shader-Pufferdeklarationen beschreiben Parameter und Arrays, und Ressourcenhandles identifizieren die vom Shader verwendeten Ressourcen." -concepts.shaders.dispatch.description: "{dispatch} gibt die Anzahl der auszuführenden Threadgruppen an. Das Compute-Beispiel deklariert {numthreads}, sodass jede Gruppe 16 × 16 Threads enthält. Teilen Sie Breite und Höhe des Bildes jeweils durch 16 und runden Sie auf, um es vollständig abzudecken: Ein Bild mit 17 × 19 Pixeln benötigt 2 × 2 Gruppen. Der Shader prüft die Koordinaten jedes Threads und überspringt Positionen außerhalb des Bildes." -concepts.shaders.dispatch.details: "Die deklarierte Gruppengröße ist über {shaderDescThreadGroupSize} verfügbar und kann zur Berechnung der an {dispatch} übergebenen Gruppenanzahl dienen. {computeShaderRendererCs} zeigt die vollständige Berechnung. Für Zugriffe auf das erzeugte Bild gelten anschließend die in {link} beschriebenen Anforderungen." +concepts.shaders.compilation.title: 'Shader-Kompilierung' +concepts.shaders.description: 'C#- und Slang-Deklarationen müssen darin übereinstimmen, wo Werte gespeichert werden und wie der Shader darauf zugreift. Vertex-Eingabelayouts beschreiben Vertexattribute, Shader-Pufferdeklarationen beschreiben Parameter und Arrays, und Ressourcenhandles identifizieren die vom Shader verwendeten Ressourcen.' +concepts.shaders.dispatch.description: '{dispatch} gibt die Anzahl der auszuführenden Threadgruppen an. Das Compute-Beispiel deklariert {numthreads}, sodass jede Gruppe 16 × 16 Threads enthält. Teilen Sie Breite und Höhe des Bildes jeweils durch 16 und runden Sie auf, um es vollständig abzudecken: Ein Bild mit 17 × 19 Pixeln benötigt 2 × 2 Gruppen. Der Shader prüft die Koordinaten jedes Threads und überspringt Positionen außerhalb des Bildes.' +concepts.shaders.dispatch.details: 'Die deklarierte Gruppengröße ist über {shaderDescThreadGroupSize} verfügbar und kann zur Berechnung der an {dispatch} übergebenen Gruppenanzahl dienen. {computeShaderRendererCs} zeigt die vollständige Berechnung. Für Zugriffe auf das erzeugte Bild gelten anschließend die in {link} beschriebenen Anforderungen.' concepts.shaders.dispatch.details.link: Synchronisation -concepts.shaders.dispatch.title: "Threadgruppen" -concepts.shaders.layout.context: "Die {link} zeigen diese Anordnung anhand von Bildabmessungen und zwei Texturhandles. Explizite Offsets legen den Beginn jedes Feldes fest. Die Deklaration verwendet {systemRuntimeInteropServices} und {zenithNET}:" -concepts.shaders.layout.context.link: "C#-Konstanten des Compute-Beispiels" -concepts.shaders.layout.description: "Für Vertexeingaben beschreibt {inputLayout} das Format, den Offset und die Semantik jedes Attributs sowie den Stride zwischen Vertices. Beim Dreieck folgt auf eine {float3}-Position eine {float4}-Farbe. Die Farbe beginnt am Byte-Offset 12; jeder Vertex belegt 28 Bytes. {inputLayoutAdd} berechnet diese dicht gepackte Anordnung aus den Elementformaten. Enthält die C#-Struktur Auffüllungen, müssen Offsets und Stride diese berücksichtigen." -concepts.shaders.layout.details: "Konstantenpuffer enthalten Shader-Parameter, strukturierte Puffer Arrays typisierter Elemente. Ihre Anordnung folgt den Slang-Deklarationen und nicht {inputLayout}. Stimmen Sie C#-Feldoffsets, Elementgrößen und Auffüllungen mit dem kompilierten Shader-Layout ab. Ein nicht verwalteter C#-Typ lässt sich als Bytes kopieren, doch seine Speicheranordnung entspricht nicht zwangsläufig dem Shader-Layout. Ein im Vertex dicht gepacktes {float3} kann in einem Shader-Puffer eine andere Ausrichtung benötigen." -concepts.shaders.layout.guidance: "Shader-Parameter können neben gewöhnlichen Werten auch Ressourcenhandles enthalten. Ein Handle bezeichnet bereits vorhandenen Speicher. Wird er in einen Konstantenpuffer kopiert, werden deshalb nicht die Inhalte der Ressource mitkopiert." -concepts.shaders.layout.notes: "Die zugehörige Deklaration in {computeShaderSlang} lautet:" -concepts.shaders.layout.reference: "Die beiden Abmessungen belegen die ersten acht Bytes; darauf folgen zwei Handles mit je acht Bytes. Das C#-Beispiel reserviert insgesamt 256 Bytes für den Datensatz. Die Größe anderer Datensätze ist anhand ihrer eigenen Felder sowie der benötigten Anordnung und Ausrichtung zu bestimmen." -concepts.shaders.layout.title: "Datenlayout" -concepts.shaders.matrices.description: "Der Compiler wählt zeilenweise Matrixspeicherung mit zusammenhängenden Zeilen. Der {link} speichert drei {matrix4x4}-Werte an den Byte-Offsets 0, 64 und 128. Sein {detail} führt {mulVectorMatrix} in Modell-, View- und Projektionsreihenfolge aus." +concepts.shaders.dispatch.title: 'Threadgruppen' +concepts.shaders.layout.context: 'Die {link} zeigen diese Anordnung anhand von Bildabmessungen und zwei Texturhandles. Explizite Offsets legen den Beginn jedes Feldes fest. Die Deklaration verwendet {systemRuntimeInteropServices} und {zenithNET}:' +concepts.shaders.layout.context.link: 'C#-Konstanten des Compute-Beispiels' +concepts.shaders.layout.description: 'Für Vertexeingaben beschreibt {inputLayout} das Format, den Offset und die Semantik jedes Attributs sowie den Stride zwischen Vertices. Beim Dreieck folgt auf eine {float3}-Position eine {float4}-Farbe. Die Farbe beginnt am Byte-Offset 12; jeder Vertex belegt 28 Bytes. {inputLayoutAdd} berechnet diese dicht gepackte Anordnung aus den Elementformaten. Enthält die C#-Struktur Auffüllungen, müssen Offsets und Stride diese berücksichtigen.' +concepts.shaders.layout.details: 'Konstantenpuffer enthalten Shader-Parameter, strukturierte Puffer Arrays typisierter Elemente. Ihre Anordnung folgt den Slang-Deklarationen und nicht {inputLayout}. Stimmen Sie C#-Feldoffsets, Elementgrößen und Auffüllungen mit dem kompilierten Shader-Layout ab. Ein nicht verwalteter C#-Typ lässt sich als Bytes kopieren, doch seine Speicheranordnung entspricht nicht zwangsläufig dem Shader-Layout. Ein im Vertex dicht gepacktes {float3} kann in einem Shader-Puffer eine andere Ausrichtung benötigen.' +concepts.shaders.layout.guidance: 'Shader-Parameter können neben gewöhnlichen Werten auch Ressourcenhandles enthalten. Ein Handle bezeichnet bereits vorhandenen Speicher. Wird er in einen Konstantenpuffer kopiert, werden deshalb nicht die Inhalte der Ressource mitkopiert.' +concepts.shaders.layout.notes: 'Die zugehörige Deklaration in {computeShaderSlang} lautet:' +concepts.shaders.layout.reference: 'Die beiden Abmessungen belegen die ersten acht Bytes; darauf folgen zwei Handles mit je acht Bytes. Das C#-Beispiel reserviert insgesamt 256 Bytes für den Datensatz. Die Größe anderer Datensätze ist anhand ihrer eigenen Felder sowie der benötigten Anordnung und Ausrichtung zu bestimmen.' +concepts.shaders.layout.title: 'Datenlayout' +concepts.shaders.matrices.description: 'Der Compiler wählt zeilenweise Matrixspeicherung mit zusammenhängenden Zeilen. Der {link} speichert drei {matrix4x4}-Werte an den Byte-Offsets 0, 64 und 128. Sein {detail} führt {mulVectorMatrix} in Modell-, View- und Projektionsreihenfolge aus.' concepts.shaders.matrices.description.detail: Shader concepts.shaders.matrices.description.link: Renderer des rotierenden Würfels -concepts.shaders.matrices.details: "Die Speicherreihenfolge bestimmt die Anordnung der Matrixelemente; die Multiplikationsreihenfolge bestimmt die Transformation. C# und Slang müssen aufeinander abgestimmte Konventionen verwenden." -concepts.shaders.matrices.title: "Matrixkonventionen" +concepts.shaders.matrices.details: 'Die Speicherreihenfolge bestimmt die Anordnung der Matrixelemente; die Multiplikationsreihenfolge bestimmt die Transformation. C# und Slang müssen aufeinander abgestimmte Konventionen verwenden.' +concepts.shaders.matrices.title: 'Matrixkonventionen' concepts.shaders.title: Shader-Daten und Bindung -concepts.synchronization.backends.description: "DirectX 12 und Vulkan setzen Texturübergänge als Layout- und Zugriffsänderungen um. Für Metal führt die Implementierung von {transition} in Zenith.NET keine entsprechende Operation aus. Das Metal-Backend fasst Befehle stattdessen in Render- und Compute-Encodern zusammen und fügt beim Ende eines Encoders Sichtbarkeitsbarrieren ein. Abhängige Operationen innerhalb desselben Encoders, etwa aufeinanderfolgende Compute-Dispatches, verwenden explizite Aufrufe von {barrier}." -concepts.synchronization.backends.details: "Im {link} beendet der Beginn des Grafik-Renderpasses den Compute-Encoder und macht dessen Ausgabe für die Grafikbefehle sichtbar. Zwei aufeinanderfolgende Compute-Dispatches bleiben dagegen im selben Encoder. Ihre Abhängigkeit benötigt deshalb eine Barriere, auch wenn dazwischen ein Texturübergang aufgezeichnet wird. Portable Befehlsfolgen berücksichtigen daher sowohl Zugriffsabhängigkeiten als auch Texturlayouts." +concepts.synchronization.backends.description: 'DirectX 12 und Vulkan setzen Texturübergänge als Layout- und Zugriffsänderungen um. Für Metal führt die Implementierung von {transition} in Zenith.NET keine entsprechende Operation aus. Das Metal-Backend fasst Befehle stattdessen in Render- und Compute-Encodern zusammen und fügt beim Ende eines Encoders Sichtbarkeitsbarrieren ein. Abhängige Operationen innerhalb desselben Encoders, etwa aufeinanderfolgende Compute-Dispatches, verwenden explizite Aufrufe von {barrier}.' +concepts.synchronization.backends.details: 'Im {link} beendet der Beginn des Grafik-Renderpasses den Compute-Encoder und macht dessen Ausgabe für die Grafikbefehle sichtbar. Zwei aufeinanderfolgende Compute-Dispatches bleiben dagegen im selben Encoder. Ihre Abhängigkeit benötigt deshalb eine Barriere, auch wenn dazwischen ein Texturübergang aufgezeichnet wird. Portable Befehlsfolgen berücksichtigen daher sowohl Zugriffsabhängigkeiten als auch Texturlayouts.' concepts.synchronization.backends.details.link: Compute-Beispiel -concepts.synchronization.backends.title: "Backend-Verhalten" -concepts.synchronization.barriers.context: "Wählen Sie Stufen, die die relevanten Zugriffe umfassen und von der Warteschlange unterstützt werden. {barrierStagesAll} schließt alle unterstützten Stufen ein. Beschränken Sie die Auswahl, wenn die Abhängigkeit nur einen Teil davon betrifft." -concepts.synchronization.barriers.description: "Angenommen, zwei Compute-Dispatches stehen im selben Befehlspuffer: Der erste schreibt Simulationsdaten, der zweite liest sie. Eine Barriere dazwischen stellt sicher, dass der zweite Dispatch die abgeschlossenen Schreibvorgänge sieht. Bei einem Speicherpuffer genügt es, die Zugriffe zu ordnen; ein Texturlayoutübergang ist nicht erforderlich:" -concepts.synchronization.barriers.details: "Das erste Argument benennt die Stufen, die die Daten erzeugt haben; das zweite die Stufen, die sie verwenden werden. Gemeinsam beschreiben sie die benötigte Ausführungsreihenfolge und Speichersichtbarkeit zwischen den beiden Dispatches." -concepts.synchronization.barriers.guidance: "Die {link} verwendet dieses Muster zwischen Simulationsschritten. Jede Barriere steht nach dem Dispatch, der die Daten erzeugt, und vor dem Dispatch, der sie verwendet." +concepts.synchronization.backends.title: 'Backend-Verhalten' +concepts.synchronization.barriers.context: 'Wählen Sie Stufen, die die relevanten Zugriffe umfassen und von der Warteschlange unterstützt werden. {barrierStagesAll} schließt alle unterstützten Stufen ein. Beschränken Sie die Auswahl, wenn die Abhängigkeit nur einen Teil davon betrifft.' +concepts.synchronization.barriers.description: 'Angenommen, zwei Compute-Dispatches stehen im selben Befehlspuffer: Der erste schreibt Simulationsdaten, der zweite liest sie. Eine Barriere dazwischen stellt sicher, dass der zweite Dispatch die abgeschlossenen Schreibvorgänge sieht. Bei einem Speicherpuffer genügt es, die Zugriffe zu ordnen; ein Texturlayoutübergang ist nicht erforderlich:' +concepts.synchronization.barriers.details: 'Das erste Argument benennt die Stufen, die die Daten erzeugt haben; das zweite die Stufen, die sie verwenden werden. Gemeinsam beschreiben sie die benötigte Ausführungsreihenfolge und Speichersichtbarkeit zwischen den beiden Dispatches.' +concepts.synchronization.barriers.guidance: 'Die {link} verwendet dieses Muster zwischen Simulationsschritten. Jede Barriere steht nach dem Dispatch, der die Daten erzeugt, und vor dem Dispatch, der sie verwendet.' concepts.synchronization.barriers.guidance.link: FluidTank-Simulation -concepts.synchronization.barriers.title: "Pipeline-Barrieren" -concepts.synchronization.dependencies.description: "Ermitteln Sie für jede Ressource, welche Zugriffe dieselben Daten betreffen. Sobald einer davon schreibt, muss die benötigte Reihenfolge erhalten bleiben. Zwei Lesezugriffe stehen nicht im Konflikt; Anforderungen an Texturlayout und Präsentation gelten dennoch. Auch CPU-Aktualisierungen und Ressourcenfreigaben müssen warten, bis die GPU den betroffenen Speicher nicht mehr verwendet." -concepts.synchronization.dependencies.details: "Der Mechanismus richtet sich nach dem Ausführungsort der Operationen:" -concepts.synchronization.dependencies.guidance: "Eine Aufgabe kann mehrere Mechanismen benötigen. Stammt eine Textur etwa aus einer anderen Warteschlange, sind sowohl eine Einreichungsabhängigkeit als auch das passende Layout für den nächsten Zugriff erforderlich. Die CPU muss dafür nur blockiert werden, wenn sie selbst auf die Daten zugreifen oder deren Speicher freigeben soll." -concepts.synchronization.dependencies.table.cpuAccess.mechanism: "{wait} auf dem relevanten Abschlusswert aufrufen." -concepts.synchronization.dependencies.table.cpuAccess.situation: "CPU-Zugriff oder Ressourcenfreigabe erfordert den Abschluss der GPU-Arbeit" -concepts.synchronization.dependencies.table.crossQueue.mechanism: "Den {timelineValue} der erzeugenden Einreichung an {submit} der weiterverarbeitenden Einreichung übergeben." -concepts.synchronization.dependencies.table.crossQueue.situation: "Eine Warteschlange verwendet Daten aus einer anderen Warteschlange" +concepts.synchronization.barriers.title: 'Pipeline-Barrieren' +concepts.synchronization.dependencies.description: 'Ermitteln Sie für jede Ressource, welche Zugriffe dieselben Daten betreffen. Sobald einer davon schreibt, muss die benötigte Reihenfolge erhalten bleiben. Zwei Lesezugriffe stehen nicht im Konflikt; Anforderungen an Texturlayout und Präsentation gelten dennoch. Auch CPU-Aktualisierungen und Ressourcenfreigaben müssen warten, bis die GPU den betroffenen Speicher nicht mehr verwendet.' +concepts.synchronization.dependencies.details: 'Der Mechanismus richtet sich nach dem Ausführungsort der Operationen:' +concepts.synchronization.dependencies.guidance: 'Eine Aufgabe kann mehrere Mechanismen benötigen. Stammt eine Textur etwa aus einer anderen Warteschlange, sind sowohl eine Einreichungsabhängigkeit als auch das passende Layout für den nächsten Zugriff erforderlich. Die CPU muss dafür nur blockiert werden, wenn sie selbst auf die Daten zugreifen oder deren Speicher freigeben soll.' +concepts.synchronization.dependencies.table.cpuAccess.mechanism: '{wait} auf dem relevanten Abschlusswert aufrufen.' +concepts.synchronization.dependencies.table.cpuAccess.situation: 'CPU-Zugriff oder Ressourcenfreigabe erfordert den Abschluss der GPU-Arbeit' +concepts.synchronization.dependencies.table.crossQueue.mechanism: 'Den {timelineValue} der erzeugenden Einreichung an {submit} der weiterverarbeitenden Einreichung übergeben.' +concepts.synchronization.dependencies.table.crossQueue.situation: 'Eine Warteschlange verwendet Daten aus einer anderen Warteschlange' concepts.synchronization.dependencies.table.headings.mechanism: Mechanismus concepts.synchronization.dependencies.table.headings.situation: Situation -concepts.synchronization.dependencies.table.layoutChange.mechanism: "{commandBufferTransition} mit vorherigem und folgendem Layout." +concepts.synchronization.dependencies.table.layoutChange.mechanism: '{commandBufferTransition} mit vorherigem und folgendem Layout.' concepts.synchronization.dependencies.table.layoutChange.situation: Eine Textur-Unterressource ändert ihre Verwendungsart -concepts.synchronization.dependencies.table.pipelineStages.mechanism: "{commandBufferBarrier} mit den Erzeuger- und Verbraucherstufen." +concepts.synchronization.dependencies.table.pipelineStages.mechanism: '{commandBufferBarrier} mit den Erzeuger- und Verbraucherstufen.' concepts.synchronization.dependencies.table.pipelineStages.situation: Abhängige GPU-Stufen in einem Befehlsstrom -concepts.synchronization.dependencies.title: "Zugriffsabhängigkeiten" -concepts.synchronization.description: "Synchronisation legt die Reihenfolge von Zugriffen auf gemeinsam verwendete Daten fest und stellt sicher, dass spätere Operationen die benötigten Ergebnisse sehen. Bei einer Schreib-Lese-Abhängigkeit ist die schreibende Operation der Erzeuger und die lesende der Verbraucher. Barrieren und Texturübergänge koordinieren GPU-Zugriffe; Timelines verbinden Einreichungen und ermöglichen es der CPU, auf GPU-Arbeit zu warten." -concepts.synchronization.layouts.context: "Verwenden Sie {undefined} als vorheriges Layout, wenn der bestehende Inhalt verworfen werden darf, etwa bei einem neuen Bild oder einem vollständig neu gefüllten Attachment. Soll der Inhalt geladen, abgetastet oder zur Akkumulation weiterverwendet werden, ist das Layout des vorherigen Zugriffs anzugeben." -concepts.synchronization.layouts.description: "Die Nutzungsflags einer Textur geben ihre erlaubten Rollen an. {textureLayout} beschreibt den Zugriff auf eine bestimmte Unterressource zu einem bestimmten Zeitpunkt der Befehlsfolge. Diese Unterressource wird durch Mip-Level und Array-Layer bestimmt. Ändert sich der Zugriff, zeichnen Sie einen Übergang auf. Das Compute-Beispiel schreibt etwa in eine Ausgabetextur mit dem Layout {storage} und bereitet sie anschließend für die Abtastung in einem Grafikpass vor:" -concepts.synchronization.layouts.details: "{outputTexture} wurde mit {sampledStorage} erstellt; die gewählte Unterressource liegt in {storage}. {default} bezeichnet Mip-Level 0 und Array-Layer 0. Andere Level und Layer bleiben unverändert." -concepts.synchronization.layouts.guidance: "Geben Sie bei {transition} das Layout der vorherigen Unterressourcennutzung an. Die Anwendung verfolgt diesen Zustand beim Aufzeichnen der Befehle und bei der Übergabe von Texturen zwischen Rendering-Stufen." -concepts.synchronization.layouts.title: "Texturlayouts" -concepts.synchronization.readback.description: "{isCompleted} meldet den GPU-Abschluss. Bei einem aufgezeichneten Download steht danach noch ein Schritt aus: die Kopie aus dem internen Rücklesespeicher in den Zielspeicher der Anwendung." -concepts.synchronization.readback.details: "{commandBufferDownload} zeichnet die GPU-Kopie in diesen internen Speicher auf. Nach Abschluss der Einreichung führt die Bibliothek die CPU-Kopie aus, während sie den fertigen Befehlspuffer zurücknimmt. {wait} auf dem Abschlusswert der Download-Einreichung wartet auf die GPU und verarbeitet die abgeschlossenen Puffer dieser Warteschlange. Dadurch werden beide Schritte abgeschlossen. Bis zur Rückkehr muss der Zielspeicher erhalten und verwalteter Speicher fixiert bleiben." -concepts.synchronization.readback.guidance: "Allein das Abfragen von {isCompleted} führt die abschließende CPU-Kopie nicht aus. Auch das Warten auf eine andere Warteschlange nimmt die abgeschlossenen Puffer der Download-Warteschlange nicht zurück. Wann Uploads und Downloads direkt auf Speicher zugreifen oder einen Zwischenspeicher nutzen, beschreibt {link}." +concepts.synchronization.dependencies.title: 'Zugriffsabhängigkeiten' +concepts.synchronization.description: 'Synchronisation legt die Reihenfolge von Zugriffen auf gemeinsam verwendete Daten fest und stellt sicher, dass spätere Operationen die benötigten Ergebnisse sehen. Bei einer Schreib-Lese-Abhängigkeit ist die schreibende Operation der Erzeuger und die lesende der Verbraucher. Barrieren und Texturübergänge koordinieren GPU-Zugriffe; Timelines verbinden Einreichungen und ermöglichen es der CPU, auf GPU-Arbeit zu warten.' +concepts.synchronization.layouts.context: 'Verwenden Sie {undefined} als vorheriges Layout, wenn der bestehende Inhalt verworfen werden darf, etwa bei einem neuen Bild oder einem vollständig neu gefüllten Attachment. Soll der Inhalt geladen, abgetastet oder zur Akkumulation weiterverwendet werden, ist das Layout des vorherigen Zugriffs anzugeben.' +concepts.synchronization.layouts.description: 'Die Nutzungsflags einer Textur geben ihre erlaubten Rollen an. {textureLayout} beschreibt den Zugriff auf eine bestimmte Unterressource zu einem bestimmten Zeitpunkt der Befehlsfolge. Diese Unterressource wird durch Mip-Level und Array-Layer bestimmt. Ändert sich der Zugriff, zeichnen Sie einen Übergang auf. Das Compute-Beispiel schreibt etwa in eine Ausgabetextur mit dem Layout {storage} und bereitet sie anschließend für die Abtastung in einem Grafikpass vor:' +concepts.synchronization.layouts.details: '{outputTexture} wurde mit {sampledStorage} erstellt; die gewählte Unterressource liegt in {storage}. {default} bezeichnet Mip-Level 0 und Array-Layer 0. Andere Level und Layer bleiben unverändert.' +concepts.synchronization.layouts.guidance: 'Geben Sie bei {transition} das Layout der vorherigen Unterressourcennutzung an. Die Anwendung verfolgt diesen Zustand beim Aufzeichnen der Befehle und bei der Übergabe von Texturen zwischen Rendering-Stufen.' +concepts.synchronization.layouts.title: 'Texturlayouts' +concepts.synchronization.readback.description: '{isCompleted} meldet den GPU-Abschluss. Bei einem aufgezeichneten Download steht danach noch ein Schritt aus: die Kopie aus dem internen Rücklesespeicher in den Zielspeicher der Anwendung.' +concepts.synchronization.readback.details: '{commandBufferDownload} zeichnet die GPU-Kopie in diesen internen Speicher auf. Nach Abschluss der Einreichung führt die Bibliothek die CPU-Kopie aus, während sie den fertigen Befehlspuffer zurücknimmt. {wait} auf dem Abschlusswert der Download-Einreichung wartet auf die GPU und verarbeitet die abgeschlossenen Puffer dieser Warteschlange. Dadurch werden beide Schritte abgeschlossen. Bis zur Rückkehr muss der Zielspeicher erhalten und verwalteter Speicher fixiert bleiben.' +concepts.synchronization.readback.guidance: 'Allein das Abfragen von {isCompleted} führt die abschließende CPU-Kopie nicht aus. Auch das Warten auf eine andere Warteschlange nimmt die abgeschlossenen Puffer der Download-Warteschlange nicht zurück. Wann Uploads und Downloads direkt auf Speicher zugreifen oder einen Zwischenspeicher nutzen, beschreibt {link}.' concepts.synchronization.readback.guidance.link: Ressourcenverwaltung -concepts.synchronization.readback.title: "Abschluss des Rücklesens" -concepts.synchronization.reuse.description: "Das Dreieck wartet auf den Abschluss jedes Frames, bevor es dessen Daten wiederverwendet. Sollen sich Frames in der Ausführung überlappen, benötigt jeder noch laufende Frame eigenen veränderlichen Speicher. Verfolgen Sie, wann dieser Speicher wieder verfügbar ist. Vor Datenänderungen müssen noch laufende GPU-Zugriffe auf dieselben Bytes, vor einer Ressourcenfreigabe alle ausstehenden Nutzungen der Ressource abgeschlossen sein." -concepts.synchronization.reuse.details: "Für Größenänderungen und das Beenden gilt dieselbe Reihenfolge: neue Nutzungen stoppen, bestehende abwarten und erst dann Ressourcen ersetzen oder freigeben. Halten Sie dies vor {swapChainResize} sowie vor der Freigabe von Ressourcen oder Kontext ein. Da das Dreieck jeden Frame abwartet, kann es die Größe zwischen den Callbacks ändern." -concepts.synchronization.reuse.guidance: "{swapChainPresent} setzt nach der Präsentation einen Abschlusspunkt in der Grafikwarteschlange und wartet darauf. Das Dreieck wartet daher auch dann bei der Präsentation, wenn die ausdrückliche Warteoperation nach der Einreichung entfällt. Unabhängig eingereichte Arbeit anderer Warteschlangen benötigt eine eigene Abschlussverfolgung." -concepts.synchronization.reuse.title: "Ressourcenwiederverwendung" -concepts.synchronization.timelines.context: "Soll die CPU nach der Weiterverarbeitung das Ergebnis lesen, gemeinsame Daten überschreiben oder Ressourcen freigeben, wartet sie auf diese Einreichung:" -concepts.synchronization.timelines.description: "Eine Timeline kennzeichnet den Warteschlangenfortschritt durch steigende Werte. {submit} liefert die Timeline und den Einreichungswert gemeinsam als {timelineValue}. Die numerischen {value}-Felder verschiedener Timelines sind nicht unmittelbar vergleichbar." -concepts.synchronization.timelines.details: "{producer} und {consumer} seien aufgezeichnete Befehlspuffer zweier Warteschlangen desselben Kontexts; der Verbraucher nutzt die Daten des Erzeugers. Ihre Einreichung erhält diese Abhängigkeit:" -concepts.synchronization.timelines.guidance: "Die weiterverarbeitende Warteschlange wartet vor der Ausführung ihrer Befehle auf den übergebenen Abschlusswert. Die CPU kann ohne {producedWait} weiterarbeiten. Erhalten Sie die gemeinsam verwendeten Ressourcen bis zum Abschluss von {consumed} und zeichnen Sie die für den nachfolgenden Zugriff erforderlichen Texturübergänge auf." -concepts.synchronization.timelines.notes: "Der Rückgabewert von {queueTimelineSignal} kann ebenso mit {wait} abgewartet oder als Abhängigkeit an eine andere Warteschlange übergeben werden. {signal} setzt diesen Abschlusspunkt hinter die zuvor eingereichte Arbeit. Die GPU erreicht ihn, sobald diese Arbeit beendet ist." -concepts.synchronization.timelines.title: "Timelines und Warteschlangenabhängigkeiten" +concepts.synchronization.readback.title: 'Abschluss des Rücklesens' +concepts.synchronization.reuse.description: 'Das Dreieck wartet auf den Abschluss jedes Frames, bevor es dessen Daten wiederverwendet. Sollen sich Frames in der Ausführung überlappen, benötigt jeder noch laufende Frame eigenen veränderlichen Speicher. Verfolgen Sie, wann dieser Speicher wieder verfügbar ist. Vor Datenänderungen müssen noch laufende GPU-Zugriffe auf dieselben Bytes, vor einer Ressourcenfreigabe alle ausstehenden Nutzungen der Ressource abgeschlossen sein.' +concepts.synchronization.reuse.details: 'Für Größenänderungen und das Beenden gilt dieselbe Reihenfolge: neue Nutzungen stoppen, bestehende abwarten und erst dann Ressourcen ersetzen oder freigeben. Halten Sie dies vor {swapChainResize} sowie vor der Freigabe von Ressourcen oder Kontext ein. Da das Dreieck jeden Frame abwartet, kann es die Größe zwischen den Callbacks ändern.' +concepts.synchronization.reuse.guidance: '{swapChainPresent} setzt nach der Präsentation einen Abschlusspunkt in der Grafikwarteschlange und wartet darauf. Das Dreieck wartet daher auch dann bei der Präsentation, wenn die ausdrückliche Warteoperation nach der Einreichung entfällt. Unabhängig eingereichte Arbeit anderer Warteschlangen benötigt eine eigene Abschlussverfolgung.' +concepts.synchronization.reuse.title: 'Ressourcenwiederverwendung' +concepts.synchronization.timelines.context: 'Soll die CPU nach der Weiterverarbeitung das Ergebnis lesen, gemeinsame Daten überschreiben oder Ressourcen freigeben, wartet sie auf diese Einreichung:' +concepts.synchronization.timelines.description: 'Eine Timeline kennzeichnet den Warteschlangenfortschritt durch steigende Werte. {submit} liefert die Timeline und den Einreichungswert gemeinsam als {timelineValue}. Die numerischen {value}-Felder verschiedener Timelines sind nicht unmittelbar vergleichbar.' +concepts.synchronization.timelines.details: '{producer} und {consumer} seien aufgezeichnete Befehlspuffer zweier Warteschlangen desselben Kontexts; der Verbraucher nutzt die Daten des Erzeugers. Ihre Einreichung erhält diese Abhängigkeit:' +concepts.synchronization.timelines.guidance: 'Die weiterverarbeitende Warteschlange wartet vor der Ausführung ihrer Befehle auf den übergebenen Abschlusswert. Die CPU kann ohne {producedWait} weiterarbeiten. Erhalten Sie die gemeinsam verwendeten Ressourcen bis zum Abschluss von {consumed} und zeichnen Sie die für den nachfolgenden Zugriff erforderlichen Texturübergänge auf.' +concepts.synchronization.timelines.notes: 'Der Rückgabewert von {queueTimelineSignal} kann ebenso mit {wait} abgewartet oder als Abhängigkeit an eine andere Warteschlange übergeben werden. {signal} setzt diesen Abschlusspunkt hinter die zuvor eingereichte Arbeit. Die GPU erreicht ihn, sobald diese Arbeit beendet ist.' +concepts.synchronization.timelines.title: 'Timelines und Warteschlangenabhängigkeiten' concepts.synchronization.title: Synchronisation home.actions.reference: API durchsuchen home.actions.tutorial: Mit einem Dreieck beginnen -home.entries.description: "Tutorials, Beispiele und API-Referenz" -home.entries.label: "Bereiche der Dokumentation" +home.entries.description: 'Tutorials, Beispiele und API-Referenz' +home.entries.label: 'Bereiche der Dokumentation' home.entries.reference.action: API erkunden home.entries.reference.category: Referenz -home.entries.reference.description: "API-Typen, Member und Deklarationen nachschlagen" +home.entries.reference.description: 'API-Typen, Member und Deklarationen nachschlagen' home.entries.reference.title: API-Referenz home.entries.samples.action: Beispiele durchsuchen home.entries.samples.category: Beispiele -home.entries.samples.description: "Ausführbare Beispiele für Grafik- und Compute-Verfahren" +home.entries.samples.description: 'Ausführbare Beispiele für Grafik- und Compute-Verfahren' home.entries.samples.title: Beispiele -home.entries.title: "Dokumentation" +home.entries.title: 'Dokumentation' home.entries.tutorial.action: Tutorial starten home.entries.tutorial.category: Tutorial -home.entries.tutorial.description: "Vom leeren Projekt zum ersten Dreieck auf dem Bildschirm" +home.entries.tutorial.description: 'Vom leeren Projekt zum ersten Dreieck auf dem Bildschirm' home.entries.tutorial.title: Erstes Dreieck -home.introduction.accent: "auf mehreren Plattformen" -home.introduction.description: "Zenith.NET bündelt Grafik und Compute für DirectX, Metal und Vulkan in einer gemeinsamen API" -home.introduction.title: "Grafik für .NET{lineBreak}{accent}" -home.meta.description: "Plattformübergreifende Grafik und Compute für .NET mit einer gemeinsamen API für DirectX, Metal und Vulkan" -home.scene.description: "Interaktive rotierende Geometrie. Ansicht durch Ziehen oder mit den Pfeiltasten verändern." +home.introduction.accent: 'auf mehreren Plattformen' +home.introduction.description: 'Zenith.NET bündelt Grafik und Compute für DirectX, Metal und Vulkan in einer gemeinsamen API' +home.introduction.title: 'Grafik für .NET{lineBreak}{accent}' +home.meta.description: 'Plattformübergreifende Grafik und Compute für .NET mit einer gemeinsamen API für DirectX, Metal und Vulkan' +home.scene.description: 'Interaktive rotierende Geometrie. Ansicht durch Ziehen oder mit den Pfeiltasten verändern.' home.scene.label: Geometrieanzeige home.scene.surface: Oberfläche home.scene.wireframe: Drahtgitter home.title: Modernes RHI für .NET -learning.concepts.description: "Ressourcennutzungen wählen, Shader-Daten beschreiben und GPU-Ausführung koordinieren" -learning.concepts.execution.description: "Aufzeichnung, Einreichung und Ressourcenlebensdauer" -learning.concepts.platforms.description: "Native Präsentation und UI-Rendering-Steuerelemente" -learning.concepts.resources.description: "Ressourcennutzungen, Speicherplatzierung und Ansichten" -learning.concepts.shaders.description: "Layout- und Bindungskonventionen für C# und Slang" -learning.concepts.synchronization.description: "Abhängigkeiten, Sichtbarkeit und Abschluss" +learning.concepts.description: 'Ressourcennutzungen wählen, Shader-Daten beschreiben und GPU-Ausführung koordinieren' +learning.concepts.execution.description: 'Aufzeichnung, Einreichung und Ressourcenlebensdauer' +learning.concepts.platforms.description: 'Native Präsentation und UI-Rendering-Steuerelemente' +learning.concepts.resources.description: 'Ressourcennutzungen, Speicherplatzierung und Ansichten' +learning.concepts.shaders.description: 'Layout- und Bindungskonventionen für C# und Slang' +learning.concepts.synchronization.description: 'Abhängigkeiten, Sichtbarkeit und Abschluss' learning.concepts.title: Kernkonzepte -learning.description: "Beginnen Sie mit dem Dreieck-Tutorial und erstellen Sie Ihre erste Anwendung. Anschließend erläutern die Konzeptartikel Ressourcenverwaltung, Shader-Daten und Synchronisation. Für einzelne Grafikverfahren stehen ausführbare Beispiele bereit." +learning.description: 'Beginnen Sie mit dem Dreieck-Tutorial und erstellen Sie Ihre erste Anwendung. Anschließend erläutern die Konzeptartikel Ressourcenverwaltung, Shader-Daten und Synchronisation. Für einzelne Grafikverfahren stehen ausführbare Beispiele bereit.' learning.entries.samples.action: Beispiele durchsuchen -learning.entries.samples.description: "C#- und Slang-Implementierungen für Geometrie, Compute, Ray-Queries und Mesh-Shading" +learning.entries.samples.description: 'C#- und Slang-Implementierungen für Geometrie, Compute, Ray-Queries und Mesh-Shading' learning.entries.tutorial.action: Tutorial öffnen -learning.entries.tutorial.description: "Eine Konsolenanwendung mit Fenster und gerendertem Dreieck" -learning.meta.description: "Tutorials und Konzepte zum Programmiermodell von Zenith.NET" +learning.entries.tutorial.description: 'Eine Konsolenanwendung mit Fenster und gerendertem Dreieck' +learning.meta.description: 'Tutorials und Konzepte zum Programmiermodell von Zenith.NET' learning.title: Lernen -reference.description: "Referenz zu Ressourcen, Befehlen und Plattformintegration" -reference.entries.commands.description: "Grafik-, Compute- und Transferbefehle" -reference.entries.commands.label: "Befehle aufzeichnen" -reference.entries.context.description: "GPU-Ressourcenerstellung für das gewählte Backend" +reference.description: 'Referenz zu Ressourcen, Befehlen und Plattformintegration' +reference.entries.commands.description: 'Grafik-, Compute- und Transferbefehle' +reference.entries.commands.label: 'Befehle aufzeichnen' +reference.entries.context.description: 'GPU-Ressourcenerstellung für das gewählte Backend' reference.entries.context.label: Hier beginnen -reference.meta.description: "Namespaces, Typen und Member von Zenith.NET" -reference.navigation.core: "Referenz der Kern-API" +reference.meta.description: 'Namespaces, Typen und Member von Zenith.NET' +reference.navigation.core: 'Referenz der Kern-API' reference.title: API-Referenz -samples.computeShader.description: "Das Beispiel lädt {assetsTexturesShokoPng}, wandelt das Bild mit einem Compute-Dispatch in Graustufen um und zeigt die Ausgabetextur an. Die Umwandlung erfolgt einmal; spätere Frames zeigen dasselbe Ergebnis. Der Renderer zeigt die Bindung abtastbarer und beschreibbarer Texturen, das Aufrunden der Threadgruppenanzahl zur vollständigen Bildabdeckung und die Bereichsprüfung im Shader." -samples.computeShader.details: "{computeShaderRendererCs} · {computeShaderSlang}" +samples.computeShader.description: 'Das Beispiel lädt {assetsTexturesShokoPng}, wandelt das Bild mit einem Compute-Dispatch in Graustufen um und zeigt die Ausgabetextur an. Die Umwandlung erfolgt einmal; spätere Frames zeigen dasselbe Ergebnis. Der Renderer zeigt die Bindung abtastbarer und beschreibbarer Texturen, das Aufrunden der Threadgruppenanzahl zur vollständigen Bildabdeckung und die Bereichsprüfung im Shader.' +samples.computeShader.details: '{computeShaderRendererCs} · {computeShaderSlang}' samples.computeShader.title: Compute-Shader -samples.cube.description: "Der Würfel ergänzt indexiertes Zeichnen, Modell-, View- und Projektionsmatrizen in einem Konstantenpuffer sowie Tiefentests. Seine Tiefen-/Stencil-Textur im Format {d32FloatS8UInt} wird bei Größenänderungen neu erstellt." -samples.cube.details: "{spinningCubeRendererCs} · {spinningCubeSlang}" +samples.cube.description: 'Der Würfel ergänzt indexiertes Zeichnen, Modell-, View- und Projektionsmatrizen in einem Konstantenpuffer sowie Tiefentests. Seine Tiefen-/Stencil-Textur im Format {d32FloatS8UInt} wird bei Größenänderungen neu erstellt.' +samples.cube.details: '{spinningCubeRendererCs} · {spinningCubeSlang}' samples.cube.title: Rotierender Würfel -samples.description: "Jedes Beispiel verbindet einen C#-Renderer mit seinem Slang-Shader und behandelt ein bestimmtes Verfahren. Den vollständigen Anwendungsaufbau und die Rendersequenz erläutert {link}." +samples.description: 'Jedes Beispiel verbindet einen C#-Renderer mit seinem Slang-Shader und behandelt ein bestimmtes Verfahren. Den vollständigen Anwendungsaufbau und die Rendersequenz erläutert {link}.' samples.description.link: Erstes Dreieck -samples.execution.description: "Starten Sie das Projekt {link} und wählen Sie ein Beispiel im Konsolenmenü." +samples.execution.description: 'Starten Sie das Projekt {link} und wählen Sie ein Beispiel im Konsolenmenü.' samples.execution.description.link: ZenithTutorials -samples.execution.title: "Beispiele ausführen" -samples.host.description: "{appCs} initialisiert Kontext, Fenster und Swapchain. Pro Frame bezieht der Host einen Befehlspuffer, ruft den Renderer auf, reicht die Befehle ein und präsentiert das Ergebnis. {iRendererCs} definiert Aktualisierung, Rendering, Größenanpassung und Freigabe." -samples.host.details: "Die Compute- und Raytracing-Renderer erzeugen Offscreen-Texturen. {texturePresenterCs} und {presentTextureSlang} zeichnen diese in die aktuelle Ausgabetextur. Anschließend reicht der gemeinsame Host die Befehle ein und präsentiert den Frame." -samples.host.title: "Host und Präsentation" -samples.indirectDrawing.description: "Indirektes Zeichnen stellt mehrere Würfelinstanzen aus einem Puffer für indexierte Zeichenargumente und einem strukturierten Puffer mit Instanzdaten dar. Die CPU liefert die Argumente und aktualisiert die Transformationen." -samples.indirectDrawing.details: "{indirectDrawingRendererCs} · {indirectDrawingSlang}" +samples.execution.title: 'Beispiele ausführen' +samples.host.description: '{appCs} initialisiert Kontext, Fenster und Swapchain. Pro Frame bezieht der Host einen Befehlspuffer, ruft den Renderer auf, reicht die Befehle ein und präsentiert das Ergebnis. {iRendererCs} definiert Aktualisierung, Rendering, Größenanpassung und Freigabe.' +samples.host.details: 'Die Compute- und Raytracing-Renderer erzeugen Offscreen-Texturen. {texturePresenterCs} und {presentTextureSlang} zeichnen diese in die aktuelle Ausgabetextur. Anschließend reicht der gemeinsame Host die Befehle ein und präsentiert den Frame.' +samples.host.title: 'Host und Präsentation' +samples.indirectDrawing.description: 'Indirektes Zeichnen stellt mehrere Würfelinstanzen aus einem Puffer für indexierte Zeichenargumente und einem strukturierten Puffer mit Instanzdaten dar. Die CPU liefert die Argumente und aktualisiert die Transformationen.' +samples.indirectDrawing.details: '{indirectDrawingRendererCs} · {indirectDrawingSlang}' samples.indirectDrawing.title: Indirektes Zeichnen -samples.meshShading.description: "Ein Task-Shader sortiert nicht sichtbare Kugelinstanzen aus und übergibt die verbleibenden Indizes an den Mesh-Shader, der die Geometrie erzeugt. Vor der Pipeline-Erstellung prüft der Renderer {contextCapabilitiesMeshShadingSupported}." -samples.meshShading.details: "{meshShadingRendererCs} · {meshShadingSlang}" +samples.meshShading.description: 'Ein Task-Shader sortiert nicht sichtbare Kugelinstanzen aus und übergibt die verbleibenden Indizes an den Mesh-Shader, der die Geometrie erzeugt. Vor der Pipeline-Erstellung prüft der Renderer {contextCapabilitiesMeshShadingSupported}.' +samples.meshShading.details: '{meshShadingRendererCs} · {meshShadingSlang}' samples.meshShading.title: Mesh-Shading -samples.rayTracing.description: "Das Beispiel erstellt Beschleunigungsstrukturen der unteren und oberen Ebene für einen Boden und prozedurale Kugeln und führt Inline-Rayqueries in einem Compute-Shader aus. Vor der Initialisierung prüft es {contextCapabilitiesRayTracingSupported}." -samples.rayTracing.details: "{rayTracingRendererCs} · {rayTracingSlang}" +samples.rayTracing.description: 'Das Beispiel erstellt Beschleunigungsstrukturen der unteren und oberen Ebene für einen Boden und prozedurale Kugeln und führt Inline-Rayqueries in einem Compute-Shader aus. Vor der Initialisierung prüft es {contextCapabilitiesRayTracingSupported}.' +samples.rayTracing.details: '{rayTracingRendererCs} · {rayTracingSlang}' samples.rayTracing.title: Raytracing samples.title: Beispiele -samples.triangle.description: "Das Dreieck verbindet einen Vertexpuffer mit dem passenden Eingabelayout und zeichnet drei Vertices durch eine Grafikpipeline." -samples.triangle.details: "{helloTriangleRendererCs} · {helloTriangleSlang} · {link}" +samples.triangle.description: 'Das Dreieck verbindet einen Vertexpuffer mit dem passenden Eingabelayout und zeichnet drei Vertices durch eine Grafikpipeline.' +samples.triangle.details: '{helloTriangleRendererCs} · {helloTriangleSlang} · {link}' samples.triangle.details.link: Vollständiges Tutorial samples.triangle.title: Hallo Dreieck -samples.workloads.description: "Das {link} im Haupt-Repository enthält größere Anwendungen, die den Bibliotheksquellcode referenzieren." +samples.workloads.description: 'Das {link} im Haupt-Repository enthält größere Anwendungen, die den Bibliotheksquellcode referenzieren.' samples.workloads.description.link: Verzeichnis Experiments -samples.workloads.details: "Die Fensterexperimente nutzen dieselben Präsentationspfade für Windows, macOS und Linux/X11. UI-Steuerelemente für Avalonia, WinForms, WPF, WinUI/Uno und MAUI behandelt {link}, einschließlich Frame-Ablauf und Implementierungsquellen." +samples.workloads.details: 'Die Fensterexperimente nutzen dieselben Präsentationspfade für Windows, macOS und Linux/X11. UI-Steuerelemente für Avalonia, WinForms, WPF, WinUI/Uno und MAUI behandelt {link}, einschließlich Frame-Ablauf und Implementierungsquellen.' samples.workloads.details.link: Plattformintegration -samples.workloads.table.cornellBox.example: "{link}" +samples.workloads.table.cornellBox.example: '{link}' samples.workloads.table.cornellBox.example.link: CornellBox -samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: "Pathtracing, Rauschunterdrückung, Tone-Mapping, Hochskalierung und ImGui-Steuerelemente. Erfordert Raytracing-Unterstützung." -samples.workloads.table.fluidTank.example: "{link}" +samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: 'Pathtracing, Rauschunterdrückung, Tone-Mapping, Hochskalierung und ImGui-Steuerelemente. Erfordert Raytracing-Unterstützung.' +samples.workloads.table.fluidTank.example: '{link}' samples.workloads.table.fluidTank.example.link: FluidTank -samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: "Compute-Fluidsimulation, Abhängigkeiten zwischen Simulationsstufen und mehrpassiges Oberflächen-Rendering." +samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: 'Compute-Fluidsimulation, Abhängigkeiten zwischen Simulationsstufen und mehrpassiges Oberflächen-Rendering.' samples.workloads.table.headings.example: Beispiel -samples.workloads.table.headings.whatItDemonstratesAndRequires: "Verfahren und Voraussetzungen" -samples.workloads.table.inkCanvas.example: "{link}" +samples.workloads.table.headings.whatItDemonstratesAndRequires: 'Verfahren und Voraussetzungen' +samples.workloads.table.inkCanvas.example: '{link}' samples.workloads.table.inkCanvas.example.link: InkCanvas samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: Skia-Zeichnen und Eingabeverarbeitung in einem nativen Fenster. Erfordert das Backend und die native Skia-Bibliothek für die Zielplattform. -samples.workloads.table.platformDetection.example: "{link}" +samples.workloads.table.platformDetection.example: '{link}' samples.workloads.table.platformDetection.example.link: PlatformDetection -samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: "Versucht für jedes Backend einen Kontext zu erstellen und meldet die Gerätefunktionen. Ein fehlgeschlagener Versuch wird als nicht unterstützt gemeldet; Ursache können das Gerät, der Treiber oder eine fehlende Laufzeitabhängigkeit sein." -samples.workloads.title: "Umfangreichere Anwendungen" -tutorial.context.description: "Ein {graphicsContext} verbindet die Anwendung über ein Backend mit der GPU und stellt die Methoden zum Erstellen der Rendering-Ressourcen bereit." -tutorial.context.details: "Fügen Sie die Kontextinitialisierung {emphasis} ein:" +samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: 'Versucht für jedes Backend einen Kontext zu erstellen und meldet die Gerätefunktionen. Ein fehlgeschlagener Versuch wird als nicht unterstützt gemeldet; Ursache können das Gerät, der Treiber oder eine fehlende Laufzeitabhängigkeit sein.' +samples.workloads.title: 'Umfangreichere Anwendungen' +tutorial.context.description: 'Ein {graphicsContext} verbindet die Anwendung über ein Backend mit der GPU und stellt die Methoden zum Erstellen der Rendering-Ressourcen bereit.' +tutorial.context.details: 'Fügen Sie die Kontextinitialisierung {emphasis} ein:' tutorial.context.details.emphasis: nach den using-Direktiven, vor {iWindowWindow} -tutorial.context.guidance: "Jeder Zweig wählt das Backend der aktuellen Plattform und fordert Validierung an. Meldungen von {validationMessage} werden in der Konsole ausgegeben." -tutorial.context.imports: "Ergänzen Sie am Anfang von {programCs} die folgenden using-Direktiven:" -tutorial.context.title: "Grafikkontext" -tutorial.description: "In diesem Tutorial entsteht aus einem leeren .NET-Konsolenprojekt eine Anwendung, die ein Fenster öffnet und ein farbiges Dreieck zeichnet." -tutorial.details: "Das Tutorial führt über drei überprüfbare Zwischenstände zum Ergebnis: ein leeres Fenster, eine einfarbige Fläche und schließlich das farbige Dreieck. Führen Sie die Anwendung nach jedem dieser Schritte aus, bevor Sie den nächsten Teil ergänzen." -tutorial.draw.context: "Die Argumente für {draw} sind:" -tutorial.draw.description: "Ersetzen Sie im Callback {windowRender} den Kommentar {addTheTriangleDrawCommandsHereLater} durch folgende Befehle zwischen {beginRenderPass} und {endRenderPass}:" -tutorial.draw.details: "{setPipeline} wählt Shader und Renderzustand. Der Aufruf muss vor der Vertexbindung stehen, weil deren Interpretation vom Eingabelayout der Pipeline abhängt." -tutorial.draw.guidance: "{setVertexBufferVertexBuffer} bindet die hochgeladenen Vertexdaten ab Byte-Offset 0 an Eingabeslot 0. Dieser entspricht dem einzigen Eintrag in {inputLayouts}." -tutorial.draw.notes: "Diese Aufrufe zeichnen die Zeichenbefehle auf. Das vorhandene {submitWait} reicht sie ein und wartet auf ihren GPU-Abschluss; {present} fordert anschließend die Anzeige des fertigen Bildes an. Behalten Sie das Füllen mit der Hintergrundfarbe am Anfang des Passes bei, damit auch die Fläche außerhalb des Dreiecks einen definierten Inhalt hat." +tutorial.context.guidance: 'Jeder Zweig wählt das Backend der aktuellen Plattform und fordert Validierung an. Meldungen von {validationMessage} werden in der Konsole ausgegeben.' +tutorial.context.imports: 'Ergänzen Sie am Anfang von {programCs} die folgenden using-Direktiven:' +tutorial.context.title: 'Grafikkontext' +tutorial.description: 'In diesem Tutorial entsteht aus einem leeren .NET-Konsolenprojekt eine Anwendung, die ein Fenster öffnet und ein farbiges Dreieck zeichnet.' +tutorial.details: 'Das Tutorial führt über drei überprüfbare Zwischenstände zum Ergebnis: ein leeres Fenster, eine einfarbige Fläche und schließlich das farbige Dreieck. Führen Sie die Anwendung nach jedem dieser Schritte aus, bevor Sie den nächsten Teil ergänzen.' +tutorial.draw.context: 'Die Argumente für {draw} sind:' +tutorial.draw.description: 'Ersetzen Sie im Callback {windowRender} den Kommentar {addTheTriangleDrawCommandsHereLater} durch folgende Befehle zwischen {beginRenderPass} und {endRenderPass}:' +tutorial.draw.details: '{setPipeline} wählt Shader und Renderzustand. Der Aufruf muss vor der Vertexbindung stehen, weil deren Interpretation vom Eingabelayout der Pipeline abhängt.' +tutorial.draw.guidance: '{setVertexBufferVertexBuffer} bindet die hochgeladenen Vertexdaten ab Byte-Offset 0 an Eingabeslot 0. Dieser entspricht dem einzigen Eintrag in {inputLayouts}.' +tutorial.draw.notes: 'Diese Aufrufe zeichnen die Zeichenbefehle auf. Das vorhandene {submitWait} reicht sie ein und wartet auf ihren GPU-Abschluss; {present} fordert anschließend die Anzeige des fertigen Bildes an. Behalten Sie das Füllen mit der Hintergrundfarbe am Anfang des Passes bei, damit auch die Fläche außerhalb des Dreiecks einen definierten Inhalt hat.' tutorial.draw.table.firstInstance.meaning: Instanznummerierung bei null beginnen. -tutorial.draw.table.firstVertex.meaning: "Mit dem ersten Vertex im Puffer beginnen." +tutorial.draw.table.firstVertex.meaning: 'Mit dem ersten Vertex im Puffer beginnen.' tutorial.draw.table.headings.argument: Argument tutorial.draw.table.headings.description: Wert tutorial.draw.table.headings.meaning: Bedeutung tutorial.draw.table.instanceCount.meaning: Eine Kopie des Dreiecks zeichnen. -tutorial.draw.table.vertexCount.meaning: "Drei Vertices lesen." -tutorial.draw.title: "Zeichenbefehle" -tutorial.execution.description: "Erstellen und starten Sie das Projekt {firstTriangle}." -tutorial.execution.details: "Auf dem dunklen Hintergrund erscheint ein Dreieck: oben rot, rechts unten grün und links unten blau. Durch Interpolation gehen die Vertexfarben im Inneren fließend ineinander über." -tutorial.execution.guidance: "Beim Ändern der Fenstergröße ändern sich die Pixelmaße des Bildes, während die Vertexkoordinaten gleich bleiben. Der Viewport bildet sie auf die neue Breite und Höhe ab. Das Dreieck wird deshalb gestreckt, wenn sich das Seitenverhältnis des Fensters ändert." -tutorial.execution.title: "Anwendung ausführen" -tutorial.frame.commands.context: "Nach {endRenderPass} bereitet der zweite Übergang die Präsentation vor. {submit} beendet die Aufzeichnung und reicht den Befehlspuffer ein; {wait} blockiert bis zu dessen Abschluss. Danach fordert {present} die Bildanzeige an." -tutorial.frame.commands.description: "Ein Renderpass fasst Zeichenoperationen zusammen, die in dieselben Attachments schreiben. Hier nimmt die Ausgabetextur der Swapchain die Farbausgabe auf. {colorAttachmentClear} legt fest, dass dieses Attachment zu Beginn mit einer RGBA-Farbe gefüllt und sein Inhalt am Ende erhalten wird. {beginRenderPass} zeichnet den Beginn des Passes mit diesen Einstellungen auf." -tutorial.frame.commands.details: "Die Sammlung enthält ein Farb-Attachment. {null} gibt an, dass der Pass kein Tiefen-/Stencil-Attachment verwendet." -tutorial.frame.commands.guidance: "{beginRenderPass} setzt Viewport und Scissor auf die gesamte Attachment-Fläche. Der Viewport bildet Renderkoordinaten auf Pixelpositionen ab; der Scissor begrenzt den Bereich, in den geschrieben werden darf." -tutorial.frame.commands.title: "Löschen, Einreichung und Präsentation" -tutorial.frame.description: "Füllen Sie das Fenster zunächst mit einer Hintergrundfarbe. Diese Operation heißt Löschen. Sobald die Farbe sichtbar ist, arbeiten das native Präsentationsziel, die Befehlseinreichung und die Präsentation zusammen. Darauf bauen die Vertices und Shader des Dreiecks auf." -tutorial.frame.details: "Silk.NET ruft den Render-Callback auf, sobald ein Frame ansteht. Das Zeitargument wird nicht verwendet und erhält den Namen {value}. Registrieren Sie den Callback {emphasis}:" +tutorial.draw.table.vertexCount.meaning: 'Drei Vertices lesen.' +tutorial.draw.title: 'Zeichenbefehle' +tutorial.execution.description: 'Erstellen und starten Sie das Projekt {firstTriangle}.' +tutorial.execution.details: 'Auf dem dunklen Hintergrund erscheint ein Dreieck: oben rot, rechts unten grün und links unten blau. Durch Interpolation gehen die Vertexfarben im Inneren fließend ineinander über.' +tutorial.execution.guidance: 'Beim Ändern der Fenstergröße ändern sich die Pixelmaße des Bildes, während die Vertexkoordinaten gleich bleiben. Der Viewport bildet sie auf die neue Breite und Höhe ab. Das Dreieck wird deshalb gestreckt, wenn sich das Seitenverhältnis des Fensters ändert.' +tutorial.execution.title: 'Anwendung ausführen' +tutorial.frame.commands.context: 'Nach {endRenderPass} bereitet der zweite Übergang die Präsentation vor. {submit} beendet die Aufzeichnung und reicht den Befehlspuffer ein; {wait} blockiert bis zu dessen Abschluss. Danach fordert {present} die Bildanzeige an.' +tutorial.frame.commands.description: 'Ein Renderpass fasst Zeichenoperationen zusammen, die in dieselben Attachments schreiben. Hier nimmt die Ausgabetextur der Swapchain die Farbausgabe auf. {colorAttachmentClear} legt fest, dass dieses Attachment zu Beginn mit einer RGBA-Farbe gefüllt und sein Inhalt am Ende erhalten wird. {beginRenderPass} zeichnet den Beginn des Passes mit diesen Einstellungen auf.' +tutorial.frame.commands.details: 'Die Sammlung enthält ein Farb-Attachment. {null} gibt an, dass der Pass kein Tiefen-/Stencil-Attachment verwendet.' +tutorial.frame.commands.guidance: '{beginRenderPass} setzt Viewport und Scissor auf die gesamte Attachment-Fläche. Der Viewport bildet Renderkoordinaten auf Pixelpositionen ab; der Scissor begrenzt den Bereich, in den geschrieben werden darf.' +tutorial.frame.commands.title: 'Löschen, Einreichung und Präsentation' +tutorial.frame.description: 'Füllen Sie das Fenster zunächst mit einer Hintergrundfarbe. Diese Operation heißt Löschen. Sobald die Farbe sichtbar ist, arbeiten das native Präsentationsziel, die Befehlseinreichung und die Präsentation zusammen. Darauf bauen die Vertices und Shader des Dreiecks auf.' +tutorial.frame.details: 'Silk.NET ruft den Render-Callback auf, sobald ein Frame ansteht. Das Zeitargument wird nicht verwendet und erhält den Namen {value}. Registrieren Sie den Callback {emphasis}:' tutorial.frame.details.emphasis: vor {windowRun} -tutorial.frame.target.description: "{graphicsQueueCommandBuffer} liefert einen aufzeichnungsbereiten Befehlspuffer. Die Aufzeichnung beschreibt GPU-Arbeit; ausgeführt wird sie erst nach der Einreichung." -tutorial.frame.target.details: "Ein Texturlayout beschreibt, welchen Zugriff eine Operation benötigt. Der erste Aufruf von {transition} bereitet die Ausgabetextur als Farb-Attachment vor. {default} wählt Mip-Level 0 und Array-Layer 0, also das Basisbild dieser Textur. Da der Pass das gesamte Bild mit einer Hintergrundfarbe füllt, darf {undefined} den bisherigen Inhalt verwerfen." -tutorial.frame.target.guidance: "Verwenden Sie in jedem Frame die aktuelle Ausgabetextur, da die Präsentation zum nächsten Bild wechseln kann." +tutorial.frame.target.description: '{graphicsQueueCommandBuffer} liefert einen aufzeichnungsbereiten Befehlspuffer. Die Aufzeichnung beschreibt GPU-Arbeit; ausgeführt wird sie erst nach der Einreichung.' +tutorial.frame.target.details: 'Ein Texturlayout beschreibt, welchen Zugriff eine Operation benötigt. Der erste Aufruf von {transition} bereitet die Ausgabetextur als Farb-Attachment vor. {default} wählt Mip-Level 0 und Array-Layer 0, also das Basisbild dieser Textur. Da der Pass das gesamte Bild mit einer Hintergrundfarbe füllt, darf {undefined} den bisherigen Inhalt verwerfen.' +tutorial.frame.target.guidance: 'Verwenden Sie in jedem Frame die aktuelle Ausgabetextur, da die Präsentation zum nächsten Bild wechseln kann.' tutorial.frame.target.title: Ausgabetextur vorbereiten -tutorial.frame.title: "Der erste Frame" -tutorial.geometry.data.description: "Fügen Sie das Vertexarray {emphasis} ein. Auch die anschließende Ressourceninitialisierung steht in der angegebenen Reihenfolge vor diesem Callback." +tutorial.frame.title: 'Der erste Frame' +tutorial.geometry.data.description: 'Fügen Sie das Vertexarray {emphasis} ein. Auch die anschließende Ressourceninitialisierung steht in der angegebenen Reihenfolge vor diesem Callback.' tutorial.geometry.data.description.emphasis: vor {windowRender} -tutorial.geometry.data.details: "Jeder Eintrag erstellt einen {vertex}; die beiden inneren {new}-Ausdrücke liefern {vector3}-Position und {vector4}-Farbe. Die Positionen bilden die obere, rechte untere und linke untere Ecke. Der Vertex-Shader ergänzt {w} als vierte Koordinate. Bei w = 1 sind x und y zugleich normalisierte Gerätekoordinaten: -1 und +1 markieren die Bildgrenzen, 0 die Mitte, unabhängig von Pixelmaßen." -tutorial.geometry.data.guidance: "Jede Farbe hat Rot-, Grün-, Blau- und Alpha-Komponenten; Alpha ist 1. Alle drei Vertices liegen mit z = 0 in derselben Ebene." -tutorial.geometry.data.title: "Vertexpositionen und Farben" -tutorial.geometry.description: "Jeder der drei Vertices besitzt eine Position und eine Farbe. Aus den Positionen ergibt sich die Form des Dreiecks; die GPU interpoliert die Farben über dessen Fläche." -tutorial.geometry.format.description: "Ergänzen Sie die Vertexdeklaration {emphasis}:" +tutorial.geometry.data.details: 'Jeder Eintrag erstellt einen {vertex}; die beiden inneren {new}-Ausdrücke liefern {vector3}-Position und {vector4}-Farbe. Die Positionen bilden die obere, rechte untere und linke untere Ecke. Der Vertex-Shader ergänzt {w} als vierte Koordinate. Bei w = 1 sind x und y zugleich normalisierte Gerätekoordinaten: -1 und +1 markieren die Bildgrenzen, 0 die Mitte, unabhängig von Pixelmaßen.' +tutorial.geometry.data.guidance: 'Jede Farbe hat Rot-, Grün-, Blau- und Alpha-Komponenten; Alpha ist 1. Alle drei Vertices liegen mit z = 0 in derselben Ebene.' +tutorial.geometry.data.title: 'Vertexpositionen und Farben' +tutorial.geometry.description: 'Jeder der drei Vertices besitzt eine Position und eine Farbe. Aus den Positionen ergibt sich die Form des Dreiecks; die GPU interpoliert die Farben über dessen Fläche.' +tutorial.geometry.format.description: 'Ergänzen Sie die Vertexdeklaration {emphasis}:' tutorial.geometry.format.description.emphasis: am Ende von {programCs}, nach den Bereinigungsanweisungen -tutorial.geometry.format.details: "{file} beschränkt den Typ auf {programCs}, und {layoutKindSequential} erhält die Deklarationsreihenfolge seiner Felder. {position} enthält drei 32-Bit-Gleitkommazahlen und beginnt am Byte-Offset 0; {color} enthält vier und beginnt am Byte-Offset 12. Ein Vertex belegt damit 28 Bytes. Das Eingabelayout beschreibt diese Anordnung, damit die GPU die Felder korrekt liest." -tutorial.geometry.format.imports: "Ergänzen Sie am Anfang von {programCs} diese using-Direktiven für die Vektortypen und das Attribut zur Festlegung des Strukturlayouts:" -tutorial.geometry.format.title: "Vertexdarstellung" -tutorial.geometry.title: "Vertexdaten" -tutorial.geometry.upload.context: "{fixed} verhindert, dass die Garbage Collection das Array verschiebt, solange dessen Adresse verwendet wird. Bei diesem CPU-beschreibbaren Puffer mappt {upload} den Speicher, kopiert die Daten und hebt das Mapping vor der Rückkehr auf. Das Array muss daher nur während des Aufrufs fixiert bleiben. Laden Sie die Vertices einmal bei der Initialisierung hoch und geben Sie den Puffer erst nach Abschluss des Renderings frei." -tutorial.geometry.upload.description: "Speichern Sie die Vertices in einem {buffer}, damit die GPU sie beim Zeichnen lesen kann. Fügen Sie Allokation und Upload direkt nach dem Array ein:" -tutorial.geometry.upload.details: "{sizeofVertexVerticesLength} ergibt drei Vertices zu 28 Bytes, insgesamt 84 Bytes. {bufferUsagesVertex} deklariert Vertex-Eingabezugriff, {cpuWriteOnly} ermöglicht die direkte CPU-Initialisierung. Der Stride beschreibt die Elementgröße; das anschließende Eingabelayout bestimmt die Interpretation jedes Attributs." -tutorial.geometry.upload.guidance: "Die Allokation initialisiert den Inhalt nicht. {upload} kopiert das Array ab Ziel-Byte-Offset 0 mit dem Quellzeiger und der Bytezahl der Datenbeschreibung." -tutorial.geometry.upload.imports: "Ergänzen Sie {bufferAlias} bei den using-Direktiven in {programCs}, um den Puffertyp von Zenith.NET von {systemBuffer} zu unterscheiden." -tutorial.geometry.upload.notes: "Setzen Sie {vertexBufferDispose} direkt vor {swapChainDispose} in die Bereinigung am Ende von {programCs}. GPU-only-Speicher und Transfer-Uploads für größere Geometrie erläutert {link}." +tutorial.geometry.format.details: '{file} beschränkt den Typ auf {programCs}, und {layoutKindSequential} erhält die Deklarationsreihenfolge seiner Felder. {position} enthält drei 32-Bit-Gleitkommazahlen und beginnt am Byte-Offset 0; {color} enthält vier und beginnt am Byte-Offset 12. Ein Vertex belegt damit 28 Bytes. Das Eingabelayout beschreibt diese Anordnung, damit die GPU die Felder korrekt liest.' +tutorial.geometry.format.imports: 'Ergänzen Sie am Anfang von {programCs} diese using-Direktiven für die Vektortypen und das Attribut zur Festlegung des Strukturlayouts:' +tutorial.geometry.format.title: 'Vertexdarstellung' +tutorial.geometry.title: 'Vertexdaten' +tutorial.geometry.upload.context: '{fixed} verhindert, dass die Garbage Collection das Array verschiebt, solange dessen Adresse verwendet wird. Bei diesem CPU-beschreibbaren Puffer mappt {upload} den Speicher, kopiert die Daten und hebt das Mapping vor der Rückkehr auf. Das Array muss daher nur während des Aufrufs fixiert bleiben. Laden Sie die Vertices einmal bei der Initialisierung hoch und geben Sie den Puffer erst nach Abschluss des Renderings frei.' +tutorial.geometry.upload.description: 'Speichern Sie die Vertices in einem {buffer}, damit die GPU sie beim Zeichnen lesen kann. Fügen Sie Allokation und Upload direkt nach dem Array ein:' +tutorial.geometry.upload.details: '{sizeofVertexVerticesLength} ergibt drei Vertices zu 28 Bytes, insgesamt 84 Bytes. {bufferUsagesVertex} deklariert Vertex-Eingabezugriff, {cpuWriteOnly} ermöglicht die direkte CPU-Initialisierung. Der Stride beschreibt die Elementgröße; das anschließende Eingabelayout bestimmt die Interpretation jedes Attributs.' +tutorial.geometry.upload.guidance: 'Die Allokation initialisiert den Inhalt nicht. {upload} kopiert das Array ab Ziel-Byte-Offset 0 mit dem Quellzeiger und der Bytezahl der Datenbeschreibung.' +tutorial.geometry.upload.imports: 'Ergänzen Sie {bufferAlias} bei den using-Direktiven in {programCs}, um den Puffertyp von Zenith.NET von {systemBuffer} zu unterscheiden.' +tutorial.geometry.upload.notes: 'Setzen Sie {vertexBufferDispose} direkt vor {swapChainDispose} in die Bereinigung am Ende von {programCs}. GPU-only-Speicher und Transfer-Uploads für größere Geometrie erläutert {link}.' tutorial.geometry.upload.notes.link: Ressourcenverwaltung -tutorial.geometry.upload.title: "Pufferallokation und Upload" -tutorial.input.description: "Die GPU muss wissen, wo Attribute wie Position und Farbe gespeichert sind. Das Eingabelayout gibt Format und Byte-Offset jedes Attributs sowie den Stride an, also den Byte-Abstand zum nächsten Vertex. Fügen Sie diesen Code nach der Shader-Erstellung ein:" -tutorial.input.details: "{inputLayoutAdd} fügt jedes Attribut unmittelbar nach dem vorherigen ein und erhöht den Stride um die Größe des neu hinzugefügten Attributs. Die Offsets ergeben sich aus den angegebenen Formaten; die C#-Struktur wird dabei nicht untersucht. Für diese beiden Felder entsteht folgendes Layout:" -tutorial.input.guidance: "Der Standardwert von {semanticIndex} ist 0 und entspricht damit {pOSITION0} und {cOLOR0} im Shader. Position und Farbe stehen gemeinsam in einem Vertexpuffer, weshalb die Pipeline ein Eingabelayout an Slot 0 verwendet. Passen Sie dieses Layout an, wenn sich Feldreihenfolge oder Auffüllung der C#-Struktur ändern." +tutorial.geometry.upload.title: 'Pufferallokation und Upload' +tutorial.input.description: 'Die GPU muss wissen, wo Attribute wie Position und Farbe gespeichert sind. Das Eingabelayout gibt Format und Byte-Offset jedes Attributs sowie den Stride an, also den Byte-Abstand zum nächsten Vertex. Fügen Sie diesen Code nach der Shader-Erstellung ein:' +tutorial.input.details: '{inputLayoutAdd} fügt jedes Attribut unmittelbar nach dem vorherigen ein und erhöht den Stride um die Größe des neu hinzugefügten Attributs. Die Offsets ergeben sich aus den angegebenen Formaten; die C#-Struktur wird dabei nicht untersucht. Für diese beiden Felder entsteht folgendes Layout:' +tutorial.input.guidance: 'Der Standardwert von {semanticIndex} ist 0 und entspricht damit {pOSITION0} und {cOLOR0} im Shader. Position und Farbe stehen gemeinsam in einem Vertexpuffer, weshalb die Pipeline ein Eingabelayout an Slot 0 verwendet. Passen Sie dieses Layout an, wenn sich Feldreihenfolge oder Auffüllung der C#-Struktur ändern.' tutorial.input.table.headings.byteOffset: Byte-Offset -tutorial.input.table.headings.cField: "C#-Feld" +tutorial.input.table.headings.cField: 'C#-Feld' tutorial.input.table.headings.format: Format tutorial.input.table.headings.shaderInput: Shader-Eingabe -tutorial.input.table.nextVertex.cField: "Nächster Vertex" -tutorial.input.table.nextVertex.format: "Gesamter Stride: 28 Bytes" +tutorial.input.table.nextVertex.cField: 'Nächster Vertex' +tutorial.input.table.nextVertex.format: 'Gesamter Stride: 28 Bytes' tutorial.input.table.nextVertex.shaderInput: Nächster Eingabedatensatz -tutorial.input.table.vertexColor.format: "{float4} (16 Bytes)" -tutorial.input.table.vertexPosition.format: "{float3} (12 Bytes)" -tutorial.input.title: "Vertex-Eingabelayout" -tutorial.lifecycle.description: "Jeder Frame folgt dieser Sequenz:" -tutorial.lifecycle.details: "Nach dem Schließen des Fensters kehrt {run} zurück, und die Ausführung wird mit der Bereinigung fortgesetzt. Da jeder Frame bereits auf den Abschluss seiner eingereichten Befehle gewartet hat, können die dafür verwendeten Ressourcen nun freigegeben werden. Nach {windowRun} steht die vollständige Bereinigung:" -tutorial.lifecycle.guidance: "Geben Sie die Swapchain vor ihrem nativen Fenster und den Kontext nach seinen Ressourcen frei. Eingereichte Befehlspuffer werden von der Warteschlange wiederverwendet; die Ausgabetextur wird von der Swapchain verwaltet. Beide benötigen daher keinen eigenen {dispose}-Aufruf." -tutorial.lifecycle.title: "Frame-Ablauf und Bereinigung" -tutorial.pipeline.behavior: "Erstellen Sie nach dem Eingabelayout die Pipeline:" -tutorial.pipeline.context: "{cullNone} deaktiviert das Face-Culling. Das Dreieck wird dadurch gezeichnet, unabhängig davon, ob seine Vertices im oder gegen den Uhrzeigersinn angeordnet erscheinen." -tutorial.pipeline.description: "Eine {graphicsPipeline} verbindet das Vertexlayout und die beiden Shader mit den Einstellungen für die Zusammenstellung der Primitive und die Ausgabe in Attachments." -tutorial.pipeline.details: "Die Shader verarbeiten Vertices und Fragmente. Die übrigen Pipeline-Einstellungen bestimmen die Primitivzusammenstellung, das Face-Culling, den Tiefentest und das Blending:" -tutorial.pipeline.guidance: "Das Farbformat muss dem Renderpass-Attachment entsprechen und wird deshalb aus {swapChainDescFormat} übernommen. {count1} legt ein Sample pro Pixel fest." -tutorial.pipeline.item: "{triangleList} setzt jeweils drei aufeinanderfolgende Vertices zu einem Dreieck zusammen." -tutorial.pipeline.notes: "{depthNone} deaktiviert Tiefentest und Tiefenschreiben entsprechend dem fehlenden Tiefen-Attachment." -tutorial.pipeline.reference: "{opaque} deaktiviert Blending. Die Fragmentfarbe ersetzt damit den Hintergrund innerhalb des Dreiecks." -tutorial.pipeline.title: "Grafikpipeline" -tutorial.pipeline.usage: "Shader-Objekte dürfen nach der Pipeline-Erstellung freigegeben werden. Geben Sie die Pipeline dagegen erst nach Abschluss des Renderings frei und ergänzen Sie dafür {pipelineDispose} vor {vertexBufferDispose} in der Bereinigung." -tutorial.presentation.title: "Grafikkontext und Präsentation" -tutorial.project.context: "Aktivieren Sie {emphasis} ({allowUnsafeBlocks}) in den Buildeinstellungen. Die nativen Fensteraufrufe und der Vertexupload benötigen unsicheren Code." +tutorial.input.table.vertexColor.format: '{float4} (16 Bytes)' +tutorial.input.table.vertexPosition.format: '{float3} (12 Bytes)' +tutorial.input.title: 'Vertex-Eingabelayout' +tutorial.lifecycle.description: 'Jeder Frame folgt dieser Sequenz:' +tutorial.lifecycle.details: 'Nach dem Schließen des Fensters kehrt {run} zurück, und die Ausführung wird mit der Bereinigung fortgesetzt. Da jeder Frame bereits auf den Abschluss seiner eingereichten Befehle gewartet hat, können die dafür verwendeten Ressourcen nun freigegeben werden. Nach {windowRun} steht die vollständige Bereinigung:' +tutorial.lifecycle.guidance: 'Geben Sie die Swapchain vor ihrem nativen Fenster und den Kontext nach seinen Ressourcen frei. Eingereichte Befehlspuffer werden von der Warteschlange wiederverwendet; die Ausgabetextur wird von der Swapchain verwaltet. Beide benötigen daher keinen eigenen {dispose}-Aufruf.' +tutorial.lifecycle.title: 'Frame-Ablauf und Bereinigung' +tutorial.pipeline.behavior: 'Erstellen Sie nach dem Eingabelayout die Pipeline:' +tutorial.pipeline.context: '{cullNone} deaktiviert das Face-Culling. Das Dreieck wird dadurch gezeichnet, unabhängig davon, ob seine Vertices im oder gegen den Uhrzeigersinn angeordnet erscheinen.' +tutorial.pipeline.description: 'Eine {graphicsPipeline} verbindet das Vertexlayout und die beiden Shader mit den Einstellungen für die Zusammenstellung der Primitive und die Ausgabe in Attachments.' +tutorial.pipeline.details: 'Die Shader verarbeiten Vertices und Fragmente. Die übrigen Pipeline-Einstellungen bestimmen die Primitivzusammenstellung, das Face-Culling, den Tiefentest und das Blending:' +tutorial.pipeline.guidance: 'Das Farbformat muss dem Renderpass-Attachment entsprechen und wird deshalb aus {swapChainDescFormat} übernommen. {count1} legt ein Sample pro Pixel fest.' +tutorial.pipeline.item: '{triangleList} setzt jeweils drei aufeinanderfolgende Vertices zu einem Dreieck zusammen.' +tutorial.pipeline.notes: '{depthNone} deaktiviert Tiefentest und Tiefenschreiben entsprechend dem fehlenden Tiefen-Attachment.' +tutorial.pipeline.reference: '{opaque} deaktiviert Blending. Die Fragmentfarbe ersetzt damit den Hintergrund innerhalb des Dreiecks.' +tutorial.pipeline.title: 'Grafikpipeline' +tutorial.pipeline.usage: 'Shader-Objekte dürfen nach der Pipeline-Erstellung freigegeben werden. Geben Sie die Pipeline dagegen erst nach Abschluss des Renderings frei und ergänzen Sie dafür {pipelineDispose} vor {vertexBufferDispose} in der Bereinigung.' +tutorial.presentation.title: 'Grafikkontext und Präsentation' +tutorial.project.context: 'Aktivieren Sie {emphasis} ({allowUnsafeBlocks}) in den Buildeinstellungen. Die nativen Fensteraufrufe und der Vertexupload benötigen unsicheren Code.' tutorial.project.context.emphasis: Unsicheren Code zulassen -tutorial.project.description: "Erstellen Sie ein C#-Konsolenprojekt namens {firstTriangle} mit .NET 10 als Zielframework." -tutorial.project.details: "Fügen Sie dem Projekt die folgenden NuGet-Pakete hinzu:" -tutorial.project.guidance: "{zenithNET} liefert die gemeinsame API, die drei Backend-Pakete ihre Plattformimplementierungen. {zenithNETCompiler} übersetzt die unten eingeführten Slang-Shader für das Backend. Silk.NET übernimmt Fenster und Ereignisse." -tutorial.project.title: "Projekteinrichtung" -tutorial.requirements.context: "Das {link} und sein {detail} dienen als Referenzimplementierungen für dieses Tutorial." +tutorial.project.description: 'Erstellen Sie ein C#-Konsolenprojekt namens {firstTriangle} mit .NET 10 als Zielframework.' +tutorial.project.details: 'Fügen Sie dem Projekt die folgenden NuGet-Pakete hinzu:' +tutorial.project.guidance: '{zenithNET} liefert die gemeinsame API, die drei Backend-Pakete ihre Plattformimplementierungen. {zenithNETCompiler} übersetzt die unten eingeführten Slang-Shader für das Backend. Silk.NET übernimmt Fenster und Ereignisse.' +tutorial.project.title: 'Projekteinrichtung' +tutorial.requirements.context: 'Das {link} und sein {detail} dienen als Referenzimplementierungen für dieses Tutorial.' tutorial.requirements.context.detail: gemeinsamer Host tutorial.requirements.context.link: Hallo-Dreieck-Beispiel -tutorial.requirements.description: "Sie benötigen das {emphasis} und C#-Grundkenntnisse. Die Anwendung verwendet das Zielframework {net10}. GPU und Treiber müssen das für Ihre Plattform gewählte Backend unterstützen:" +tutorial.requirements.description: 'Sie benötigen das {emphasis} und C#-Grundkenntnisse. Die Anwendung verwendet das Zielframework {net10}. GPU und Treiber müssen das für Ihre Plattform gewählte Backend unterstützen:' tutorial.requirements.description.emphasis: .NET 10 SDK -tutorial.requirements.guidance: "Zenith.NET rendert in ein von der Anwendung bereitgestelltes Präsentationsziel. Silk.NET.Windowing erstellt das Fenster und verarbeitet Ereignisse. Unter macOS dient ein in {cAMetalLayerCs} repräsentierter Metal-Layer als Ziel; der Fenster-Helper verbindet ihn mit dem Fenster." +tutorial.requirements.guidance: 'Zenith.NET rendert in ein von der Anwendung bereitgestelltes Präsentationsziel. Silk.NET.Windowing erstellt das Fenster und verarbeitet Ereignisse. Unter macOS dient ein in {cAMetalLayerCs} repräsentierter Metal-Layer als Ziel; der Fenster-Helper verbindet ihn mit dem Fenster.' tutorial.requirements.table.headings.graphicsBackend: Grafik-Backend tutorial.requirements.table.headings.platform: Plattform tutorial.requirements.table.linux.graphicsBackend: Vulkan 1.4 -tutorial.requirements.table.linux.platform: "Linux (X11 oder XWayland)" +tutorial.requirements.table.linux.platform: 'Linux (X11 oder XWayland)' tutorial.requirements.table.macOS.graphicsBackend: Metal 4 tutorial.requirements.table.macOS.platform: macOS tutorial.requirements.table.windows.graphicsBackend: DirectX 12 tutorial.requirements.table.windows.platform: Windows -tutorial.requirements.title: "Voraussetzungen" -tutorial.resize.context: "Erstellen und starten Sie die Anwendung erneut. Auch beim Ändern der Fenstergröße sollte der Hintergrund das gesamte Fenster ausfüllen: Jeder neue Renderpass übernimmt die Abmessungen des angepassten Attachments für Viewport und Scissor. Behalten Sie den Render-Callback bei; in diesem Pass wird später das Dreieck gezeichnet." -tutorial.resize.description: "Die Swapchain muss Änderungen der Framebuffer-Größe übernehmen. Registrieren Sie nach dem Render-Callback und vor {windowRun} einen Callback für {framebufferResize}:" -tutorial.resize.details: "Reagieren Sie auf {link}, die in Pixeln angegeben werden, statt auf Änderungen der logischen Fenstergröße. Wird beim Minimieren eine der beiden Framebuffer-Abmessungen null, lässt der Resize-Callback die Swapchain unverändert. Auch der Render-Callback kehrt bei einer Nullgröße sofort zurück. Das Rendering wird erst fortgesetzt, wenn wieder eine nutzbare Größe vorliegt." +tutorial.requirements.title: 'Voraussetzungen' +tutorial.resize.context: 'Erstellen und starten Sie die Anwendung erneut. Auch beim Ändern der Fenstergröße sollte der Hintergrund das gesamte Fenster ausfüllen: Jeder neue Renderpass übernimmt die Abmessungen des angepassten Attachments für Viewport und Scissor. Behalten Sie den Render-Callback bei; in diesem Pass wird später das Dreieck gezeichnet.' +tutorial.resize.description: 'Die Swapchain muss Änderungen der Framebuffer-Größe übernehmen. Registrieren Sie nach dem Render-Callback und vor {windowRun} einen Callback für {framebufferResize}:' +tutorial.resize.details: 'Reagieren Sie auf {link}, die in Pixeln angegeben werden, statt auf Änderungen der logischen Fenstergröße. Wird beim Minimieren eine der beiden Framebuffer-Abmessungen null, lässt der Resize-Callback die Swapchain unverändert. Auch der Render-Callback kehrt bei einer Nullgröße sofort zurück. Das Rendering wird erst fortgesetzt, wenn wieder eine nutzbare Größe vorliegt.' tutorial.resize.details.link: Framebuffer-Größenänderungen -tutorial.resize.guidance: "Der Render-Callback wartet vor {present}, bis die eingereichten Befehle des Frames abgeschlossen sind. Der Resize-Callback kann die Swapchain-Bilder daher ersetzen, ohne noch laufende Arbeit eines früheren Frames zu beeinträchtigen. Der Artikel {link} erläutert den Zusammenhang zwischen GPU-Abschluss und Ressourcenlebensdauer." +tutorial.resize.guidance: 'Der Render-Callback wartet vor {present}, bis die eingereichten Befehle des Frames abgeschlossen sind. Der Resize-Callback kann die Swapchain-Bilder daher ersetzen, ohne noch laufende Arbeit eines früheren Frames zu beeinträchtigen. Der Artikel {link} erläutert den Zusammenhang zwischen GPU-Abschluss und Ressourcenlebensdauer.' tutorial.resize.guidance.link: Synchronisation -tutorial.resize.title: "Größenänderungen" -tutorial.shaders.compilation.context: "Mit {appContextBaseDirectory} wird die kopierte Shader-Datei aus dem Ausgabeverzeichnis der Anwendung geladen. Ihr Speicherort wird deshalb auch dann korrekt ermittelt, wenn die Anwendung aus einem anderen Arbeitsverzeichnis gestartet wird." -tutorial.shaders.compilation.description: "Setzen Sie für {triangleSlang} die Dateieigenschaft {emphasis} auf {detail}. Der Build kopiert die Shader-Datei damit neben die ausführbare Datei." +tutorial.resize.title: 'Größenänderungen' +tutorial.shaders.compilation.context: 'Mit {appContextBaseDirectory} wird die kopierte Shader-Datei aus dem Ausgabeverzeichnis der Anwendung geladen. Ihr Speicherort wird deshalb auch dann korrekt ermittelt, wenn die Anwendung aus einem anderen Arbeitsverzeichnis gestartet wird.' +tutorial.shaders.compilation.description: 'Setzen Sie für {triangleSlang} die Dateieigenschaft {emphasis} auf {detail}. Der Build kopiert die Shader-Datei damit neben die ausführbare Datei.' tutorial.shaders.compilation.description.detail: Kopieren, wenn neuer tutorial.shaders.compilation.description.emphasis: In Ausgabeverzeichnis kopieren -tutorial.shaders.compilation.details: "Fügen Sie in {programCs} nach dem Vertexupload und vor dem Render-Callback die Shader-Initialisierung ein:" -tutorial.shaders.compilation.guidance: "{zenithCompiler} kompiliert den Quelltext für {contextGraphicsApi}; {createShader} erstellt aus der kompilierten Beschreibung ein Shader-Objekt. Die Einstiegspunktnamen {vSMain} und {fSMain} wählen die beiden Funktionen aus der Slang-Datei aus." -tutorial.shaders.compilation.title: "Shader kompilieren" -tutorial.shaders.context: "{fSInput} verbindet die beiden Shader-Stufen. Der Vertex-Shader schreibt eine Position im Clipraum nach {sVPOSITION}; daraus ermittelt die GPU den sichtbaren Teil des Dreiecks. {cOLOR0} enthält die Vertexfarbe, die vor der Übergabe an den Fragment-Shader über das Dreieck interpoliert wird. Typ und Semantik dieses Feldes müssen zwischen den Stufen übereinstimmen." -tutorial.shaders.description: "Shader sind Programme, die auf der GPU laufen. Der Vertex-Shader bestimmt die Position jedes Vertex, der Fragment-Shader die Farbe an den vom Dreieck bedeckten Bildpositionen. Beide Stufen stehen in einer Slang-Datei und haben jeweils einen eigenen Einstiegspunkt, also eine Funktion, mit der die Ausführung beginnt." -tutorial.shaders.details: "Erstellen Sie {triangleSlang} mit diesen Eingabe- und Ausgabestrukturen:" -tutorial.shaders.fragment.description: "Ergänzen Sie den Fragment-Einstiegspunkt in derselben Datei:" -tutorial.shaders.fragment.details: "Die Rasterisierung ermittelt die vom Dreieck bedeckten Bildpositionen und erzeugt dort Fragmente. Jedes Fragment erhält eine aus den drei Vertexfarben interpolierte Farbe. {fSMain} gibt diese Farbe zurück; {sVTARGET} leitet das Ergebnis an das erste Farb-Attachment weiter." -tutorial.shaders.fragment.title: "Fragment-Shading" -tutorial.shaders.guidance: "{vSInput} definiert die Vertex-Shader-Eingaben. {pOSITION0} und {cOLOR0} identifizieren Attribute über ihre Semantik; C#-Feldnamen stellen diese Zuordnung nicht her." -tutorial.shaders.title: "Shader-Stufen" -tutorial.shaders.vertex.description: "Ergänzen Sie den Vertex-Einstiegspunkt in {triangleSlang}:" -tutorial.shaders.vertex.details: "Die GPU ruft den Einstiegspunkt für jeden Vertex auf, ergänzt die homogene Koordinate {w} und übergibt die Farbe. Nach der Vertexverarbeitung wird die Position durch w geteilt. Hier ist w = 1; x, y und z bleiben unverändert und entsprechen normalisierten Gerätekoordinaten." -tutorial.shaders.vertex.title: "Vertex-Shading" -tutorial.surface.description: "Definieren Sie das native Präsentationsziel {emphasis}:" +tutorial.shaders.compilation.details: 'Fügen Sie in {programCs} nach dem Vertexupload und vor dem Render-Callback die Shader-Initialisierung ein:' +tutorial.shaders.compilation.guidance: '{zenithCompiler} kompiliert den Quelltext für {contextGraphicsApi}; {createShader} erstellt aus der kompilierten Beschreibung ein Shader-Objekt. Die Einstiegspunktnamen {vSMain} und {fSMain} wählen die beiden Funktionen aus der Slang-Datei aus.' +tutorial.shaders.compilation.title: 'Shader kompilieren' +tutorial.shaders.context: '{fSInput} verbindet die beiden Shader-Stufen. Der Vertex-Shader schreibt eine Position im Clipraum nach {sVPOSITION}; daraus ermittelt die GPU den sichtbaren Teil des Dreiecks. {cOLOR0} enthält die Vertexfarbe, die vor der Übergabe an den Fragment-Shader über das Dreieck interpoliert wird. Typ und Semantik dieses Feldes müssen zwischen den Stufen übereinstimmen.' +tutorial.shaders.description: 'Shader sind Programme, die auf der GPU laufen. Der Vertex-Shader bestimmt die Position jedes Vertex, der Fragment-Shader die Farbe an den vom Dreieck bedeckten Bildpositionen. Beide Stufen stehen in einer Slang-Datei und haben jeweils einen eigenen Einstiegspunkt, also eine Funktion, mit der die Ausführung beginnt.' +tutorial.shaders.details: 'Erstellen Sie {triangleSlang} mit diesen Eingabe- und Ausgabestrukturen:' +tutorial.shaders.fragment.description: 'Ergänzen Sie den Fragment-Einstiegspunkt in derselben Datei:' +tutorial.shaders.fragment.details: 'Die Rasterisierung ermittelt die vom Dreieck bedeckten Bildpositionen und erzeugt dort Fragmente. Jedes Fragment erhält eine aus den drei Vertexfarben interpolierte Farbe. {fSMain} gibt diese Farbe zurück; {sVTARGET} leitet das Ergebnis an das erste Farb-Attachment weiter.' +tutorial.shaders.fragment.title: 'Fragment-Shading' +tutorial.shaders.guidance: '{vSInput} definiert die Vertex-Shader-Eingaben. {pOSITION0} und {cOLOR0} identifizieren Attribute über ihre Semantik; C#-Feldnamen stellen diese Zuordnung nicht her.' +tutorial.shaders.title: 'Shader-Stufen' +tutorial.shaders.vertex.description: 'Ergänzen Sie den Vertex-Einstiegspunkt in {triangleSlang}:' +tutorial.shaders.vertex.details: 'Die GPU ruft den Einstiegspunkt für jeden Vertex auf, ergänzt die homogene Koordinate {w} und übergibt die Farbe. Nach der Vertexverarbeitung wird die Position durch w geteilt. Hier ist w = 1; x, y und z bleiben unverändert und entsprechen normalisierten Gerätekoordinaten.' +tutorial.shaders.vertex.title: 'Vertex-Shading' +tutorial.surface.description: 'Definieren Sie das native Präsentationsziel {emphasis}:' tutorial.surface.description.emphasis: nach {windowCenter} und vor {windowRun} -tutorial.surface.details: "Der Framebuffer ist das Fensterbild in Pixeln. {surface} beschreibt das native Präsentationsziel und seine Abmessungen; {framebufferSize} liefert die Pixelgröße. Bei aktiver Anzeigeskalierung kann sie von der logischen Fenstergröße abweichen." -tutorial.surface.guidance: "Die Oberflächenbeschreibung liefert die nativen Handles des gewählten Backends: ein Win32-Fenster unter Windows, X11-Display und -Fenster unter Linux oder den angebundenen Metal-Layer unter macOS." -tutorial.surface.title: "Native Oberfläche" -tutorial.swapChain.context: "Die Swapchain hängt von Kontext und Fenster ab. Ersetzen Sie {windowDispose} am Ende von {programCs} durch diese Freigabereihenfolge:" -tutorial.swapChain.description: "Erstellen Sie unmittelbar nach der Oberflächenbeschreibung die Swapchain:" -tutorial.swapChain.details: "Die {swapChain} verwaltet die angezeigten Bilder. {drawable} liefert das aktuelle Bild als {texture}, den Bildressourcentyp der API. Nach dem Rendering fordert {present} die Anzeige an und wechselt zur nächsten Ausgabetextur." -tutorial.swapChain.guidance: "{b8G8R8A8UNorm} speichert vier 8-Bit-Kanäle in Blau-, Grün-, Rot- und Alpha-Reihenfolge. {uNorm} bildet die Ganzzahlen von 0 bis 255 auf den Bereich von 0 bis 1 ab. Der Shader gibt die Farbe weiterhin in der logischen RGBA-Reihenfolge aus; das Format bestimmt ihre Speicherung. Die Pipeline übernimmt das Farbformat aus {swapChainDescFormat}, damit es zum Attachment passt." -tutorial.swapChain.title: "Swapchain" +tutorial.surface.details: 'Der Framebuffer ist das Fensterbild in Pixeln. {surface} beschreibt das native Präsentationsziel und seine Abmessungen; {framebufferSize} liefert die Pixelgröße. Bei aktiver Anzeigeskalierung kann sie von der logischen Fenstergröße abweichen.' +tutorial.surface.guidance: 'Die Oberflächenbeschreibung liefert die nativen Handles des gewählten Backends: ein Win32-Fenster unter Windows, X11-Display und -Fenster unter Linux oder den angebundenen Metal-Layer unter macOS.' +tutorial.surface.title: 'Native Oberfläche' +tutorial.swapChain.context: 'Die Swapchain hängt von Kontext und Fenster ab. Ersetzen Sie {windowDispose} am Ende von {programCs} durch diese Freigabereihenfolge:' +tutorial.swapChain.description: 'Erstellen Sie unmittelbar nach der Oberflächenbeschreibung die Swapchain:' +tutorial.swapChain.details: 'Die {swapChain} verwaltet die angezeigten Bilder. {drawable} liefert das aktuelle Bild als {texture}, den Bildressourcentyp der API. Nach dem Rendering fordert {present} die Anzeige an und wechselt zur nächsten Ausgabetextur.' +tutorial.swapChain.guidance: '{b8G8R8A8UNorm} speichert vier 8-Bit-Kanäle in Blau-, Grün-, Rot- und Alpha-Reihenfolge. {uNorm} bildet die Ganzzahlen von 0 bis 255 auf den Bereich von 0 bis 1 ab. Der Shader gibt die Farbe weiterhin in der logischen RGBA-Reihenfolge aus; das Format bestimmt ihre Speicherung. Die Pipeline übernimmt das Farbformat aus {swapChainDescFormat}, damit es zum Attachment passt.' +tutorial.swapChain.title: 'Swapchain' tutorial.title: Erstes Dreieck -tutorial.troubleshooting.description: "Konsolendiagnosen und die drei Kontrollpunkte grenzen den Fehler ein:" -tutorial.troubleshooting.details: "Der {link} und der {detail} dienen als Referenz für Vertexdaten, Eingabelayout und Zeichenbefehle. Das Beispiel verwaltet Fenster und Befehlseinreichung in einem gemeinsamen Host; dieses Tutorial belässt den Anwendungsablauf in {programCs}. Das Beispiel {context} ergänzt indexiertes Zeichnen, Transformationen und Tiefentests." +tutorial.troubleshooting.description: 'Konsolendiagnosen und die drei Kontrollpunkte grenzen den Fehler ein:' +tutorial.troubleshooting.details: 'Der {link} und der {detail} dienen als Referenz für Vertexdaten, Eingabelayout und Zeichenbefehle. Das Beispiel verwaltet Fenster und Befehlseinreichung in einem gemeinsamen Host; dieses Tutorial belässt den Anwendungsablauf in {programCs}. Das Beispiel {context} ergänzt indexiertes Zeichnen, Transformationen und Tiefentests.' tutorial.troubleshooting.details.context: Rotierender Würfel tutorial.troubleshooting.details.detail: Slang-Shader tutorial.troubleshooting.details.link: Beispiel-Renderer @@ -497,17 +497,17 @@ tutorial.troubleshooting.table.drawing.symptom: Der Hintergrund erscheint, aber tutorial.troubleshooting.table.headings.check: Prüfung tutorial.troubleshooting.table.headings.symptom: Symptom tutorial.troubleshooting.table.input.check: Überprüfen Sie den Stride von 28 Bytes und die Positions-/Farboffsets von 0 und 12. -tutorial.troubleshooting.table.input.symptom: "Vertexpositionen oder -farben sind fehlerhaft" +tutorial.troubleshooting.table.input.symptom: 'Vertexpositionen oder -farben sind fehlerhaft' tutorial.troubleshooting.table.shaders.check: Überprüfen Sie die kopierte Datei {triangleSlang}, die Schreibweise des Einstiegspunkts und die vom Compiler gemeldete Diagnose. tutorial.troubleshooting.table.shaders.symptom: Der Schritt mit der Hintergrundfarbe funktioniert, aber das Laden der Shader schlägt fehl tutorial.troubleshooting.table.window.check: Bestätigen Sie, dass das .NET-Projekt kompiliert wird und der reine Fensterschritt in einer Desktop-Sitzung ausgeführt wird. Überprüfen Sie unter Linux, ob X11 oder XWayland verfügbar ist. tutorial.troubleshooting.table.window.symptom: Es öffnet sich kein Fenster -tutorial.troubleshooting.title: "Fehlerdiagnose" -tutorial.window.description: "Laden Sie {cocoaHelperCs} in das Projekt herunter. Die Hilfsklasse bindet den Metal-Layer an das macOS-Fenster." -tutorial.window.details: "Ersetzen Sie den erzeugten Inhalt von {programCs} durch den folgenden Code. Er verwendet Top-Level-Anweisungen, die ohne explizite {main}-Methode der Reihe nach laufen. Die folgenden Abschnitte geben jeweils die Stelle für zusätzlichen Code an:" -tutorial.window.guidance: "{graphicsAPINone} überlässt den Grafikkontext Zenith.NET. {initialize} erstellt das native Fenster und macht die Handles des Fenstersystems verfügbar. {center} platziert das Fenster in der Bildschirmmitte. {run} verarbeitet Ereignisse bis zum Schließen; danach gibt {dispose} das Fenster frei." -tutorial.window.notes: "Erstellen und starten Sie die Anwendung. Prüfen Sie, ob sich das Fenster öffnen, verschieben, in der Größe ändern und schließen lässt. Sein Inhalt ist noch nicht definiert, da keine Renderbefehle eingereicht wurden. Schließen Sie das Fenster, bevor Sie fortfahren." -tutorial.window.title: "Fenstererstellung" +tutorial.troubleshooting.title: 'Fehlerdiagnose' +tutorial.window.description: 'Laden Sie {cocoaHelperCs} in das Projekt herunter. Die Hilfsklasse bindet den Metal-Layer an das macOS-Fenster.' +tutorial.window.details: 'Ersetzen Sie den erzeugten Inhalt von {programCs} durch den folgenden Code. Er verwendet Top-Level-Anweisungen, die ohne explizite {main}-Methode der Reihe nach laufen. Die folgenden Abschnitte geben jeweils die Stelle für zusätzlichen Code an:' +tutorial.window.guidance: '{graphicsAPINone} überlässt den Grafikkontext Zenith.NET. {initialize} erstellt das native Fenster und macht die Handles des Fenstersystems verfügbar. {center} platziert das Fenster in der Bildschirmmitte. {run} verarbeitet Ereignisse bis zum Schließen; danach gibt {dispose} das Fenster frei.' +tutorial.window.notes: 'Erstellen und starten Sie die Anwendung. Prüfen Sie, ob sich das Fenster öffnen, verschieben, in der Größe ändern und schließen lässt. Sein Inhalt ist noch nicht definiert, da keine Renderbefehle eingereicht wurden. Schließen Sie das Fenster, bevor Sie fortfahren.' +tutorial.window.title: 'Fenstererstellung' ui.action.copy: Kopieren ui.action.navigate: Navigieren ui.action.open: Öffnen @@ -530,12 +530,12 @@ ui.content.tutorial: Tutorial ui.contents.close: Inhaltsverzeichnis schließen ui.contents.open: Inhaltsverzeichnis öffnen ui.contents.title: Inhalt -ui.footer.caption: "Modernes RHI für .NET" +ui.footer.caption: 'Modernes RHI für .NET' ui.footer.label: Fußzeile ui.language.label: Sprache ui.language.unavailable: Nicht übersetzt ui.members.clear: Membersuche löschen -ui.members.close: "Membersuche schließen" +ui.members.close: 'Membersuche schließen' ui.members.empty: Keine passenden Member. ui.members.open: Zum Member wechseln ui.members.placeholder: Name oder Signatur… @@ -552,7 +552,7 @@ ui.outline.title: Auf dieser Seite ui.reference.assembly: Assembly ui.reference.classes: Klassen ui.reference.constructors: Konstruktoren -ui.reference.declaration: "C#-Typdeklaration" +ui.reference.declaration: 'C#-Typdeklaration' ui.reference.delegates: Delegaten ui.reference.derived: Abgeleitete Typen ui.reference.enums: Enumerationen @@ -588,6 +588,6 @@ ui.search.loading: Suche wird geladen… ui.search.more: Weitere Ergebnisse anzeigen ui.search.pending: Suche läuft… ui.search.placeholder: Wonach suchen Sie? -ui.search.resultCount: "Ergebnisse: {count}" +ui.search.resultCount: 'Ergebnisse: {count}' ui.search.title: Dokumentation durchsuchen ui.search.unavailable: Die Suche ist nicht verfügbar. Sie können weiterhin die folgenden Seiten aufrufen. diff --git a/documents/locales/de-DE/translation.md b/documents/locales/de-DE/translation.md index 1dc3769d..6896825a 100644 --- a/documents/locales/de-DE/translation.md +++ b/documents/locales/de-DE/translation.md @@ -2,7 +2,7 @@ ## Ressourcen und Aufbau -Das [englische Ressourcenwörterbuch](../en-US/strings.yml) ist die einzige Textquelle. Die Projektregeln stehen im [Leitfaden zur Dokumentationspflege](../../authoring.md). Für eine neue Übersetzung die vollständige englische Datei als `strings.yml` in dieses Verzeichnis kopieren. Die erste Zeile `### YamlMime:Resources` und die UTF-8-Kodierung beibehalten. Spätere Änderungen mit dem englischen Stand abgleichen, ohne vorhandene Übersetzungen zu überschreiben. Diese `translation.md` bleibt dauerhaft erhalten und wird nicht auf der Website veröffentlicht. +Das [englische Ressourcenwörterbuch](../en-US/strings.yml) ist die einzige Textquelle. Die Projektregeln stehen im [Leitfaden zur Dokumentationspflege](../../maintenance.md). Für eine neue Übersetzung die vollständige englische Datei als `strings.yml` in dieses Verzeichnis kopieren. Die erste Zeile `### YamlMime:Resources` und die UTF-8-Kodierung beibehalten. Spätere Änderungen mit dem englischen Stand abgleichen, ohne vorhandene Übersetzungen zu überschreiben. Diese `translation.md` bleibt dauerhaft erhalten und wird nicht auf der Website veröffentlicht. Navigation, Kapitelreihenfolge, Anker, Links, Formatierung, Code und Bilder werden außerhalb von `locales/` gemeinsam gepflegt. Hier keine Artikel, TOCs, Vorlagen, Skripte oder Konfigurationen anlegen. @@ -65,21 +65,21 @@ Vor der Abgabe Schlüssel und Platzhalter abgleichen. Startseite, Learn-Einstieg ## Terminologie -| Englischer Begriff | Festgelegte Form | -| --- | --- | -| API / GPU / RHI | Abkürzungen beibehalten; nach dem Original erläutern | -| barrier | Barriere | -| buffer | Puffer; `Buffer` bleibt unverändert | -| command buffer | Befehlspuffer | -| command queue | Befehlswarteschlange | -| drawable | Ausgabetextur des aktuellen Frames; `Drawable` bleibt unverändert, nicht grundsätzlich als Swapchain-Bild bezeichnen | -| graphics context | Grafikkontext | -| pipeline | Pipeline | -| readback | Rücklesen von GPU-Daten | -| render pass | Renderpass | -| resource | Ressource | -| shader | Shader | -| swap chain | Swapchain | -| texture | Textur | -| timeline | Timeline | -| upload | Hochladen von Daten | +| Englischer Begriff | Festgelegte Form | +| ------------------ | -------------------------------------------------------------------------------------------------------------------- | +| API / GPU / RHI | Abkürzungen beibehalten; nach dem Original erläutern | +| barrier | Barriere | +| buffer | Puffer; `Buffer` bleibt unverändert | +| command buffer | Befehlspuffer | +| command queue | Befehlswarteschlange | +| drawable | Ausgabetextur des aktuellen Frames; `Drawable` bleibt unverändert, nicht grundsätzlich als Swapchain-Bild bezeichnen | +| graphics context | Grafikkontext | +| pipeline | Pipeline | +| readback | Rücklesen von GPU-Daten | +| render pass | Renderpass | +| resource | Ressource | +| shader | Shader | +| swap chain | Swapchain | +| texture | Textur | +| timeline | Timeline | +| upload | Hochladen von Daten | diff --git a/documents/locales/en-US/strings.yml b/documents/locales/en-US/strings.yml index 0e7d7f4e..aad0d256 100644 --- a/documents/locales/en-US/strings.yml +++ b/documents/locales/en-US/strings.yml @@ -1,8 +1,10 @@ ### YamlMime:Resources -concepts.execution.context.description: A {graphicsContext} connects the application to a GPU device through a particular +concepts.execution.context.description: + A {graphicsContext} connects the application to a GPU device through a particular backend and provides its graphics, compute, and transfer queues. Resources used together must belong to the same context; buffers, textures, shaders, pipelines, and their handles cannot be bound across contexts. -concepts.execution.context.details: '{capabilities} reports the device name and supported features. Use {rayTracingSupported} +concepts.execution.context.details: + '{capabilities} reports the device name and supported features. Use {rayTracingSupported} and {meshShadingSupported} to check support before creating the resources for those workloads. The {link} and {detail} samples show these checks during initialization.' concepts.execution.context.details.detail: mesh shading @@ -48,7 +50,8 @@ concepts.execution.queues.details: Separate queues allow independent workloads t do not necessarily correspond to independent hardware engines. Use additional queues when the work can benefit from overlapping execution. When one queue uses data produced by another, connect their submissions with an explicit dependency. -concepts.execution.queues.guidance: Within a queue, dependent operations can also require barriers or texture transitions +concepts.execution.queues.guidance: + Within a queue, dependent operations can also require barriers or texture transitions so that later accesses observe earlier writes. These memory dependencies are distinct from submission order; {link} explains how to express them. concepts.execution.queues.guidance.link: Synchronization @@ -61,7 +64,8 @@ concepts.execution.queues.table.headings.workToRecord: Supported work concepts.execution.queues.table.transferQueue.workToRecord: Upload, download and copy work, without drawing or compute dispatches. concepts.execution.queues.title: Queue selection -concepts.execution.recording.context: 'The queue reclaims completed command buffers for reuse. Obtain one with {queueCommandBuffer} +concepts.execution.recording.context: + 'The queue reclaims completed command buffers for reuse. Obtain one with {queueCommandBuffer} for each recording, record from one thread at a time, and submit it once. After submission, leave the buffer to the queue: do not modify, resubmit, or dispose it.' concepts.execution.recording.description: '{queueCommandBuffer} returns a {commandBuffer} with recording already @@ -106,7 +110,8 @@ concepts.platforms.integration.details: These implementations differ in how the concepts.platforms.integration.guidance: Add the integration package for your UI framework through NuGet. For Avalonia, use {avaloniaPackage}. concepts.platforms.integration.table.avalonia.integration: Avalonia -concepts.platforms.integration.table.avalonia.presentation: Renders to a texture and downloads pixels into a {writeableBitmap}. +concepts.platforms.integration.table.avalonia.presentation: + Renders to a texture and downloads pixels into a {writeableBitmap}. See {zenithViewCs} and {surfaceCs}. concepts.platforms.integration.table.headings.integration: Integration concepts.platforms.integration.table.headings.presentation: Presentation mechanism @@ -129,10 +134,10 @@ concepts.platforms.integration.title: Framework and presentation path concepts.platforms.lifecycle.context: Use {descWidth}, {descHeight}, {descFormat}, and {descSampleCount} from the drawable supplied by the render event when creating matching attachments. The event texture gives the render target's actual dimensions; they should not be inferred from the control's layout size or display scale. -concepts.platforms.lifecycle.description: 'The swap chain uses the framebuffer''s width and height in pixels, which - can differ from the window''s logical dimensions under display scaling. Defer rendering and swap-chain resizing +concepts.platforms.lifecycle.description: "The swap chain uses the framebuffer's width and height in pixels, which + can differ from the window's logical dimensions under display scaling. Defer rendering and swap-chain resizing while either dimension is zero. Obtain {swapChainDrawable} for each frame: the swap chain owns this texture and - may replace it after presentation or resizing.' + may replace it after presentation or resizing." concepts.platforms.lifecycle.details: When framebuffer dimensions change, wait for outstanding GPU uses of the old images before calling {swapChainResize}. To replace the native presentation target, pass its new surface description and handles to {swapChainRefresh} after those uses finish. At shutdown, release the swap chain before destroying @@ -150,7 +155,8 @@ concepts.platforms.ownership.description: The application owns the assigned cont concepts.platforms.ownership.details: Before replacing rendering resources, stop the view's frame activity and wait for the GPU work that uses them. Only then release the old resources or context. The application remains responsible for releasing the assigned context when the view is removed. -concepts.platforms.ownership.guidance: The shared {frameSchedulerCs} runs frame handlers through the view's UI dispatcher. +concepts.platforms.ownership.guidance: + The shared {frameSchedulerCs} runs frame handlers through the view's UI dispatcher. Keep those handlers focused on updating scene data and recording commands; lengthy CPU work there also delays the interface. concepts.platforms.ownership.title: Application and control ownership @@ -249,7 +255,7 @@ concepts.resources.transfers.description: 'Uploads copy CPU data into a GPU reso concepts.resources.transfers.details: Before calling these methods, resolve any conflicting accesses on other queues. A wait inside the method covers its own transfer; it does not establish a dependency on another queue. The direct mapped-memory paths rely entirely on the caller to wait for conflicting GPU accesses. -concepts.resources.transfers.guidance: "To submit transfers together with other GPU work, record them with {commandBufferUpload} or {commandBufferDownload}. Upload sources and download destinations have different lifetime requirements:" +concepts.resources.transfers.guidance: 'To submit transfers together with other GPU work, record them with {commandBufferUpload} or {commandBufferDownload}. Upload sources and download destinations have different lifetime requirements:' concepts.resources.transfers.item: During an upload call, the library copies the source data into temporary upload storage, called staging memory. The GPU later reads from this storage, so the application's source pointer is needed only until the call returns. @@ -282,7 +288,8 @@ concepts.resources.views.details: A resource's own handle provides its default v constants containing the old {link}. concepts.resources.views.details.link: resource handle concepts.resources.views.title: Views and backing resources -concepts.shaders.binding.context: 'The compute sample assigns {inputTextureSampledHandle} to {input} and {outputTextureStorageHandle} +concepts.shaders.binding.context: + 'The compute sample assigns {inputTextureSampledHandle} to {input} and {outputTextureStorageHandle} to {output}. In Slang, the type parameter of {descriptorHandle} defines how the shader accesses each resource:' concepts.shaders.binding.description: '{setConstantBuffer} selects an existing buffer and byte offset from which the current pipeline reads its constants. Upload the parameter data into that storage before it is used by the @@ -310,9 +317,9 @@ concepts.shaders.binding.table.samplerHandle.access: Texture sampling state concepts.shaders.binding.table.textureSampledHandle.access: Texture reads concepts.shaders.binding.table.textureStorageHandle.access: Storage-texture reads and writes concepts.shaders.binding.title: Constant buffers and resource handles -concepts.shaders.compilation.description: '{zenithCompiler} compiles a named Slang entry point into a {shaderDesc}. - The context''s {graphicsApi} selects the required target: DXIL for DirectX 12, a Metal library for Metal, or SPIR-V - for Vulkan.' +concepts.shaders.compilation.description: "{zenithCompiler} compiles a named Slang entry point into a {shaderDesc}. + The context's {graphicsApi} selects the required target: DXIL for DirectX 12, a Metal library for Metal, or SPIR-V + for Vulkan." concepts.shaders.compilation.details: 'With a graphics context named {context} already created, compile the triangle shader from the copy placed beside the executable:' concepts.shaders.compilation.guidance: The entry-point name {vSMain} must match the declaration in the shader file. @@ -323,10 +330,10 @@ concepts.shaders.compilation.title: Shader compilation concepts.shaders.description: The C# and Slang declarations must agree on where each value is stored and how the shader accesses it. Vertex input layouts describe vertex attributes; shader buffer declarations describe parameters and arrays; resource handles identify the resources used by a shader. -concepts.shaders.dispatch.description: '{dispatch} specifies how many thread groups to execute. The compute sample +concepts.shaders.dispatch.description: "{dispatch} specifies how many thread groups to execute. The compute sample declares {numthreads}, so each group contains 16 × 16 threads. To cover an image, divide its width and height - by 16 and round each result up: a 17 × 19 image requires 2 × 2 groups. The shader checks each thread''s coordinates - and skips those outside the image.' + by 16 and round each result up: a 17 × 19 image requires 2 × 2 groups. The shader checks each thread's coordinates + and skips those outside the image." concepts.shaders.dispatch.details: The declared group size is available in {shaderDescThreadGroupSize} and can be used to calculate the group counts passed to {dispatch}. {computeShaderRendererCs} shows the complete calculation. After the dispatch, access to the resulting image must follow the requirements described in {link}. @@ -335,11 +342,11 @@ concepts.shaders.dispatch.title: Thread groups concepts.shaders.layout.context: 'The {link} illustrate this arrangement with image dimensions and two texture handles. Explicit offsets specify where each field begins. The declaration uses {systemRuntimeInteropServices} and {zenithNET}:' concepts.shaders.layout.context.link: compute sample's C# constants -concepts.shaders.layout.description: 'For vertex input, {inputLayout} describes each attribute''s format, offset, +concepts.shaders.layout.description: "For vertex input, {inputLayout} describes each attribute's format, offset, and semantic, together with the stride between vertices. The triangle places a {float3} position before a {float4} color: the color starts at byte offset 12, and each vertex occupies 28 bytes. {inputLayoutAdd} calculates this packed layout from the element formats. If the C# struct contains padding, supply offsets and a stride that account - for it.' + for it." concepts.shaders.layout.details: "Constant buffers hold shader parameters, and structured buffers hold arrays of typed elements. Their layouts follow the Slang declarations rather than {inputLayout}. Match the C# field offsets, element sizes, and padding to the compiled shader layout. A C# unmanaged type can be copied as bytes, but its memory layout does not necessarily match the shader's layout; the tightly packed {float3} used for a vertex may require different alignment in a shader buffer." concepts.shaders.layout.guidance: Shader parameters can include resource handles as well as ordinary values. A handle identifies storage that already exists, so copying the handle into a constant buffer does not copy the resource's @@ -410,22 +417,22 @@ concepts.synchronization.description: Synchronization establishes the order in w concepts.synchronization.layouts.context: Use {undefined} as the previous layout when the existing contents can be discarded, such as for a new image or an attachment that will be cleared completely. To preserve the contents for loading, sampling, or accumulation, use the layout from the preceding access. -concepts.synchronization.layouts.description: 'A texture''s usage flags declare its permitted roles. {textureLayout} +concepts.synchronization.layouts.description: "A texture's usage flags declare its permitted roles. {textureLayout} describes how a particular subresource, identified by a mip level and array layer, is accessed at a given point in the command sequence. When that access changes, record a transition. For example, the compute sample writes - an output texture in {storage} layout, then prepares it for sampling in a graphics pass:' + an output texture in {storage} layout, then prepares it for sampling in a graphics pass:" concepts.synchronization.layouts.details: Here, {outputTexture} was created with {sampledStorage} usage and the selected subresource is in {storage} layout. {default} selects mip level 0 and array layer 0. Other mip levels and layers are unaffected by this transition. concepts.synchronization.layouts.guidance: For {transition}, supply the layout from the subresource's previous use. The application tracks this state as it records commands and passes textures between rendering stages. concepts.synchronization.layouts.title: Texture layouts -concepts.synchronization.readback.description: '{isCompleted} reports GPU completion. A recorded download has one - further step: copying the result from internal readback storage into the application''s destination memory.' -concepts.synchronization.readback.details: '{commandBufferDownload} records the GPU copy into that internal storage. +concepts.synchronization.readback.description: "{isCompleted} reports GPU completion. A recorded download has one + further step: copying the result from internal readback storage into the application's destination memory." +concepts.synchronization.readback.details: "{commandBufferDownload} records the GPU copy into that internal storage. After the submission finishes, the library performs the CPU copy while reclaiming the completed command buffer. - Calling {wait} on the download''s submission value waits for the GPU and processes that queue''s completed buffers, - completing both steps. Keep the destination allocated, and managed memory pinned, until the call returns.' + Calling {wait} on the download's submission value waits for the GPU and processes that queue's completed buffers, + completing both steps. Keep the destination allocated, and managed memory pinned, until the call returns." concepts.synchronization.readback.guidance: Polling {isCompleted} alone does not perform the final CPU copy. A wait on another queue does not reclaim the download queue's completed buffers either. {link} describes when uploads and downloads use direct memory access or staging storage. @@ -490,7 +497,8 @@ learning.concepts.resources.description: Resource usages, memory placement, and learning.concepts.shaders.description: Data-layout and binding conventions for C# and Slang learning.concepts.synchronization.description: Dependencies, visibility, and completion learning.concepts.title: Core concepts -learning.description: Start with the triangle tutorial to build your first application. Then explore resource management, +learning.description: + Start with the triangle tutorial to build your first application. Then explore resource management, shader data, and synchronization in the concept articles, or choose a sample for the technique you want to implement. learning.entries.samples.action: Browse samples learning.entries.samples.description: C# and Slang implementations of geometry, compute, ray queries, and mesh shading @@ -522,9 +530,9 @@ samples.description.link: First Triangle samples.execution.description: Run the {link} project and choose an example from its console menu. samples.execution.description.link: ZenithTutorials samples.execution.title: Running the examples -samples.host.description: '{appCs} initializes the context, window, and swap chain. On each frame it obtains a command +samples.host.description: "{appCs} initializes the context, window, and swap chain. On each frame it obtains a command buffer, invokes the selected renderer, submits the commands, and presents the result. {iRendererCs} defines the - renderer''s update, render, resize, and disposal operations.' + renderer's update, render, resize, and disposal operations." samples.host.details: The compute and ray tracing renderers produce offscreen textures. {texturePresenterCs} and {presentTextureSlang} draw those textures into the current drawable; the shared host then submits the commands and presents the frame. @@ -582,7 +590,7 @@ tutorial.context.details: 'Insert the context initialization {emphasis}:' tutorial.context.details.emphasis: after the using directives, before {iWindowWindow} tutorial.context.guidance: Each branch selects a backend for the current platform and requests validation. Messages from {validationMessage} are printed in the console. -tutorial.context.imports: "Add the following using directives at the top of {programCs}:" +tutorial.context.imports: 'Add the following using directives at the top of {programCs}:' tutorial.context.title: Graphics context tutorial.description: In this tutorial, you will build a .NET console application that opens a window and draws a colored triangle, starting from an empty project. @@ -591,8 +599,8 @@ tutorial.details: 'The tutorial has three checkpoints: an empty window, a solid tutorial.draw.context: 'The arguments to {draw} are:' tutorial.draw.description: 'In the {windowRender} callback, replace {addTheTriangleDrawCommandsHereLater} with the following commands, between {beginRenderPass} and {endRenderPass}:' -tutorial.draw.details: '{setPipeline} selects the shaders and render state. It must precede vertex binding because - the backend interprets that binding using the pipeline''s input layout.' +tutorial.draw.details: "{setPipeline} selects the shaders and render state. It must precede vertex binding because + the backend interprets that binding using the pipeline's input layout." tutorial.draw.guidance: '{setVertexBufferVertexBuffer} binds the uploaded vertex data at byte offset 0 to input slot 0, corresponding to the single entry in {inputLayouts}.' tutorial.draw.notes: These calls record the draw commands. The existing {submitWait} submits them and waits for @@ -634,7 +642,8 @@ tutorial.frame.details: 'Silk.NET invokes the render callback when a frame is du tutorial.frame.details.emphasis: before {windowRun} tutorial.frame.target.description: '{graphicsQueueCommandBuffer} returns a command buffer ready for recording. Recording defines the GPU workload; execution begins only after submission.' -tutorial.frame.target.details: A texture layout describes the kind of access an operation requires. The first {transition} +tutorial.frame.target.details: + A texture layout describes the kind of access an operation requires. The first {transition} prepares the drawable for use as a color attachment. Here, {default} selects mip level 0 and array layer 0, the drawable's base image. Specifying {undefined} allows the previous contents to be discarded because this pass clears the entire image. @@ -660,7 +669,7 @@ tutorial.geometry.format.details: '{file} limits the type to {programCs}, and {l in declaration order. {position} contains three 32-bit floats and starts at byte offset 0; {color} contains four and starts at byte offset 12. Each vertex therefore occupies 28 bytes. The input layout will describe this arrangement so the GPU can read the fields correctly.' -tutorial.geometry.format.imports: "Add these using directives at the top of {programCs} for the vector types and the struct layout attribute:" +tutorial.geometry.format.imports: 'Add these using directives at the top of {programCs} for the vector types and the struct layout attribute:' tutorial.geometry.format.title: Vertex representation tutorial.geometry.title: Vertex data tutorial.geometry.upload.context: '{fixed} prevents the garbage collector from moving the array while its address @@ -669,13 +678,13 @@ tutorial.geometry.upload.context: '{fixed} prevents the garbage collector from m keep the buffer alive until rendering has finished.' tutorial.geometry.upload.description: 'Store the vertices in a {buffer} so the GPU can read them during drawing. Add the allocation and upload immediately after the array:' -tutorial.geometry.upload.details: 'The allocation size is {sizeofVertexVerticesLength}: three 28-byte vertices, +tutorial.geometry.upload.details: "The allocation size is {sizeofVertexVerticesLength}: three 28-byte vertices, or 84 bytes. {bufferUsagesVertex} declares vertex-input access, while {cpuWriteOnly} permits direct initialization - by the CPU. The descriptor''s stride records the element size. The input layout defined below specifies how vertex - fetching interprets each attribute.' + by the CPU. The descriptor's stride records the element size. The input layout defined below specifies how vertex + fetching interprets each attribute." tutorial.geometry.upload.guidance: Allocation does not initialize the buffer's contents. {upload} copies the array to destination byte offset 0 using the source pointer and byte count supplied in the data description. -tutorial.geometry.upload.imports: "In {programCs}, add {bufferAlias} to the using directives to distinguish the Zenith.NET buffer type from {systemBuffer}." +tutorial.geometry.upload.imports: 'In {programCs}, add {bufferAlias} to the using directives to distinguish the Zenith.NET buffer type from {systemBuffer}.' tutorial.geometry.upload.notes: Add {vertexBufferDispose} immediately before {swapChainDispose} in the cleanup at the end of {programCs}. For larger static geometry, {link} discusses GPU-only storage and transfer uploads. tutorial.geometry.upload.notes.link: Resource Management @@ -719,10 +728,11 @@ tutorial.pipeline.guidance: The pipeline's color format must match the render-pa tutorial.pipeline.item: '{triangleList} assembles each consecutive group of three vertices into a triangle.' tutorial.pipeline.notes: '{depthNone} disables depth testing and depth writes, consistent with the absence of a depth attachment.' -tutorial.pipeline.reference: '{opaque} disables blending. The fragment shader''s output therefore replaces the background - color inside the triangle.' +tutorial.pipeline.reference: "{opaque} disables blending. The fragment shader's output therefore replaces the background + color inside the triangle." tutorial.pipeline.title: Graphics pipeline -tutorial.pipeline.usage: Shader objects may be released after pipeline creation. Keep the pipeline alive while rendering, +tutorial.pipeline.usage: + Shader objects may be released after pipeline creation. Keep the pipeline alive while rendering, and add {pipelineDispose} before {vertexBufferDispose} in the cleanup. tutorial.presentation.title: Graphics context and presentation tutorial.project.context: Enable {emphasis} ({allowUnsafeBlocks}) in the project's build settings. Native calls @@ -755,8 +765,9 @@ tutorial.requirements.title: Prerequisites tutorial.resize.context: 'Build and run the application again. The background should continue to fill the window when you resize it: each new render pass sets its viewport and scissor from the resized attachment. Keep the render callback in place; the triangle will be drawn inside this pass.' -tutorial.resize.description: 'The swap chain must follow changes to the framebuffer''s size. Register a {framebufferResize} - callback after the render callback and before {windowRun}:' +tutorial.resize.description: + "The swap chain must follow changes to the framebuffer's size. Register a {framebufferResize} + callback after the render callback and before {windowRun}:" tutorial.resize.details: Listen for {link}, which are measured in pixels, rather than changes to the window's logical size. If minimizing the window sets either framebuffer dimension to zero, the resize callback leaves the swap chain unchanged. The render callback also returns while either dimension is zero, pausing rendering until the @@ -776,7 +787,8 @@ tutorial.shaders.compilation.description.detail: Copy if newer tutorial.shaders.compilation.description.emphasis: Copy to Output Directory tutorial.shaders.compilation.details: 'Return to {programCs} and add shader initialization after the vertex upload, before the render callback:' -tutorial.shaders.compilation.guidance: '{zenithCompiler} compiles the source for {contextGraphicsApi}, and {createShader} +tutorial.shaders.compilation.guidance: + '{zenithCompiler} compiles the source for {contextGraphicsApi}, and {createShader} creates a shader object from the compiled description. The entry-point names {vSMain} and {fSMain} select the two functions defined in the Slang file.' tutorial.shaders.compilation.title: Compiling the shaders @@ -793,15 +805,15 @@ tutorial.shaders.fragment.details: Rasterization determines where the triangle c for those locations. Each fragment receives a color interpolated from the three vertex colors. {fSMain} returns this color, and {sVTARGET} directs the result to the first color attachment. tutorial.shaders.fragment.title: Fragment shading -tutorial.shaders.guidance: '{vSInput} defines the vertex shader''s inputs. {pOSITION0} and {cOLOR0} identify the - attributes by semantic; the C# field names alone do not establish this mapping.' +tutorial.shaders.guidance: "{vSInput} defines the vertex shader's inputs. {pOSITION0} and {cOLOR0} identify the + attributes by semantic; the C# field names alone do not establish this mapping." tutorial.shaders.title: Shader stages tutorial.shaders.vertex.description: 'Append the vertex entry point to {triangleSlang}:' tutorial.shaders.vertex.details: The GPU invokes this entry point for each input vertex. It adds the homogeneous coordinate {w} and forwards the color. After vertex processing, position is divided by w. Since w is 1 here, x, y, and z are unchanged and may be interpreted directly as normalized device coordinates. tutorial.shaders.vertex.title: Vertex shading -tutorial.surface.description: "Specify the native presentation target {emphasis}:" +tutorial.surface.description: 'Specify the native presentation target {emphasis}:' tutorial.surface.description.emphasis: after {windowCenter} and before {windowRun} tutorial.surface.details: The framebuffer is the window's image in pixels. {surface} describes the native presentation target and its dimensions, and {framebufferSize} gives the size in pixels. With display scaling, this can differ @@ -845,7 +857,7 @@ tutorial.troubleshooting.table.window.check: Confirm the .NET project builds and desktop session. On Linux, check that X11 or XWayland is available. tutorial.troubleshooting.table.window.symptom: No window opens tutorial.troubleshooting.title: Troubleshooting -tutorial.window.description: "Download {cocoaHelperCs} into the project. This helper class attaches the Metal layer to the macOS window." +tutorial.window.description: 'Download {cocoaHelperCs} into the project. This helper class attaches the Metal layer to the macOS window.' tutorial.window.details: 'Replace the generated {programCs} with the code below. It uses top-level statements, which run in order without an explicit {main} method. Each later section will show where to add its code:' tutorial.window.guidance: '{graphicsAPINone} leaves graphics-context creation to Zenith.NET. {initialize} creates diff --git a/documents/locales/es-ES/strings.yml b/documents/locales/es-ES/strings.yml index 516b042e..768e023d 100644 --- a/documents/locales/es-ES/strings.yml +++ b/documents/locales/es-ES/strings.yml @@ -1,593 +1,593 @@ ### YamlMime:Resources -concepts.execution.context.description: "Un {graphicsContext} conecta la aplicación con un dispositivo GPU mediante un backend concreto y proporciona sus colas gráfica, de cálculo y de transferencia. Los recursos que se utilizan juntos deben pertenecer al mismo contexto; no se pueden enlazar búferes, texturas, sombreadores, canalizaciones ni sus identificadores entre contextos distintos." -concepts.execution.context.details: "{capabilities} indica el nombre del dispositivo y las funciones que admite. Compruebe {rayTracingSupported} y {meshShadingSupported} antes de crear los recursos que necesitan esas funciones. Los ejemplos de {link} y {detail} realizan estas comprobaciones durante la inicialización." -concepts.execution.context.details.detail: "sombreado de mallas" -concepts.execution.context.details.link: "trazado de rayos" -concepts.execution.context.title: "Contexto gráfico" -concepts.execution.description: "El trabajo de la GPU se prepara en la CPU: la aplicación crea recursos, graba comandos que los utilizan y envía esos comandos a una cola. Tras el envío, la CPU puede continuar mientras la GPU ejecuta el trabajo. Los recursos deben seguir disponibles hasta que esa ejecución termine." -concepts.execution.ownership.description: "La propiedad establece quién libera un objeto; la finalización en la GPU determina cuándo puede hacerlo. Una llamada a {dispose} libera los recursos nativos aunque aún existan referencias de C# al objeto. Enviar comandos no transfiere a la cola la propiedad de los recursos que utilizan." -concepts.execution.ownership.details: "Al cerrar la aplicación, deje de enviar trabajo y espere al último uso de los recursos en cada cola implicada. Después, libere los recursos de la aplicación y el contexto. El contexto libera sus colas y auxiliares internos, por lo que este último paso debe realizarse cuando todo el trabajo de la aplicación haya terminado." -concepts.execution.ownership.guidance: "Durante el renderizado, lleve un seguimiento del trabajo que utiliza datos que se van a sobrescribir o recursos que se van a sustituir. Espere a que termine antes de modificar o liberar el almacenamiento afectado. {link} explica cómo se aplica este modelo de vida útil a las vistas y a los recursos que las respaldan." -concepts.execution.ownership.guidance.link: "Administración de recursos" -concepts.execution.ownership.table.applicationResources.object: "Recursos creados por la aplicación" -concepts.execution.ownership.table.applicationResources.ownership: "La aplicación los libera después de su último uso en la GPU." -concepts.execution.ownership.table.commandBuffers.object: "Búferes de comandos prestados" -concepts.execution.ownership.table.commandBuffers.ownership: "La cola los gestiona y los recicla." -concepts.execution.ownership.table.headings.object: "Objeto" -concepts.execution.ownership.table.headings.ownership: "Responsabilidad de liberación" -concepts.execution.ownership.table.queues.object: "Colas de contexto y sus líneas de tiempo" -concepts.execution.ownership.table.queues.ownership: "El contexto y las colas las gestionan." -concepts.execution.ownership.table.swapChainDrawable.ownership: "La cadena de intercambio lo gestiona." -concepts.execution.ownership.title: "Propiedad y tiempo de vida" -concepts.execution.pipelines.description: "Una canalización gráfica define los sombreadores, la disposición de entrada de vértices, el ensamblado de primitivas, los formatos de adjunto y el estado de renderizado. Se selecciona antes de enlazar vértices, índices o constantes. Los formatos y el número de muestras deben coincidir con la pasada de renderizado." -concepts.execution.pipelines.details: "Una canalización de cálculo selecciona el punto de entrada del sombreador que ejecutará un despacho. Enlace la canalización y sus constantes antes del despacho, fuera de una pasada de renderizado gráfico." -concepts.execution.pipelines.guidance: "La {link} presenta la secuencia gráfica. El {detail} incorpora un despacho de cálculo antes de la pasada que muestra su resultado." -concepts.execution.pipelines.guidance.detail: "ejemplo de cálculo" -concepts.execution.pipelines.guidance.link: "función de renderizado del triángulo" -concepts.execution.pipelines.title: "Estado de la canalización" -concepts.execution.queues.description: "{graphicsQueue} es el punto de partida habitual para un fotograma que combina dibujo, cálculo y copias. Agrupar operaciones dependientes en una cola simplifica su ordenación." -concepts.execution.queues.details: "Las colas permiten enviar cargas de trabajo independientes por separado, aunque no necesariamente corresponden a motores de hardware independientes. Use colas adicionales cuando resulte útil solapar la ejecución. Si una cola utiliza datos producidos por otra, conecte sus envíos mediante una dependencia explícita." -concepts.execution.queues.guidance: "Dentro de una cola, las operaciones dependientes también pueden necesitar barreras o transiciones de textura para que los accesos posteriores vean las escrituras anteriores. Estas dependencias de memoria son distintas del orden de envío; {link} explica cómo expresarlas." -concepts.execution.queues.guidance.link: "Sincronización" -concepts.execution.queues.table.computeQueue.workToRecord: "Despachos de cálculo y transferencias compatibles, sin pasadas gráficas." -concepts.execution.queues.table.graphicsQueue.workToRecord: "Pasadas de renderizado, dibujo, cálculo y transferencias." -concepts.execution.queues.table.headings.queue: "Cola" -concepts.execution.queues.table.headings.workToRecord: "Operaciones admitidas" -concepts.execution.queues.table.transferQueue.workToRecord: "Cargas, descargas y copias, sin dibujo ni despachos de cálculo." -concepts.execution.queues.title: "Selección de colas" -concepts.execution.recording.context: "La cola recupera los búferes de comandos completados para reutilizarlos. Obtenga uno con {queueCommandBuffer} para cada grabación, grabe desde un solo hilo a la vez y envíelo una única vez. Después del envío, deje que la cola lo gestione: no lo modifique, vuelva a enviar ni libere." -concepts.execution.recording.description: "{queueCommandBuffer} devuelve un {commandBuffer} cuya grabación ya está iniciada. Tras grabar las operaciones y sus dependencias, se llama a {submit} una vez. El envío cierra la grabación y devuelve un {timelineValue} que identifica su finalización en esa cola." -concepts.execution.recording.details: "Tras grabar un fotograma en {commandBuffer}, el tutorial lo envía y espera de este modo:" -concepts.execution.recording.guidance: "La grabación construye la secuencia de comandos; {submit} programa su ejecución. La llamada posterior a {wait} bloquea el hilo de la CPU hasta que termina ese envío. Así, el bucle del tutorial resulta fácil de seguir: cada fotograma termina antes de comenzar el siguiente." -concepts.execution.recording.title: "Grabación y envío" -concepts.execution.title: "Modelo de ejecución" -concepts.platforms.description: "La presentación puede gestionarla la aplicación o un control de interfaz. Esta elección determina quién obtiene la textura de salida del fotograma, registra y envía los comandos y presenta el resultado. Esa textura de salida se denomina drawable." -concepts.platforms.frame.context: "Grabe los enlaces de canalización y los comandos de dibujo dentro de la pasada y termínela antes de que retorne el manejador. El control envía los comandos y presenta el resultado. El manejador no debe enviar el búfer de comandos ni liberar ninguno de los objetos recibidos. Si cambia la disposición de la textura de salida, restáurela a {colorAttachment} antes de retornar para que el control pueda realizar la transición final." -concepts.platforms.frame.description: "Los controles implementan {iZenithView}. La aplicación asigna {graphicsContext}, actualiza la escena en {updateRequested} y graba en {renderRequested} mediante los {renderEventArgs} recibidos." -concepts.platforms.frame.details: "En cada fotograma, el control obtiene una textura de salida y un búfer de comandos, cambia la disposición de la textura a {colorAttachment} y llama a los manejadores de actualización y renderizado. Después envía el trabajo grabado y presenta la imagen mediante el mecanismo del framework." -concepts.platforms.frame.guidance: "Añada {usingZenithNET} al archivo. Para una instancia de {iZenithView} llamada {view}, ya inicializada y con un contexto gráfico asignado, registre este manejador del evento de renderizado para borrar la textura de salida que proporciona el control:" -concepts.platforms.frame.notes: "La transición inicial utiliza {undefined}, que permite descartar el contenido anterior. Dibuje o borre la imagen completa en cada fotograma. Guarde el renderizado acumulado o en caché en una textura propia de la aplicación y dibújela después sobre la textura de salida del control." -concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat} proporciona el formato de color predeterminado de estas integraciones." -concepts.platforms.frame.title: "Renderizado mediante controles de interfaz" -concepts.platforms.integration.context: "WinForms, WPF y la integración Windows de WinUI se ejecutan en Windows. Para MAUI, instale la carga de trabajo de la plataforma de destino y registre el controlador con {useZenithView}, como se muestra en {extensionsCs}." -concepts.platforms.integration.description: "La interfaz de eventos es común, pero la presentación depende del framework:" -concepts.platforms.integration.details: "Estas implementaciones difieren en cómo llevan la imagen de la GPU a la interfaz. La lectura como mapa de bits copia los píxeles a la memoria de la CPU antes de mostrarlos. La interoperabilidad mediante texturas compartidas evita esa copia, pero aún puede necesitar copias en la GPU y sincronización. Al elegir una integración, considere este mecanismo de presentación además del evento común {renderRequested}." -concepts.platforms.integration.guidance: "Añada mediante NuGet el paquete de integración de su framework de interfaz. Para Avalonia, utilice {avaloniaPackage}." -concepts.platforms.integration.table.avalonia.integration: "Avalonia" -concepts.platforms.integration.table.avalonia.presentation: "Renderiza en una textura y descarga píxeles en un {writeableBitmap}. Consulte {zenithViewCs} y {surfaceCs}." -concepts.platforms.integration.table.headings.integration: "Integración" -concepts.platforms.integration.table.headings.presentation: "Mecanismo de presentación" -concepts.platforms.integration.table.maui.integration: ".NET MAUI" -concepts.platforms.integration.table.maui.presentation: "Utiliza superficies nativas en Android, iOS y Mac Catalyst, y composición de texturas compartidas en Windows. Consulte las {link}." -concepts.platforms.integration.table.maui.presentation.link: "implementaciones de plataforma" -concepts.platforms.integration.table.uno.integration: "Ruta de Uno" -concepts.platforms.integration.table.uno.presentation: "Descarga píxeles en un {writeableBitmap}. Consulte {zenithViewUnoCs}." -concepts.platforms.integration.table.winForms.integration: "WinForms" -concepts.platforms.integration.table.winForms.presentation: "Crea una cadena de intercambio de Zenith.NET para el {hWND} del control. Consulte {zenithViewCs}." -concepts.platforms.integration.table.winUI.integration: "WinUI en Windows" -concepts.platforms.integration.table.winUI.presentation: "Renderiza en una textura compartida de Direct3D 11 importada y copia el resultado a una cadena de intercambio de composición conectada a {swapChainPanel}. Consulte {zenithViewWinUICs}." -concepts.platforms.integration.table.wpf.integration: "WPF" -concepts.platforms.integration.table.wpf.presentation: "Importa una textura compartida de Direct3D 11 y copia su contenido, mediante interoperabilidad con Direct3D, a una superficie que muestra {d3DImage}. Consulte {surfaceCs}." -concepts.platforms.integration.title: "Framework y presentación" -concepts.platforms.lifecycle.context: "Al crear adjuntos compatibles, utilice {descWidth}, {descHeight}, {descFormat} y {descSampleCount} de la textura de salida que proporciona el evento de renderizado. Esa textura indica las dimensiones reales del destino; no deben deducirse del tamaño de diseño del control ni de la escala de pantalla." -concepts.platforms.lifecycle.description: "La cadena de intercambio utiliza el ancho y el alto en píxeles del búfer de fotogramas, que pueden diferir del tamaño lógico de la ventana cuando hay escalado de pantalla. Aplace el renderizado y el redimensionamiento de la cadena mientras alguna dimensión sea cero. Obtenga {swapChainDrawable} en cada fotograma: la cadena de intercambio posee esta textura y puede sustituirla tras presentar o redimensionar." -concepts.platforms.lifecycle.details: "Si cambia el tamaño del búfer de fotogramas, espere a que terminen los usos pendientes de las imágenes anteriores en la GPU antes de llamar a {swapChainResize}. Para sustituir el destino nativo de presentación, espere del mismo modo y pase la nueva descripción de superficie y sus identificadores a {swapChainRefresh}. Al cerrar, libere la cadena de intercambio antes de destruir su destino nativo." -concepts.platforms.lifecycle.guidance: "Si la aplicación tiene texturas de profundidad o fuera de pantalla que siguen el tamaño de la ventana, vuelva a crearlas cuando cambie ese tamaño y actualice las constantes que contengan sus identificadores. La canalización se puede reutilizar mientras sigan coincidiendo los formatos y el número de muestras de los adjuntos. El {link} muestra esta separación entre las texturas que se redimensionan y la canalización reutilizable." -concepts.platforms.lifecycle.guidance.link: "renderizador de cubo giratorio" -concepts.platforms.lifecycle.title: "Dimensiones y vida útil de la cadena de intercambio" -concepts.platforms.ownership.description: "La aplicación posee el contexto asignado y sus recursos de renderizado; el control posee sus recursos de presentación. Cuando cambia {graphicsContext} en la vista, el planificador vuelve a crear los recursos del control para el nuevo contexto. Vuelva a crear también las canalizaciones, los búferes y las texturas de la aplicación para ese contexto." -concepts.platforms.ownership.details: "Antes de sustituir recursos de renderizado, detenga la actividad de fotogramas de la vista y espere al trabajo de la GPU que los utiliza. Solo entonces libere los recursos o el contexto anteriores. Al retirar la vista, la aplicación sigue siendo responsable de liberar el contexto que tenía asignado." -concepts.platforms.ownership.guidance: "El componente compartido {frameSchedulerCs} ejecuta los manejadores de eventos de cada fotograma mediante el distribuidor de la interfaz de la vista. Limite esos manejadores a actualizar la escena y grabar comandos: un trabajo prolongado en la CPU también retrasa la respuesta de la interfaz." -concepts.platforms.ownership.title: "Responsabilidades de aplicación y control" -concepts.platforms.surface.description: "El {link} utiliza Silk.NET para crear la ventana y procesar sus eventos. Zenith.NET recibe los identificadores nativos y las dimensiones mediante una descripción {surface}, con la que crea una {swapChain}. La aplicación sigue siendo responsable de la ventana del sistema operativo." -concepts.platforms.surface.description.link: "tutorial del triángulo" -concepts.platforms.surface.details: "Los identificadores nativos deben corresponder al backend:" -concepts.platforms.surface.guidance: "El programa anfitrión de {appCs} admite Windows, macOS y X11. En Linux, la ventana proporciona identificadores Xlib, por lo que necesita XWayland para ejecutarse en una sesión Wayland. Una aplicación nativa de Wayland proporciona los identificadores de pantalla y superficie mediante {surfaceWayland}." -concepts.platforms.surface.table.android.backend: "Vulkan en Android." -concepts.platforms.surface.table.apple.backend: "Metal en plataformas Apple." -concepts.platforms.surface.table.headings.backend: "Backend y plataforma" -concepts.platforms.surface.table.headings.factory: "Fábrica de superficies" -concepts.platforms.surface.table.headings.handles: "Identificadores suministrados por el host" -concepts.platforms.surface.table.wayland.backend: "Vulkan con un host Wayland nativo." -concepts.platforms.surface.table.wayland.handles: "Pantalla y superficie Wayland" -concepts.platforms.surface.table.win32.backend: "DirectX 12 o Vulkan en Windows." -concepts.platforms.surface.table.xlib.backend: "Vulkan en Linux con X11 o XWayland." -concepts.platforms.surface.table.xlib.handles: "Pantalla y ventana X11" -concepts.platforms.surface.title: "Superficies de presentación nativas" -concepts.platforms.title: "Integración de plataforma" -concepts.resources.allocation.context: "Los recursos colocados en un montículo dependen de su almacenamiento durante toda su vida útil. Después de su último uso en la GPU, libere los recursos antes de liberar el montículo." -concepts.resources.allocation.description: "Use un {heap} cuando la aplicación necesite gestionar las asignaciones por sí misma. Un montículo proporciona almacenamiento donde se colocan los recursos en desplazamientos explícitos en bytes; la aplicación elige esos desplazamientos y lleva el registro de las regiones ocupadas." -concepts.resources.allocation.details: "Para cada recurso, llame a {contextGetSizeAndAlignment} con la descripción de búfer o textura que se utilizará al crearlo. Reserve el tamaño devuelto en un desplazamiento múltiplo de la alineación indicada, dentro del montículo y sin solapar otra asignación en uso. Las texturas pueden necesitar relleno específico del backend; por eso, el número de píxeles y los bytes por píxel no bastan para calcular el tamaño de la asignación." -concepts.resources.allocation.guidance: "La residencia de un búfer colocado en un montículo debe coincidir con la del montículo. Para almacenar texturas, use un montículo exclusivo de la GPU." -concepts.resources.allocation.title: "Asignación en montículos" -concepts.resources.bufferUsages.table.constant.role: "Parámetros de sombreador leídos a través de un enlace de búfer de constantes." -concepts.resources.bufferUsages.table.headings.role: "Rol" -concepts.resources.bufferUsages.table.headings.usage: "Uso" -concepts.resources.bufferUsages.table.index.role: "Índices utilizados por el dibujo indexado." -concepts.resources.bufferUsages.table.indirect.role: "Argumentos leídos por comandos de dibujo o despacho indirectos." -concepts.resources.bufferUsages.table.none.role: "No se declaran indicadores de uso del búfer." -concepts.resources.bufferUsages.table.storageReadOnly.role: "Datos del búfer disponibles mediante un enlace de sombreador de solo lectura." -concepts.resources.bufferUsages.table.storageReadWrite.role: "Datos del búfer disponibles mediante un enlace de sombreador de lectura y escritura." -concepts.resources.bufferUsages.table.transferDst.role: "Almacenamiento de destino para una copia de GPU." -concepts.resources.bufferUsages.table.transferSrc.role: "Datos de origen para una copia de GPU." -concepts.resources.bufferUsages.table.vertex.role: "Atributos de vértice que leen los comandos de dibujo." -concepts.resources.bufferUsages.title: "Usos de búfer" -concepts.resources.description: "La descripción de un recurso establece cómo puede utilizar la aplicación su almacenamiento. Por ejemplo, una textura que se usa como destino de renderizado, se muestrea en un sombreador y se copia a la CPU necesita los indicadores de uso de las tres operaciones. La ubicación de memoria determina el acceso de la CPU; la sincronización y la gestión de la vida útil determinan cuándo se pueden usar los datos o liberar el almacenamiento." -concepts.resources.memory.context: "En los búferes accesibles desde la CPU, {map} proporciona la dirección desde la que se leen o escriben los datos. Ni el mapeo ni {unmap} esperan al trabajo de la GPU: antes de leer un resultado, la aplicación debe esperar a que termine la escritura que lo produce; antes de modificar esos mismos bytes, debe esperar a que terminen los accesos pendientes de la GPU." -concepts.resources.memory.description: "El campo {residency} de {bufferDesc} establece el acceso de CPU previsto para la asignación:" -concepts.resources.memory.details: "La residencia expresa los requisitos de acceso de la CPU, también en sistemas donde CPU y GPU comparten memoria física. El triángulo utiliza {cpuWriteOnly} para inicializar directamente su pequeño búfer de vértices. Para geometría estática de mayor tamaño, puede ser más adecuado cargar los datos en almacenamiento exclusivo de la GPU." -concepts.resources.memory.guidance: "Las texturas creadas directamente mediante el contexto utilizan almacenamiento de la GPU. Por eso, {textureDesc} no tiene un campo de residencia; la aplicación intercambia sus datos con la memoria de la CPU mediante cargas y descargas." -concepts.resources.memory.table.cpuReadOnly.cPUAccess: "Solo lectura" -concepts.resources.memory.table.cpuReadOnly.typicalRole: "Datos producidos por la GPU para su lectura en la CPU" -concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "Solo escritura" -concepts.resources.memory.table.cpuWriteOnly.typicalRole: "Datos proporcionados o actualizados por la CPU" -concepts.resources.memory.table.gpuOnly.cPUAccess: "Ninguno" -concepts.resources.memory.table.gpuOnly.typicalRole: "Geometría estática y datos de trabajo de la GPU" -concepts.resources.memory.table.headings.cPUAccess: "Acceso previsto de la CPU" -concepts.resources.memory.table.headings.residency: "Residencia" -concepts.resources.memory.table.headings.typicalRole: "Rol típico" -concepts.resources.memory.title: "Acceso de CPU y ubicación de memoria" -concepts.resources.textureUsages.description: "Los indicadores de transferencia describen si el recurso actúa como origen o destino de una copia en la GPU. La posibilidad de acceder directamente desde la CPU se decide por separado al elegir la ubicación de memoria." -concepts.resources.textureUsages.details: "Los indicadores de uso declaran las funciones que puede desempeñar una textura. Para pasar de una a otra se deben cumplir los requisitos de {link}; además, el dispositivo elegido debe admitir esos usos para el formato de la textura." -concepts.resources.textureUsages.details.link: "disposición y sincronización" -concepts.resources.textureUsages.table.colorAttachment.role: "Un adjunto de color en una pasada de renderizado." -concepts.resources.textureUsages.table.depthStencilAttachment.role: "Un adjunto de profundidad y plantilla en una pasada de renderizado." -concepts.resources.textureUsages.table.headings.role: "Rol" -concepts.resources.textureUsages.table.headings.usage: "Uso" -concepts.resources.textureUsages.table.none.role: "No se declaran indicadores de uso de la textura." -concepts.resources.textureUsages.table.sampled.role: "Datos de textura leídos mediante un enlace de textura muestreada." -concepts.resources.textureUsages.table.storage.role: "Datos de textura disponibles para lectura o escritura del sombreador mediante un enlace de textura de almacenamiento." -concepts.resources.textureUsages.table.transferDst.role: "Almacenamiento de imagen de destino para una copia de GPU." -concepts.resources.textureUsages.table.transferSrc.role: "Datos de imagen de origen para una copia de GPU." -concepts.resources.textureUsages.title: "Usos de textura" -concepts.resources.title: "Administración de recursos" -concepts.resources.transfers.context: "Una descarga copia primero los datos de la GPU a un almacenamiento interno de lectura. La biblioteca los copia al destino de CPU indicado cuando recupera el búfer de comandos completado. La llamada a {wait} sobre el valor de envío de la descarga completa ambos pasos. Mantenga el destino asignado y la memoria administrada anclada hasta que esa llamada retorne." -concepts.resources.transfers.description: "Las cargas copian datos de la CPU a un recurso de la GPU; las descargas copian datos del recurso a la memoria de la CPU. Los métodos de búferes y texturas completan la transferencia antes de retornar:" -concepts.resources.transfers.details: "Antes de llamar a estos métodos, resuelva los accesos en conflicto de otras colas. La espera interna del método abarca su propia transferencia y no establece una dependencia con otra cola. Cuando se copia directamente a través de memoria mapeada, corresponde al llamador esperar a los accesos de la GPU que entren en conflicto." -concepts.resources.transfers.guidance: "Para enviar transferencias junto con otro trabajo de la GPU, grábelas con {commandBufferUpload} o {commandBufferDownload}. La memoria de origen de una carga y la de destino de una descarga tienen requisitos de vida útil distintos:" -concepts.resources.transfers.item: "Durante una llamada de carga, la biblioteca copia los datos de origen a un almacenamiento temporal de transferencia. Después, la GPU lee los datos desde ese almacenamiento, por lo que el puntero de origen de la aplicación solo debe permanecer válido hasta que retorna la llamada." -concepts.resources.transfers.notes: "En las transferencias de texturas, el paso de fila es la distancia en bytes entre filas consecutivas de datos de la CPU; el paso de sección es la distancia entre secciones de profundidad consecutivas. Estos valores permiten copiar los datos entre su organización en la CPU y el almacenamiento de la textura en la GPU. {link} explica por qué terminar la copia en la GPU y entregar los datos al destino de una descarga son pasos distintos." -concepts.resources.transfers.notes.link: "Sincronización" -concepts.resources.transfers.table.bufferDownload.transfer: "Para {cpuReadOnly}, copia directamente desde la memoria mapeada. En los demás casos, envía la descarga a la cola de transferencia y espera a que termine." -concepts.resources.transfers.table.bufferUpload.transfer: "Para {cpuWriteOnly}, copia directamente a la memoria mapeada. En los demás casos, envía la carga a la cola de transferencia y espera a que termine." -concepts.resources.transfers.table.headings.method: "Método" -concepts.resources.transfers.table.headings.transfer: "Comportamiento de transferencia" -concepts.resources.transfers.table.textureTransfers.method: "{textureUpload} / {textureDownload}" -concepts.resources.transfers.table.textureTransfers.transfer: "Envía la copia y las transiciones de textura a la cola gráfica y espera a que terminen. El subrecurso seleccionado queda en la disposición final solicitada." -concepts.resources.transfers.title: "Transferencias inmediatas y grabadas" -concepts.resources.usages.description: "{bufferUsages} y {textureUsages} son enumeraciones de indicadores que declaran los usos de un recurso. Se asignan a {bufferDescUsages} y {textureDescUsages}, respectivamente. Para varios usos, se combinan los miembros necesarios mediante {value}." -concepts.resources.usages.title: "Usos de recursos" -concepts.resources.views.description: "Una {bufferView} describe una región de un búfer y cómo se interpretan sus datos. Una {textureView} selecciona un intervalo de subrecursos y un tipo y formato de textura compatibles. Ambas se refieren al almacenamiento existente, con los usos declarados al crearlo. Los intervalos de las vistas describen el acceso, pero no garantizan una comprobación de límites uniforme en los sombreadores de todos los backends." -concepts.resources.views.details: "El identificador del propio recurso proporciona su vista predeterminada. Cree otra vista para seleccionar una región o una interpretación compatible diferente. Mantenga vivos tanto la vista como el recurso que la respalda hasta que la GPU termine de utilizarlos; un identificador no conserva ninguno de los dos objetos. Si sustituye alguno, actualice las constantes que contengan el {link} anterior." -concepts.resources.views.details.link: "identificador de recurso" -concepts.resources.views.title: "Vistas y recursos subyacentes" -concepts.shaders.binding.context: "El ejemplo asigna {inputTextureSampledHandle} a {input} y {outputTextureStorageHandle} a {output}. En Slang, el parámetro de tipo de {descriptorHandle} determina cómo se accede al recurso:" -concepts.shaders.binding.description: "{setConstantBuffer} selecciona un búfer existente y el desplazamiento de byte desde el que la canalización actual lee sus constantes. Cargue los parámetros en ese almacenamiento antes de que los utilice el sombreador. Si un trabajo anterior de la GPU todavía lee esos bytes, espere a que termine antes de actualizarlos." -concepts.shaders.binding.details: "Con el búfer de comandos, la canalización de cálculo, el búfer de constantes cargado y el número de grupos de hilos preparados, grabe el despacho en este orden. Seleccione primero la canalización, ya que el enlace del búfer de constantes se aplica a ella:" -concepts.shaders.binding.guidance: "Aquí, {commandBuffer} graba un despacho con {computePipeline} y los parámetros almacenados en {constantBuffer}. El búfer necesita el uso {bufferUsagesConstant}, y el desplazamiento 0 selecciona su comienzo. Si varios registros de constantes comparten un búfer, el desplazamiento inicial de cada registro debe cumplir también la alineación de enlace del backend, con independencia de la disposición de sus campos internos." -concepts.shaders.binding.notes: "{resourceHandle} contiene dos campos de 32 bits cuya interpretación depende del backend. Sus valores solo son válidos en el contexto donde se creó el recurso." -concepts.shaders.binding.reference: "El recurso y su vista deben conservarse hasta el último acceso del sombreador. Sustituir una textura o vista exige actualizar las constantes con el identificador anterior. Las reglas de propiedad se detallan en {link}." -concepts.shaders.binding.reference.link: "Administración de recursos" -concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: "Lectura de elementos estructurados del tipo {t} del sombreador" -concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: "Lectura y escritura de elementos estructurados del tipo {t} del sombreador" -concepts.shaders.binding.table.headings.access: "Acceso previsto" -concepts.shaders.binding.table.headings.cHandle: "Identificador de C#" -concepts.shaders.binding.table.headings.slangFieldType: "Tipo de campo Slang" -concepts.shaders.binding.table.samplerHandle.access: "Estado de muestreo de texturas" -concepts.shaders.binding.table.textureSampledHandle.access: "Lectura de texturas" -concepts.shaders.binding.table.textureStorageHandle.access: "Lectura y escritura de texturas de almacenamiento" -concepts.shaders.binding.title: "Constantes e identificadores de recursos" -concepts.shaders.compilation.description: "{zenithCompiler} compila un punto de entrada Slang en un {shaderDesc}. {graphicsApi} selecciona DXIL para DirectX 12, una biblioteca Metal para Metal o SPIR-V para Vulkan." -concepts.shaders.compilation.details: "Con un contexto gráfico ya creado y llamado {context}, compile el sombreador del triángulo a partir de la copia situada junto al ejecutable:" -concepts.shaders.compilation.guidance: "El nombre del punto de entrada {vSMain} debe coincidir con la declaración del archivo de sombreadores. Compile los sombreadores y cree las canalizaciones durante la inicialización; después, reutilice las canalizaciones al renderizar. Una vez creadas, los objetos sombreador se pueden liberar, como muestra {link}." -concepts.shaders.compilation.guidance.link: "Primer triángulo" -concepts.shaders.compilation.title: "Compilación de sombreadores" -concepts.shaders.description: "Las declaraciones de C# y Slang deben coincidir en la ubicación de cada valor y en la forma de acceder a él desde el sombreador. Las disposiciones de entrada describen los atributos de los vértices; las declaraciones de búferes del sombreador describen parámetros y arrays; los identificadores señalan los recursos que utiliza el sombreador." -concepts.shaders.dispatch.description: "{dispatch} indica cuántos grupos de hilos se ejecutan. El ejemplo de cálculo declara {numthreads}, por lo que cada grupo contiene 16 × 16 hilos. Para cubrir una imagen, divida el ancho y el alto entre 16 y redondee cada resultado hacia arriba: una imagen de 17 × 19 necesita 2 × 2 grupos. El sombreador comprueba las coordenadas de cada hilo y omite los que quedan fuera de la imagen." -concepts.shaders.dispatch.details: "El tamaño de grupo declarado está disponible en {shaderDescThreadGroupSize} y permite calcular los grupos que se pasan a {dispatch}. {computeShaderRendererCs} muestra el cálculo completo. Después del despacho, el acceso a la imagen resultante debe seguir los requisitos descritos en {link}." -concepts.shaders.dispatch.details.link: "Sincronización" -concepts.shaders.dispatch.title: "Grupos de hilos" -concepts.shaders.layout.context: "Las {link} muestran esta organización con las dimensiones de una imagen y dos identificadores de textura. Los desplazamientos explícitos indican dónde comienza cada campo. La declaración utiliza {systemRuntimeInteropServices} y {zenithNET}:" -concepts.shaders.layout.context.link: "constantes de C# del ejemplo de cálculo" -concepts.shaders.layout.description: "Para la entrada de vértices, {inputLayout} describe el formato, el desplazamiento y la semántica de cada atributo, junto con el paso entre vértices. El triángulo coloca una posición {float3} antes de un color {float4}: el color comienza en el desplazamiento de byte 12 y cada vértice ocupa 28 bytes. {inputLayoutAdd} calcula esta disposición compacta a partir de los formatos. Si la estructura de C# contiene relleno, indique desplazamientos y un paso que lo tengan en cuenta." -concepts.shaders.layout.details: "Los búferes de constantes contienen parámetros del sombreador, y los búferes estructurados contienen arrays de elementos tipados. Su disposición sigue las declaraciones de Slang, no {inputLayout}. Ajuste los desplazamientos, tamaños de elemento y relleno de C# a la disposición del sombreador compilado. Un tipo no administrado de C# se puede copiar byte a byte, pero su disposición en memoria no tiene por qué coincidir con la del sombreador; un {float3} empaquetado para un vértice puede necesitar otra alineación en un búfer del sombreador." -concepts.shaders.layout.guidance: "Los parámetros del sombreador pueden incluir identificadores de recursos además de valores ordinarios. Un identificador se refiere a almacenamiento ya existente, por lo que copiarlo a un búfer de constantes no copia el contenido del recurso." -concepts.shaders.layout.notes: "La declaración correspondiente en {computeShaderSlang} es:" -concepts.shaders.layout.reference: "Las dos dimensiones ocupan los primeros ocho bytes, seguidas de dos identificadores de ocho bytes cada uno. El ejemplo de C# reserva 256 bytes para el registro completo. El tamaño de otros registros se debe calcular a partir de sus propios campos y requisitos de disposición y alineación." -concepts.shaders.layout.title: "Disposición de los datos" -concepts.shaders.matrices.description: "El compilador almacena las matrices por filas contiguas. El {link} sitúa tres valores {matrix4x4} en los desplazamientos 0, 64 y 128. Su {detail} aplica {mulVectorMatrix} en el orden modelo, vista y proyección." -concepts.shaders.matrices.description.detail: "sombreador" -concepts.shaders.matrices.description.link: "renderizador de cubo giratorio" -concepts.shaders.matrices.details: "El orden de almacenamiento define la disposición de los elementos de la matriz en memoria; el de multiplicación define la transformación. Las convenciones de C# y Slang deben coincidir." -concepts.shaders.matrices.title: "Convenciones matriciales" -concepts.shaders.title: "Datos de sombreadores y enlace" -concepts.synchronization.backends.description: "DirectX 12 y Vulkan codifican las transiciones de textura como cambios de disposición y acceso. En Metal, la implementación de {transition} de Zenith.NET no realiza una operación equivalente. El backend de Metal agrupa los comandos en codificadores de renderizado y cálculo e inserta barreras de visibilidad cuando termina un codificador. Las operaciones dependientes dentro del mismo codificador, como los despachos de cálculo sucesivos, utilizan llamadas explícitas a {barrier}." -concepts.synchronization.backends.details: "En el {link}, iniciar la pasada gráfica termina el codificador de cálculo y hace visible su salida para el trabajo gráfico. Dos despachos de cálculo consecutivos permanecen en el mismo codificador, de modo que necesitan una barrera aunque se grabe una transición de textura entre ellos. Por eso, una secuencia de comandos portable debe contemplar tanto las dependencias de acceso como las disposiciones de textura." -concepts.synchronization.backends.details.link: "ejemplo de cálculo" -concepts.synchronization.backends.title: "Comportamiento de los backends" -concepts.synchronization.barriers.context: "Elija etapas que incluyan los accesos implicados y que admita la cola. {barrierStagesAll} incluye todas las etapas admitidas; seleccione un conjunto más reducido si la dependencia solo afecta a esas etapas." -concepts.synchronization.barriers.description: "Considere dos despachos de cálculo grabados en el mismo búfer de comandos: el primero escribe datos de simulación y el segundo los lee. Coloque una barrera entre ambos para que el segundo vea las escrituras completadas. En un búfer de almacenamiento, esto ordena los accesos sin una transición de disposición de textura:" -concepts.synchronization.barriers.details: "El primer argumento identifica las etapas que producen los datos; el segundo, las que los consumen. Juntos describen el orden de ejecución y la visibilidad de memoria necesarios entre los dos despachos." -concepts.synchronization.barriers.guidance: "La {link} aplica este patrón entre los pasos de simulación. Cada barrera va después del despacho que produce los datos y antes del que los utiliza." -concepts.synchronization.barriers.guidance.link: "simulación FluidTank" -concepts.synchronization.barriers.title: "Barreras de canalización" -concepts.synchronization.dependencies.description: "Para cada recurso, identifique los accesos que afectan a los mismos datos. Si alguno escribe, conserve el orden necesario entre ellos. Dos lecturas no entran en conflicto, aunque siguen vigentes los requisitos de disposición de textura y presentación. Las actualizaciones de la CPU y la liberación de recursos también deben esperar a que la GPU termine de utilizar el almacenamiento afectado." -concepts.synchronization.dependencies.details: "El mecanismo se elige según dónde se ejecutan las operaciones:" -concepts.synchronization.dependencies.guidance: "Una carga de trabajo puede necesitar varios mecanismos. Por ejemplo, una textura producida en otra cola necesita una dependencia entre envíos y la disposición adecuada para su siguiente uso. Ninguna de estas operaciones exige bloquear la CPU, salvo que esta necesite acceder a los datos o liberarlos." -concepts.synchronization.dependencies.table.cpuAccess.mechanism: "Llamar a {wait} en el valor de finalización correspondiente." -concepts.synchronization.dependencies.table.cpuAccess.situation: "El acceso de la CPU o la liberación de recursos depende de la finalización en la GPU" -concepts.synchronization.dependencies.table.crossQueue.mechanism: "Pase el {timelineValue} del productor a {submit} del consumidor." -concepts.synchronization.dependencies.table.crossQueue.situation: "Una cola consume datos producidos en otra" -concepts.synchronization.dependencies.table.headings.mechanism: "Mecanismo" -concepts.synchronization.dependencies.table.headings.situation: "Situación" -concepts.synchronization.dependencies.table.layoutChange.mechanism: "{commandBufferTransition} con sus disposiciones anterior y siguiente." -concepts.synchronization.dependencies.table.layoutChange.situation: "Un subrecurso de textura cambia cómo se utiliza" -concepts.synchronization.dependencies.table.pipelineStages.mechanism: "{commandBufferBarrier} con las etapas productora y consumidora." -concepts.synchronization.dependencies.table.pipelineStages.situation: "Etapas de GPU dependientes en un flujo de comandos" -concepts.synchronization.dependencies.title: "Dependencias de acceso" -concepts.synchronization.description: "La sincronización establece el orden de acceso a los datos compartidos y permite que las operaciones posteriores vean los resultados que necesitan. En una dependencia de escritura a lectura, quien escribe es el productor y quien lee es el consumidor. Las barreras y las transiciones coordinan los accesos de la GPU; las líneas de tiempo conectan envíos y permiten que la CPU espere a que termine el trabajo de la GPU." -concepts.synchronization.layouts.context: "Use {undefined} como disposición anterior cuando se pueda descartar el contenido, por ejemplo, en una imagen nueva o en un adjunto que se vaya a borrar por completo. Para conservarlo para una carga, un muestreo o una acumulación, indique la disposición del acceso anterior." -concepts.synchronization.layouts.description: "Los indicadores de uso declaran las funciones permitidas de una textura. {textureLayout} describe cómo se accede a un subrecurso, identificado por un nivel de mip y una capa de array, en un punto concreto de la secuencia de comandos. Cuando cambia ese acceso, grabe una transición. En el ejemplo de cálculo, la textura de salida se escribe en disposición {storage} y después se prepara para muestrearla en una pasada gráfica:" -concepts.synchronization.layouts.details: "{outputTexture} se creó con {sampledStorage}, y el subrecurso seleccionado está en {storage}. {default} elige el nivel mip 0 y la capa 0. Los demás niveles y capas no cambian." -concepts.synchronization.layouts.guidance: "En {transition}, indique la disposición del uso anterior del subrecurso. La aplicación debe mantener actualizado este estado al grabar comandos y pasar texturas entre las etapas de renderizado." -concepts.synchronization.layouts.title: "Disposiciones de textura" -concepts.synchronization.readback.description: "{isCompleted} informa de la finalización en la GPU. Una descarga grabada tiene un paso adicional: copiar el resultado del almacenamiento interno de lectura a la memoria de destino de la aplicación." -concepts.synchronization.readback.details: "{commandBufferDownload} graba la copia de la GPU a ese almacenamiento interno. Una vez terminado el envío, la biblioteca realiza la copia de CPU al recuperar el búfer de comandos completado. Llamar a {wait} sobre el valor de envío de la descarga espera a la GPU y procesa los búferes completados de esa cola, con lo que termina ambos pasos. Mantenga el destino asignado y la memoria administrada anclada hasta que retorne la llamada." -concepts.synchronization.readback.guidance: "Consultar {isCompleted} por sí solo no realiza la copia final de CPU. Esperar en otra cola tampoco recupera los búferes completados de la cola de descarga. {link} describe cuándo las cargas y descargas utilizan acceso directo o almacenamiento temporal de transferencia." -concepts.synchronization.readback.guidance.link: "Administración de recursos" -concepts.synchronization.readback.title: "Finalización de la lectura en CPU" -concepts.synchronization.reuse.description: "El triángulo espera a que termine cada fotograma antes de reutilizar sus datos. Para solapar fotogramas, reserve almacenamiento modificable para cada uno de los que estén en curso y registre cuándo vuelve a estar disponible. Antes de cambiar datos, espere al trabajo de la GPU que todavía acceda a esos bytes; antes de liberar un recurso, espere a todos sus usos pendientes." -concepts.synchronization.reuse.details: "El redimensionamiento y el cierre siguen la misma regla: impedir nuevos usos, esperar a que terminen los existentes y sustituir o liberar los recursos. Respete ese orden antes de llamar a {swapChainResize} o liberar recursos o el contexto. Como el triángulo ya espera en cada fotograma, puede redimensionar entre las llamadas a sus funciones de respuesta." -concepts.synchronization.reuse.guidance: "{swapChainPresent} señala un punto de la cola gráfica y espera a él después de la presentación. Por tanto, el triángulo sigue esperando al presentar aunque se elimine la espera explícita del envío. El trabajo independiente de otras colas necesita su propio seguimiento de finalización." -concepts.synchronization.reuse.title: "Reutilización de recursos" -concepts.synchronization.timelines.context: "Si la CPU necesita leer el resultado, sobrescribir los datos compartidos o liberar los recursos cuando termine el consumidor, espere a ese envío:" -concepts.synchronization.timelines.description: "Una línea de tiempo identifica la finalización con valores crecientes. {submit} devuelve un {timelineValue} con la línea y el valor del envío. Los campos numéricos {value} de líneas distintas no se comparan directamente." -concepts.synchronization.timelines.details: "Sean {producer} y {consumer} búferes grabados en dos colas del mismo contexto, donde el segundo usa los datos del primero. Su envío establece esta dependencia:" -concepts.synchronization.timelines.guidance: "La cola consumidora espera al valor de finalización recibido antes de ejecutar sus comandos. La CPU puede continuar sin llamar a {producedWait}. Conserve los recursos compartidos hasta que se complete {consumed} y grabe las transiciones de textura que necesite el acceso del consumidor." -concepts.synchronization.timelines.notes: "El valor que devuelve {queueTimelineSignal} también permite esperar con {wait} o establecer una dependencia para otra cola. {signal} coloca ese punto de finalización después del trabajo ya enviado; la GPU lo alcanza cuando termina dicho trabajo." -concepts.synchronization.timelines.title: "Líneas de tiempo y dependencias entre colas" -concepts.synchronization.title: "Sincronización" -home.actions.reference: "Explorar API" -home.actions.tutorial: "Comenzar con un triángulo" -home.entries.description: "Tutoriales, ejemplos y referencia de la API" -home.entries.label: "Secciones de la documentación" -home.entries.reference.action: "Explorar la API" -home.entries.reference.category: "Referencia" -home.entries.reference.description: "Consultar tipos, miembros y declaraciones de la API" -home.entries.reference.title: "Referencia de la API" -home.entries.samples.action: "Examinar ejemplos" -home.entries.samples.category: "Ejemplos" -home.entries.samples.description: "Ejemplos ejecutables de técnicas gráficas y de cálculo" -home.entries.samples.title: "Ejemplos" -home.entries.title: "Documentación" -home.entries.tutorial.action: "Iniciar tutorial" -home.entries.tutorial.category: "Tutorial" -home.entries.tutorial.description: "De un proyecto vacío al primer triángulo en pantalla" -home.entries.tutorial.title: "Primer triángulo" -home.introduction.accent: "con .NET" -home.introduction.description: "Zenith.NET ofrece una API común de gráficos y cálculo para DirectX, Metal y Vulkan" -home.introduction.title: "Gráficos multiplataforma{lineBreak}{accent}" -home.meta.description: "Desarrollo gráfico y de cálculo multiplataforma en .NET con una API común para DirectX, Metal y Vulkan" -home.scene.description: "Geometría interactiva en rotación. Arrastre o utilice las flechas para cambiar la vista." -home.scene.label: "Visualización geométrica" -home.scene.surface: "Superficie" -home.scene.wireframe: "Estructura alámbrica" -home.title: "API gráfica para .NET" -learning.concepts.description: "Criterios para elegir usos de recursos, describir datos de sombreadores y coordinar la ejecución en la GPU" -learning.concepts.execution.description: "Grabación, envío y tiempo de vida de los recursos" -learning.concepts.platforms.description: "Presentación nativa y controles de renderizado" -learning.concepts.resources.description: "Usos de recursos, ubicación de memoria y vistas" -learning.concepts.shaders.description: "Convenciones de disposición y enlace entre C# y Slang" -learning.concepts.synchronization.description: "Dependencias, visibilidad y finalización" -learning.concepts.title: "Conceptos básicos" -learning.description: "Empiece por el tutorial del triángulo para crear su primera aplicación. Después, consulte los conceptos de gestión de recursos, datos de sombreadores y sincronización, o elija un ejemplo de la técnica que quiera implementar." -learning.entries.samples.action: "Examinar ejemplos" -learning.entries.samples.description: "Implementaciones C# y Slang de geometría, cálculo, consultas de rayos y sombreado de mallas" -learning.entries.tutorial.action: "Abrir tutorial" -learning.entries.tutorial.description: "Una aplicación de consola que abre una ventana y renderiza un triángulo" -learning.meta.description: "Tutoriales y conceptos del modelo de programación de Zenith.NET" -learning.title: "Aprender" -reference.description: "Referencia de recursos, comandos e integración de plataformas" -reference.entries.commands.description: "Comandos gráficos, de cálculo y de transferencia" -reference.entries.commands.label: "Registrar comandos" -reference.entries.context.description: "Creación de recursos GPU para el backend elegido" -reference.entries.context.label: "Empezar aquí" -reference.meta.description: "Espacios de nombres, tipos y miembros de Zenith.NET" -reference.navigation.core: "Referencia de la API principal" -reference.title: "Referencia de la API" -samples.computeShader.description: "El ejemplo carga la imagen {assetsTexturesShokoPng}, la convierte a escala de grises en un despacho de cálculo y muestra la textura resultante. La conversión se ejecuta una vez; los fotogramas siguientes muestran el mismo resultado. El renderizador ilustra cómo enlazar texturas para muestreo y escritura, redondear hacia arriba el número de grupos de hilos para cubrir la imagen y comprobar sus límites en el sombreador." -samples.computeShader.details: "{computeShaderRendererCs} · {computeShaderSlang}" -samples.computeShader.title: "Sombreador de cálculo" -samples.cube.description: "El cubo añade dibujo indexado, matrices de modelo, vista y proyección en un búfer de constantes y prueba de profundidad. Su textura de profundidad y plantilla {d32FloatS8UInt} se recrea al redimensionar." -samples.cube.details: "{spinningCubeRendererCs} · {spinningCubeSlang}" -samples.cube.title: "Cubo giratorio" -samples.description: "Cada ejemplo reúne un renderizador C# y su sombreador Slang en torno a una técnica. La configuración completa y la secuencia de renderizado se explican en {link}." -samples.description.link: "Primer triángulo" -samples.execution.description: "Ejecute el proyecto {link} y elija un ejemplo en el menú de la consola." -samples.execution.description.link: "ZenithTutorials" -samples.execution.title: "Ejecución de ejemplos" -samples.host.description: "{appCs} inicializa contexto, ventana y cadena de intercambio. En cada fotograma obtiene un búfer, llama al renderizador, envía los comandos y presenta el resultado. {iRendererCs} define actualización, renderizado, redimensionamiento y liberación." -samples.host.details: "Los renderizadores de cálculo y trazado de rayos producen texturas fuera de pantalla. {texturePresenterCs} y {presentTextureSlang} las dibujan en la textura de salida actual; después, el programa anfitrión compartido envía los comandos y presenta el fotograma." -samples.host.title: "Host y presentación" -samples.indirectDrawing.description: "El dibujo indirecto representa varias instancias de cubo mediante un búfer de argumentos de dibujo indexado y un búfer estructurado con datos por instancia. La CPU proporciona los argumentos y actualiza las transformaciones." -samples.indirectDrawing.details: "{indirectDrawingRendererCs} · {indirectDrawingSlang}" -samples.indirectDrawing.title: "Dibujo indirecto" -samples.meshShading.description: "Un sombreador de tareas descarta las instancias de esferas no visibles y pasa los índices restantes al sombreador de mallas, que genera la geometría. El renderizador comprueba {contextCapabilitiesMeshShadingSupported} antes de crear la canalización." -samples.meshShading.details: "{meshShadingRendererCs} · {meshShadingSlang}" -samples.meshShading.title: "Sombreado de mallas" -samples.rayTracing.description: "El ejemplo construye estructuras de aceleración de nivel inferior y superior para un suelo y esferas procedurales, y realiza consultas de rayos dentro de un sombreador de cálculo. Comprueba {contextCapabilitiesRayTracingSupported} antes de la inicialización." -samples.rayTracing.details: "{rayTracingRendererCs} · {rayTracingSlang}" -samples.rayTracing.title: "Trazado de rayos" -samples.title: "Ejemplos" -samples.triangle.description: "El triángulo asocia un búfer de vértices con su disposición de entrada y dibuja tres vértices mediante una canalización gráfica." -samples.triangle.details: "{helloTriangleRendererCs} · {helloTriangleSlang} · {link}" -samples.triangle.details.link: "Tutorial completo" -samples.triangle.title: "Hola triángulo" -samples.workloads.description: "El {link} del repositorio principal contiene aplicaciones de mayor escala que utilizan el código fuente de la biblioteca." -samples.workloads.description.link: "directorio Experiments" -samples.workloads.details: "Las aplicaciones con ventana usan los mismos caminos de Windows, macOS y Linux/X11. {link} describe los controles Avalonia, WinForms, WPF, WinUI/Uno y MAUI, su ciclo de fotogramas y sus implementaciones." -samples.workloads.details.link: "Integración de plataforma" -samples.workloads.table.cornellBox.example: "{link}" -samples.workloads.table.cornellBox.example.link: "CornellBox" -samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: "Trazado de caminos, reducción de ruido, asignación de tonos, aumento de resolución y controles ImGui. Requiere soporte de trazado de rayos." -samples.workloads.table.fluidTank.example: "{link}" -samples.workloads.table.fluidTank.example.link: "FluidTank" -samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: "Simulación de fluidos por cálculo, dependencias entre etapas de simulación y renderizado de superficies multipasada." -samples.workloads.table.headings.example: "Ejemplo" -samples.workloads.table.headings.whatItDemonstratesAndRequires: "Técnicas y requisitos" -samples.workloads.table.inkCanvas.example: "{link}" -samples.workloads.table.inkCanvas.example.link: "InkCanvas" -samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: "Dibujo con Skia y control de entrada en una ventana nativa. Requiere el backend y la biblioteca nativa de Skia para la plataforma de destino." -samples.workloads.table.platformDetection.example: "{link}" -samples.workloads.table.platformDetection.example.link: "PlatformDetection" -samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: "Intenta crear un contexto para cada backend e informa de las capacidades del dispositivo. Si un intento falla, lo muestra como no compatible; la causa puede estar en el dispositivo, el controlador o una dependencia de ejecución ausente." -samples.workloads.title: "Aplicaciones de mayor escala" -tutorial.context.description: "Un {graphicsContext} conecta la aplicación con la GPU mediante un backend y proporciona los métodos para crear los recursos de renderizado." -tutorial.context.details: "Inserte la inicialización del contexto {emphasis}:" -tutorial.context.details.emphasis: "después de las directivas using, antes de {iWindowWindow}" -tutorial.context.guidance: "Cada rama selecciona el backend de la plataforma y solicita la validación. Los mensajes de {validationMessage} aparecen en la consola." -tutorial.context.imports: "Añada las siguientes directivas using al principio de {programCs}:" -tutorial.context.title: "Contexto gráfico" -tutorial.description: "Este tutorial parte de un proyecto de consola .NET vacío para crear una aplicación que abre una ventana y dibuja un triángulo de colores." -tutorial.details: "El tutorial tiene tres puntos de comprobación: una ventana vacía, un fondo de color uniforme y el triángulo de colores. Ejecute la aplicación en cada uno antes de continuar con el siguiente paso." -tutorial.draw.context: "Los argumentos para {draw} son:" -tutorial.draw.description: "En {windowRender}, sustituya {addTheTriangleDrawCommandsHereLater} por estos comandos entre {beginRenderPass} y {endRenderPass}:" -tutorial.draw.details: "{setPipeline} selecciona sombreadores y estado. Debe preceder al enlace de vértices porque el backend lo interpreta según la disposición de entrada de la canalización." -tutorial.draw.guidance: "{setVertexBufferVertexBuffer} enlaza los datos de vértices ya cargados desde el desplazamiento de byte 0 a la ranura de entrada 0, que corresponde a la única entrada de {inputLayouts}." -tutorial.draw.notes: "Estas llamadas graban los comandos de dibujo. La llamada existente a {submitWait} los envía y espera a que termine la GPU; después, {present} solicita que se muestre la imagen completada. Conserve el borrado al inicio de la pasada para que la zona exterior al triángulo tenga un color de fondo definido." -tutorial.draw.table.firstInstance.meaning: "Comenzar la numeración de instancias en cero." -tutorial.draw.table.firstVertex.meaning: "Comenzar con el primer vértice en el búfer." -tutorial.draw.table.headings.argument: "Argumento" -tutorial.draw.table.headings.description: "Valor" -tutorial.draw.table.headings.meaning: "Significado" -tutorial.draw.table.instanceCount.meaning: "Dibujar una copia del triángulo." -tutorial.draw.table.vertexCount.meaning: "Leer tres vértices." -tutorial.draw.title: "Comandos de dibujo" -tutorial.execution.description: "Compile y ejecute el proyecto {firstTriangle}." -tutorial.execution.details: "Debería aparecer un triángulo sobre un fondo oscuro, rojo arriba, verde abajo a la derecha y azul abajo a la izquierda. La interpolación de los colores de los vértices forma un degradado suave en el interior." -tutorial.execution.guidance: "Al redimensionar, cambian las dimensiones de la imagen en píxeles, pero las coordenadas de los vértices permanecen iguales. El área de visualización adapta esas coordenadas al nuevo ancho y alto, por lo que el triángulo se deforma si cambia la relación de aspecto de la ventana." -tutorial.execution.title: "Ejecución de la aplicación" -tutorial.frame.commands.context: "Después de {endRenderPass}, la segunda transición prepara la textura de salida para su presentación. {submit} termina la grabación y envía el búfer de comandos; {wait} bloquea el hilo hasta que termina ese envío. A continuación, {present} solicita que se muestre la imagen renderizada." -tutorial.frame.commands.description: "Una pasada de renderizado agrupa las operaciones de dibujo que escriben en los mismos adjuntos. En esta pasada, la textura de salida de la cadena de intercambio recibe el color. {colorAttachmentClear} indica cómo inicializar ese adjunto con un color RGBA y conservar su contenido al terminar la pasada. {beginRenderPass} graba el inicio de la pasada con estos ajustes." -tutorial.frame.commands.details: "La colección contiene un adjunto de color. {null} indica que la pasada no tiene adjunto de profundidad y plantilla." -tutorial.frame.commands.guidance: "{beginRenderPass} configura el área de visualización y el rectángulo de recorte para cubrir todo el adjunto. El área de visualización transforma las coordenadas de renderizado en posiciones de píxeles; el rectángulo de recorte limita dónde se puede escribir." -tutorial.frame.commands.title: "Borrado, envío y presentación" -tutorial.frame.description: "Comience por rellenar la ventana con un color de fondo. Esta operación se llama borrado. Cuando el fondo aparece, la superficie, el envío y la presentación ya funcionan juntos y se pueden añadir los vértices y los sombreadores del triángulo." -tutorial.frame.details: "Silk.NET invoca el callback cuando corresponde producir un fotograma. El argumento de tiempo transcurrido no se usa y se denomina {value}. Registre el callback {emphasis}:" -tutorial.frame.details.emphasis: "antes de {windowRun}" -tutorial.frame.target.description: "{graphicsQueueCommandBuffer} devuelve un búfer listo para grabar. La grabación describe trabajo GPU; la ejecución comienza después del envío." -tutorial.frame.target.details: "La disposición de una textura describe el acceso que necesita una operación. La primera llamada a {transition} prepara la textura de salida para usarla como adjunto de color. Aquí, {default} selecciona el nivel de mip 0 y la capa 0 del array, es decir, la imagen base de la textura. Como esta pasada borra toda la imagen, {undefined} permite descartar su contenido anterior." -tutorial.frame.target.guidance: "Obtenga la textura de salida en cada fotograma, ya que la presentación puede seleccionar una imagen distinta." -tutorial.frame.target.title: "Preparación de la salida" -tutorial.frame.title: "Primer fotograma" -tutorial.geometry.data.description: "Añada el array de vértices {emphasis}. Mantenga también las siguientes inicializaciones de recursos antes de este callback, en el orden indicado." -tutorial.geometry.data.description.emphasis: "antes de {windowRender}" -tutorial.geometry.data.details: "Cada entrada construye un {vertex}; las dos expresiones {new} internas aportan posición {vector3} y color {vector4}. Las posiciones forman los vértices superior, inferior derecho e inferior izquierdo. El sombreador añade {w} como cuarta coordenada. Con w = 1, x e y son coordenadas normalizadas del dispositivo: -1 y +1 delimitan la imagen y 0 marca el centro, independientemente de los píxeles." -tutorial.geometry.data.guidance: "Cada color tiene componentes rojo, verde, azul y alfa, con alfa igual a 1. Los tres vértices tienen z = 0 y están en el mismo plano." -tutorial.geometry.data.title: "Posiciones y colores" -tutorial.geometry.description: "Cada uno de los tres vértices tiene una posición y un color. La GPU determina la forma del triángulo a partir de las posiciones e interpola los colores por su superficie." -tutorial.geometry.format.description: "Añada la declaración del vértice {emphasis}:" -tutorial.geometry.format.description.emphasis: "al final de {programCs}, después de las instrucciones de limpieza" -tutorial.geometry.format.details: "{file} limita el tipo a {programCs}, y {layoutKindSequential} mantiene los campos en su orden de declaración. {position} contiene tres valores de coma flotante de 32 bits y comienza en el desplazamiento de byte 0; {color} contiene cuatro y comienza en el desplazamiento de byte 12. Cada vértice ocupa, por tanto, 28 bytes. La disposición de entrada describirá esta organización para que la GPU lea los campos correctamente." -tutorial.geometry.format.imports: "Añada estas directivas using al principio de {programCs} para utilizar los tipos vectoriales y el atributo que define la disposición de la estructura:" -tutorial.geometry.format.title: "Representación del vértice" -tutorial.geometry.title: "Datos de vértices" -tutorial.geometry.upload.context: "{fixed} impide que el recolector de basura mueva el array mientras se usa su dirección. En este búfer escribible por la CPU, {upload} mapea la memoria, copia los bytes y deshace el mapeo antes de retornar. El array solo debe permanecer anclado durante la llamada. Cargue los vértices una vez durante la inicialización y conserve el búfer hasta que termine el renderizado." -tutorial.geometry.upload.description: "Guarde los vértices en un {buffer} para que la GPU pueda leerlos al dibujar. Añada la asignación y la carga de datos justo después del array:" -tutorial.geometry.upload.details: "{sizeofVertexVerticesLength} equivale a tres vértices de 28 bytes, 84 bytes en total. {bufferUsagesVertex} declara acceso de entrada, y {cpuWriteOnly} permite inicialización directa por CPU. El paso del descriptor registra el tamaño del elemento; la disposición posterior define cada atributo." -tutorial.geometry.upload.guidance: "La asignación no inicializa el contenido del búfer. {upload} copia el array al desplazamiento de destino 0 utilizando el puntero de origen y el número de bytes de la descripción de datos." -tutorial.geometry.upload.imports: "En {programCs}, añada {bufferAlias} a las directivas using para distinguir el tipo de búfer de Zenith.NET de {systemBuffer}." -tutorial.geometry.upload.notes: "Coloque {vertexBufferDispose} justo antes de {swapChainDispose} al final de {programCs}. {link} trata el almacenamiento exclusivo de GPU y las cargas para geometrías mayores." -tutorial.geometry.upload.notes.link: "Administración de recursos" -tutorial.geometry.upload.title: "Asignación y carga del búfer" -tutorial.input.description: "La GPU necesita saber dónde se guardan los atributos de cada vértice, como la posición y el color. La disposición de entrada indica su formato y desplazamiento, además del paso: la distancia en bytes hasta el siguiente vértice. Añada este código después de crear los sombreadores:" -tutorial.input.details: "{inputLayoutAdd} sitúa cada atributo a continuación del anterior y suma su tamaño al paso entre vértices. Calcula los desplazamientos a partir de los formatos indicados, sin inspeccionar la estructura de C#. Para estos dos campos, la disposición resultante es:" -tutorial.input.guidance: "El valor predeterminado de {semanticIndex} es cero, que corresponde a {pOSITION0} y {cOLOR0} en el sombreador. La posición y el color se almacenan juntos en un búfer de vértices, por lo que la canalización utiliza una sola disposición de entrada en la ranura 0. Si cambia el orden de los campos o el relleno de la estructura de C#, ajuste también esta disposición." -tutorial.input.table.headings.byteOffset: "Desplazamiento de bytes" -tutorial.input.table.headings.cField: "Campo de C#" -tutorial.input.table.headings.format: "Formato" -tutorial.input.table.headings.shaderInput: "Entrada del sombreador" -tutorial.input.table.nextVertex.cField: "Siguiente vértice" -tutorial.input.table.nextVertex.format: "Paso total: 28 bytes" -tutorial.input.table.nextVertex.shaderInput: "Siguiente registro de entrada" -tutorial.input.table.vertexColor.format: "{float4} (16 bytes)" -tutorial.input.table.vertexPosition.format: "{float3} (12 bytes)" -tutorial.input.title: "Disposición de entrada de vértices" -tutorial.lifecycle.description: "Cada fotograma sigue esta secuencia:" -tutorial.lifecycle.details: "Al cerrar la ventana, {run} retorna y la ejecución continúa en el código de limpieza. Como cada fotograma ya ha esperado a que terminen sus comandos, los recursos que utilizaban se pueden liberar. El bloque completo de limpieza después de {windowRun} es:" -tutorial.lifecycle.guidance: "Libere la cadena de intercambio antes de destruir su ventana nativa y el contexto después de sus recursos. La cola recicla los búferes de comandos enviados, y la cadena de intercambio gestiona la textura de salida; ninguno necesita una llamada independiente a {dispose}." -tutorial.lifecycle.title: "Ciclo del fotograma y limpieza" -tutorial.pipeline.behavior: "Tras la disposición de entrada, cree la canalización:" -tutorial.pipeline.context: "{cullNone} desactiva el descarte de caras, de modo que el triángulo se dibuja tanto si sus vértices aparecen en sentido horario como antihorario." -tutorial.pipeline.description: "Una {graphicsPipeline} reúne la disposición de los vértices, los dos sombreadores y los ajustes para ensamblar primitivas y escribir en los adjuntos." -tutorial.pipeline.details: "Los sombreadores procesan vértices y fragmentos. Los demás ajustes de la canalización controlan el ensamblado de primitivas, el descarte de caras, la prueba de profundidad y la mezcla de colores:" -tutorial.pipeline.guidance: "El formato debe coincidir con el adjunto de la pasada, por lo que procede de {swapChainDescFormat}. {count1} especifica una muestra por píxel." -tutorial.pipeline.item: "{triangleList} ensambla cada grupo de tres vértices consecutivos en un triángulo." -tutorial.pipeline.notes: "{depthNone} desactiva pruebas y escrituras de profundidad, de acuerdo con la ausencia de ese adjunto." -tutorial.pipeline.reference: "{opaque} desactiva la mezcla. El color del fragmento sustituye así el fondo dentro del triángulo." -tutorial.pipeline.title: "Canalización gráfica" -tutorial.pipeline.usage: "Los objetos de sombreador pueden liberarse tras crear la canalización. Mantenga la canalización durante el renderizado y añada {pipelineDispose} antes de {vertexBufferDispose} en la limpieza." -tutorial.presentation.title: "Contexto gráfico y presentación" -tutorial.project.context: "Active {emphasis} ({allowUnsafeBlocks}) en la configuración de compilación. Las llamadas nativas de ventana y la carga de vértices necesitan código no seguro." -tutorial.project.context.emphasis: "Permitir código no seguro" -tutorial.project.description: "Cree un proyecto de consola C# llamado {firstTriangle} que tenga como destino .NET 10." -tutorial.project.details: "Añada los siguientes paquetes NuGet al proyecto:" -tutorial.project.guidance: "{zenithNET} aporta la API común y los tres paquetes de backend sus implementaciones. {zenithNETCompiler} compila los sombreadores Slang que se presentan a continuación. Silk.NET crea la ventana y procesa eventos." -tutorial.project.title: "Configuración del proyecto" -tutorial.requirements.context: "El {link} y su {detail} proporcionan las implementaciones de referencia del tutorial." -tutorial.requirements.context.detail: "host compartido" -tutorial.requirements.context.link: "ejemplo Hola triángulo" -tutorial.requirements.description: "Necesita el {emphasis} y conocimientos básicos de C#. La aplicación tiene {net10} como framework de destino. La GPU y el controlador deben admitir el backend elegido para su plataforma:" -tutorial.requirements.description.emphasis: "SDK de .NET 10" -tutorial.requirements.guidance: "Zenith.NET renderiza en una superficie nativa proporcionada por la aplicación. Silk.NET.Windowing crea la ventana y procesa eventos. En macOS se utiliza una capa Metal, representada por {cAMetalLayerCs}, que el código auxiliar conecta a la ventana." -tutorial.requirements.table.headings.graphicsBackend: "Backend gráfico" -tutorial.requirements.table.headings.platform: "Plataforma" -tutorial.requirements.table.linux.graphicsBackend: "Vulkan 1.4" -tutorial.requirements.table.linux.platform: "Linux (X11 o XWayland)" -tutorial.requirements.table.macOS.graphicsBackend: "Metal 4" -tutorial.requirements.table.macOS.platform: "macOS" -tutorial.requirements.table.windows.graphicsBackend: "DirectX 12" -tutorial.requirements.table.windows.platform: "Windows" -tutorial.requirements.title: "Requisitos previos" -tutorial.resize.context: "Compile y ejecute la aplicación de nuevo. El fondo debe seguir ocupando toda la ventana al cambiar su tamaño: cada nueva pasada ajusta el área de visualización y el rectángulo de recorte a las dimensiones del adjunto. Conserve la función de renderizado; el triángulo se dibujará dentro de esta misma pasada." -tutorial.resize.description: "La cadena de intercambio debe adaptarse a los cambios de tamaño del búfer de fotogramas. Registre una función para {framebufferResize} después de la función de renderizado y antes de {windowRun}:" -tutorial.resize.details: "Responda a los {link}, que se miden en píxeles, en lugar de a los cambios de tamaño lógico de la ventana. Si al minimizar la ventana alguna dimensión pasa a ser cero, la función de redimensionamiento mantiene la cadena de intercambio tal como está. La función de renderizado también retorna mientras alguna dimensión sea cero, de modo que el renderizado se reanuda cuando el búfer de fotogramas vuelve a tener un tamaño válido." -tutorial.resize.details.link: "cambios de tamaño del búfer de fotogramas" -tutorial.resize.guidance: "La función de renderizado espera a que termine cada fotograma enviado antes de llamar a {present}. Por ello, la función de redimensionamiento puede sustituir las imágenes de la cadena de intercambio sin interrumpir trabajo de un fotograma anterior. El artículo {link} explica la relación entre la finalización del trabajo y la vida útil de los recursos." -tutorial.resize.guidance.link: "Sincronización" -tutorial.resize.title: "Redimensionamiento" -tutorial.shaders.compilation.context: "{appContextBaseDirectory} permite cargar la copia del sombreador situada en el directorio de salida de la aplicación. Así, el archivo se busca en el mismo lugar aunque la aplicación se inicie desde otro directorio de trabajo." -tutorial.shaders.compilation.description: "Para {triangleSlang}, establezca {emphasis} en {detail}. La compilación copiará el archivo junto al ejecutable." -tutorial.shaders.compilation.description.detail: "Copiar si es posterior" -tutorial.shaders.compilation.description.emphasis: "Copiar en el directorio de salida" -tutorial.shaders.compilation.details: "En {programCs}, añada la inicialización de sombreadores después de cargar los vértices y antes del callback:" -tutorial.shaders.compilation.guidance: "{zenithCompiler} compila el código fuente para {contextGraphicsApi}, y {createShader} crea un objeto sombreador a partir de la descripción compilada. Los nombres de punto de entrada {vSMain} y {fSMain} seleccionan las dos funciones definidas en el archivo Slang." -tutorial.shaders.compilation.title: "Compilación de sombreadores" -tutorial.shaders.context: "{fSInput} conecta las dos etapas del sombreador. El sombreador de vértices escribe en {sVPOSITION} una posición en el espacio de recorte, que la GPU utiliza para determinar qué parte del triángulo es visible. El campo {cOLOR0} transporta el color del vértice, que se interpola sobre el triángulo antes de llegar al sombreador de fragmentos. Su tipo y su semántica deben coincidir en ambas etapas." -tutorial.shaders.description: "Los sombreadores son programas que se ejecutan en la GPU. El sombreador de vértices determina la posición de cada vértice, y el sombreador de fragmentos determina el color en cada posición cubierta de la imagen. Ambos se escribirán en un mismo archivo Slang, con un punto de entrada propio para cada etapa: la función por la que comienza su ejecución." -tutorial.shaders.details: "Cree {triangleSlang} con estas estructuras de entrada y salida:" -tutorial.shaders.fragment.description: "Añada el punto de entrada de fragmentos al mismo archivo:" -tutorial.shaders.fragment.details: "La rasterización determina qué zonas de la imagen cubre el triángulo y genera fragmentos en esas posiciones. Cada fragmento recibe un color interpolado a partir de los colores de los tres vértices. {fSMain} devuelve ese color, y {sVTARGET} dirige el resultado al primer adjunto de color." -tutorial.shaders.fragment.title: "Sombreado de fragmentos" -tutorial.shaders.guidance: "{vSInput} define las entradas del sombreador de vértices. {pOSITION0} y {cOLOR0} identifican atributos por semántica; los nombres C# no establecen esa correspondencia." -tutorial.shaders.title: "Etapas de sombreado" -tutorial.shaders.vertex.description: "Añada el punto de entrada de vértices a {triangleSlang}:" -tutorial.shaders.vertex.details: "La GPU invoca este punto para cada vértice, incorpora la coordenada homogénea {w} y transmite el color. La posición se divide después por w. Aquí vale 1, por lo que x, y y z no cambian y se interpretan como coordenadas normalizadas del dispositivo." -tutorial.shaders.vertex.title: "Sombreado de vértices" -tutorial.surface.description: "Defina el destino de presentación nativo {emphasis}:" -tutorial.surface.description.emphasis: "después de {windowCenter} y antes de {windowRun}" -tutorial.surface.details: "El búfer de fotogramas es la imagen de la ventana en píxeles. {surface} describe el destino nativo de presentación y sus dimensiones; {framebufferSize} proporciona el tamaño en píxeles. Con el escalado de pantalla, este puede diferir del tamaño lógico de la ventana." -tutorial.surface.guidance: "La superficie proporciona los identificadores nativos del backend: una ventana Win32 en Windows, una pantalla y una ventana X11 en Linux o la capa Metal conectada en macOS." -tutorial.surface.title: "Superficie nativa" -tutorial.swapChain.context: "La cadena depende del contexto y de la ventana. Sustituya {windowDispose} al final de {programCs} por este orden de liberación:" -tutorial.swapChain.description: "Cree la cadena inmediatamente después de describir la superficie:" -tutorial.swapChain.details: "La {swapChain} gestiona las imágenes presentadas. {drawable} suministra la actual como {texture}, el recurso de imagen de la API. Tras renderizar, {present} solicita mostrarla y avanza a la siguiente." -tutorial.swapChain.guidance: "{b8G8R8A8UNorm} almacena cuatro canales de 8 bits en orden azul, verde, rojo y alfa. {uNorm} hace corresponder 0–255 con 0–1. La salida sigue siendo RGBA lógico; el formato define su almacenamiento. La canalización usa {swapChainDescFormat} para coincidir con el adjunto." -tutorial.swapChain.title: "Cadena de intercambio" -tutorial.title: "Primer triángulo" -tutorial.troubleshooting.description: "Utilice los diagnósticos de consola y los tres puntos de control para localizar el fallo:" -tutorial.troubleshooting.details: "El {link} y el {detail} permiten contrastar datos, disposición y dibujo. El ejemplo separa ventana y envío en un host común; el tutorial mantiene el flujo en {programCs}. {context} introduce dibujo indexado, transformaciones y profundidad." -tutorial.troubleshooting.details.context: "Cubo giratorio" -tutorial.troubleshooting.details.detail: "sombreador Slang" -tutorial.troubleshooting.details.link: "renderizador de ejemplo" -tutorial.troubleshooting.table.backend.check: "Compruebe que el backend seleccionado sea compatible con el dispositivo y el controlador de gráficos instalado." -tutorial.troubleshooting.table.backend.symptom: "Falla la creación del backend" -tutorial.troubleshooting.table.drawing.check: "Compruebe el tamaño de la carga, la disposición de entrada, la selección de la canalización y la ubicación de los comandos de dibujo dentro de la pasada de renderizado." -tutorial.troubleshooting.table.drawing.symptom: "Aparece el fondo pero no el triángulo" -tutorial.troubleshooting.table.headings.check: "Comprobación" -tutorial.troubleshooting.table.headings.symptom: "Síntoma" -tutorial.troubleshooting.table.input.check: "Compruebe el paso de 28 bytes y los desplazamientos de posición/color de 0 y 12." -tutorial.troubleshooting.table.input.symptom: "Las posiciones o colores de los vértices están dañados" -tutorial.troubleshooting.table.shaders.check: "Compruebe el archivo {triangleSlang} copiado, la ortografía del punto de entrada y el diagnóstico notificado por el compilador." -tutorial.troubleshooting.table.shaders.symptom: "El fondo se muestra, pero falla la carga de los sombreadores" -tutorial.troubleshooting.table.window.check: "Confirme que el proyecto .NET se compila y que el paso de solo ventana se ejecuta en una sesión de escritorio. En Linux, compruebe que X11 o XWayland estén disponibles." -tutorial.troubleshooting.table.window.symptom: "No se abre ninguna ventana" -tutorial.troubleshooting.title: "Diagnóstico de problemas" -tutorial.window.description: "Descargue {cocoaHelperCs} en el directorio del proyecto. Esta clase auxiliar conecta la capa Metal a la ventana de macOS." -tutorial.window.details: "Sustituya el contenido generado de {programCs} por el código siguiente. Usa instrucciones de nivel superior que se ejecutan en orden, sin un método {main} explícito. Las siguientes secciones indicarán dónde añadir cada fragmento:" -tutorial.window.guidance: "{graphicsAPINone} deja la creación del contexto gráfico a Zenith.NET. {initialize} crea la ventana nativa y permite acceder a los identificadores del sistema de ventanas. {center} la coloca en el centro de la pantalla. {run} procesa los eventos hasta que se cierra; después se ejecuta {dispose} para liberarla." -tutorial.window.notes: "Compile y ejecute la aplicación. Compruebe que puede abrir, mover, redimensionar y cerrar la ventana. Su contenido aún no está definido porque no se han enviado comandos de renderizado. Cierre la ventana antes de continuar." -tutorial.window.title: "Creación de la ventana" -ui.action.copy: "Copiar" -ui.action.navigate: "Navegar" -ui.action.open: "Abrir" -ui.action.source: "Ver código fuente" -ui.api.browse: "Examinar espacios de nombres y tipos." -ui.api.clearTypeSearch: "Borrar búsqueda de tipos" -ui.api.findType: "Buscar un tipo" -ui.api.loadError: "No se pudieron cargar los tipos. Recargue esta página para intentarlo de nuevo." -ui.api.loadingNamespaces: "Cargando espacios de nombres…" -ui.api.loadingTypes: "Cargando tipos…" -ui.api.matchingTypes: "Tipos coincidentes" -ui.api.namespace: "Espacio de nombres" -ui.api.namespaces: "Espacios de nombres" -ui.api.noNamespaceTypes: "No hay tipos en este espacio de nombres." -ui.api.noTypes: "No hay tipos coincidentes." -ui.api.types: "Tipos" -ui.content.reference: "Referencia" -ui.content.source: "Código fuente" -ui.content.tutorial: "Tutorial" -ui.contents.close: "Cerrar el índice" -ui.contents.open: "Abrir el índice" -ui.contents.title: "Índice" -ui.footer.caption: "API gráfica para .NET" -ui.footer.label: "Pie de página" -ui.language.label: "Idioma" -ui.language.unavailable: "No traducido" -ui.members.clear: "Borrar búsqueda de miembros" -ui.members.close: "Cerrar buscador de miembros" -ui.members.empty: "No hay miembros coincidentes." -ui.members.open: "Ir al miembro" -ui.members.placeholder: "Nombre o firma…" -ui.members.search: "Buscar miembros" -ui.members.title: "Buscar un miembro" -ui.members.undeclared: "Este tipo no tiene miembros declarados." -ui.navigation.api: "API" -ui.navigation.concepts: "Conceptos" -ui.navigation.home: "Inicio" -ui.navigation.label: "Navegación principal" +concepts.execution.context.description: 'Un {graphicsContext} conecta la aplicación con un dispositivo GPU mediante un backend concreto y proporciona sus colas gráfica, de cálculo y de transferencia. Los recursos que se utilizan juntos deben pertenecer al mismo contexto; no se pueden enlazar búferes, texturas, sombreadores, canalizaciones ni sus identificadores entre contextos distintos.' +concepts.execution.context.details: '{capabilities} indica el nombre del dispositivo y las funciones que admite. Compruebe {rayTracingSupported} y {meshShadingSupported} antes de crear los recursos que necesitan esas funciones. Los ejemplos de {link} y {detail} realizan estas comprobaciones durante la inicialización.' +concepts.execution.context.details.detail: 'sombreado de mallas' +concepts.execution.context.details.link: 'trazado de rayos' +concepts.execution.context.title: 'Contexto gráfico' +concepts.execution.description: 'El trabajo de la GPU se prepara en la CPU: la aplicación crea recursos, graba comandos que los utilizan y envía esos comandos a una cola. Tras el envío, la CPU puede continuar mientras la GPU ejecuta el trabajo. Los recursos deben seguir disponibles hasta que esa ejecución termine.' +concepts.execution.ownership.description: 'La propiedad establece quién libera un objeto; la finalización en la GPU determina cuándo puede hacerlo. Una llamada a {dispose} libera los recursos nativos aunque aún existan referencias de C# al objeto. Enviar comandos no transfiere a la cola la propiedad de los recursos que utilizan.' +concepts.execution.ownership.details: 'Al cerrar la aplicación, deje de enviar trabajo y espere al último uso de los recursos en cada cola implicada. Después, libere los recursos de la aplicación y el contexto. El contexto libera sus colas y auxiliares internos, por lo que este último paso debe realizarse cuando todo el trabajo de la aplicación haya terminado.' +concepts.execution.ownership.guidance: 'Durante el renderizado, lleve un seguimiento del trabajo que utiliza datos que se van a sobrescribir o recursos que se van a sustituir. Espere a que termine antes de modificar o liberar el almacenamiento afectado. {link} explica cómo se aplica este modelo de vida útil a las vistas y a los recursos que las respaldan.' +concepts.execution.ownership.guidance.link: 'Administración de recursos' +concepts.execution.ownership.table.applicationResources.object: 'Recursos creados por la aplicación' +concepts.execution.ownership.table.applicationResources.ownership: 'La aplicación los libera después de su último uso en la GPU.' +concepts.execution.ownership.table.commandBuffers.object: 'Búferes de comandos prestados' +concepts.execution.ownership.table.commandBuffers.ownership: 'La cola los gestiona y los recicla.' +concepts.execution.ownership.table.headings.object: 'Objeto' +concepts.execution.ownership.table.headings.ownership: 'Responsabilidad de liberación' +concepts.execution.ownership.table.queues.object: 'Colas de contexto y sus líneas de tiempo' +concepts.execution.ownership.table.queues.ownership: 'El contexto y las colas las gestionan.' +concepts.execution.ownership.table.swapChainDrawable.ownership: 'La cadena de intercambio lo gestiona.' +concepts.execution.ownership.title: 'Propiedad y tiempo de vida' +concepts.execution.pipelines.description: 'Una canalización gráfica define los sombreadores, la disposición de entrada de vértices, el ensamblado de primitivas, los formatos de adjunto y el estado de renderizado. Se selecciona antes de enlazar vértices, índices o constantes. Los formatos y el número de muestras deben coincidir con la pasada de renderizado.' +concepts.execution.pipelines.details: 'Una canalización de cálculo selecciona el punto de entrada del sombreador que ejecutará un despacho. Enlace la canalización y sus constantes antes del despacho, fuera de una pasada de renderizado gráfico.' +concepts.execution.pipelines.guidance: 'La {link} presenta la secuencia gráfica. El {detail} incorpora un despacho de cálculo antes de la pasada que muestra su resultado.' +concepts.execution.pipelines.guidance.detail: 'ejemplo de cálculo' +concepts.execution.pipelines.guidance.link: 'función de renderizado del triángulo' +concepts.execution.pipelines.title: 'Estado de la canalización' +concepts.execution.queues.description: '{graphicsQueue} es el punto de partida habitual para un fotograma que combina dibujo, cálculo y copias. Agrupar operaciones dependientes en una cola simplifica su ordenación.' +concepts.execution.queues.details: 'Las colas permiten enviar cargas de trabajo independientes por separado, aunque no necesariamente corresponden a motores de hardware independientes. Use colas adicionales cuando resulte útil solapar la ejecución. Si una cola utiliza datos producidos por otra, conecte sus envíos mediante una dependencia explícita.' +concepts.execution.queues.guidance: 'Dentro de una cola, las operaciones dependientes también pueden necesitar barreras o transiciones de textura para que los accesos posteriores vean las escrituras anteriores. Estas dependencias de memoria son distintas del orden de envío; {link} explica cómo expresarlas.' +concepts.execution.queues.guidance.link: 'Sincronización' +concepts.execution.queues.table.computeQueue.workToRecord: 'Despachos de cálculo y transferencias compatibles, sin pasadas gráficas.' +concepts.execution.queues.table.graphicsQueue.workToRecord: 'Pasadas de renderizado, dibujo, cálculo y transferencias.' +concepts.execution.queues.table.headings.queue: 'Cola' +concepts.execution.queues.table.headings.workToRecord: 'Operaciones admitidas' +concepts.execution.queues.table.transferQueue.workToRecord: 'Cargas, descargas y copias, sin dibujo ni despachos de cálculo.' +concepts.execution.queues.title: 'Selección de colas' +concepts.execution.recording.context: 'La cola recupera los búferes de comandos completados para reutilizarlos. Obtenga uno con {queueCommandBuffer} para cada grabación, grabe desde un solo hilo a la vez y envíelo una única vez. Después del envío, deje que la cola lo gestione: no lo modifique, vuelva a enviar ni libere.' +concepts.execution.recording.description: '{queueCommandBuffer} devuelve un {commandBuffer} cuya grabación ya está iniciada. Tras grabar las operaciones y sus dependencias, se llama a {submit} una vez. El envío cierra la grabación y devuelve un {timelineValue} que identifica su finalización en esa cola.' +concepts.execution.recording.details: 'Tras grabar un fotograma en {commandBuffer}, el tutorial lo envía y espera de este modo:' +concepts.execution.recording.guidance: 'La grabación construye la secuencia de comandos; {submit} programa su ejecución. La llamada posterior a {wait} bloquea el hilo de la CPU hasta que termina ese envío. Así, el bucle del tutorial resulta fácil de seguir: cada fotograma termina antes de comenzar el siguiente.' +concepts.execution.recording.title: 'Grabación y envío' +concepts.execution.title: 'Modelo de ejecución' +concepts.platforms.description: 'La presentación puede gestionarla la aplicación o un control de interfaz. Esta elección determina quién obtiene la textura de salida del fotograma, registra y envía los comandos y presenta el resultado. Esa textura de salida se denomina drawable.' +concepts.platforms.frame.context: 'Grabe los enlaces de canalización y los comandos de dibujo dentro de la pasada y termínela antes de que retorne el manejador. El control envía los comandos y presenta el resultado. El manejador no debe enviar el búfer de comandos ni liberar ninguno de los objetos recibidos. Si cambia la disposición de la textura de salida, restáurela a {colorAttachment} antes de retornar para que el control pueda realizar la transición final.' +concepts.platforms.frame.description: 'Los controles implementan {iZenithView}. La aplicación asigna {graphicsContext}, actualiza la escena en {updateRequested} y graba en {renderRequested} mediante los {renderEventArgs} recibidos.' +concepts.platforms.frame.details: 'En cada fotograma, el control obtiene una textura de salida y un búfer de comandos, cambia la disposición de la textura a {colorAttachment} y llama a los manejadores de actualización y renderizado. Después envía el trabajo grabado y presenta la imagen mediante el mecanismo del framework.' +concepts.platforms.frame.guidance: 'Añada {usingZenithNET} al archivo. Para una instancia de {iZenithView} llamada {view}, ya inicializada y con un contexto gráfico asignado, registre este manejador del evento de renderizado para borrar la textura de salida que proporciona el control:' +concepts.platforms.frame.notes: 'La transición inicial utiliza {undefined}, que permite descartar el contenido anterior. Dibuje o borre la imagen completa en cada fotograma. Guarde el renderizado acumulado o en caché en una textura propia de la aplicación y dibújela después sobre la textura de salida del control.' +concepts.platforms.frame.reference: '{zenithViewHelperDrawableFormat} proporciona el formato de color predeterminado de estas integraciones.' +concepts.platforms.frame.title: 'Renderizado mediante controles de interfaz' +concepts.platforms.integration.context: 'WinForms, WPF y la integración Windows de WinUI se ejecutan en Windows. Para MAUI, instale la carga de trabajo de la plataforma de destino y registre el controlador con {useZenithView}, como se muestra en {extensionsCs}.' +concepts.platforms.integration.description: 'La interfaz de eventos es común, pero la presentación depende del framework:' +concepts.platforms.integration.details: 'Estas implementaciones difieren en cómo llevan la imagen de la GPU a la interfaz. La lectura como mapa de bits copia los píxeles a la memoria de la CPU antes de mostrarlos. La interoperabilidad mediante texturas compartidas evita esa copia, pero aún puede necesitar copias en la GPU y sincronización. Al elegir una integración, considere este mecanismo de presentación además del evento común {renderRequested}.' +concepts.platforms.integration.guidance: 'Añada mediante NuGet el paquete de integración de su framework de interfaz. Para Avalonia, utilice {avaloniaPackage}.' +concepts.platforms.integration.table.avalonia.integration: 'Avalonia' +concepts.platforms.integration.table.avalonia.presentation: 'Renderiza en una textura y descarga píxeles en un {writeableBitmap}. Consulte {zenithViewCs} y {surfaceCs}.' +concepts.platforms.integration.table.headings.integration: 'Integración' +concepts.platforms.integration.table.headings.presentation: 'Mecanismo de presentación' +concepts.platforms.integration.table.maui.integration: '.NET MAUI' +concepts.platforms.integration.table.maui.presentation: 'Utiliza superficies nativas en Android, iOS y Mac Catalyst, y composición de texturas compartidas en Windows. Consulte las {link}.' +concepts.platforms.integration.table.maui.presentation.link: 'implementaciones de plataforma' +concepts.platforms.integration.table.uno.integration: 'Ruta de Uno' +concepts.platforms.integration.table.uno.presentation: 'Descarga píxeles en un {writeableBitmap}. Consulte {zenithViewUnoCs}.' +concepts.platforms.integration.table.winForms.integration: 'WinForms' +concepts.platforms.integration.table.winForms.presentation: 'Crea una cadena de intercambio de Zenith.NET para el {hWND} del control. Consulte {zenithViewCs}.' +concepts.platforms.integration.table.winUI.integration: 'WinUI en Windows' +concepts.platforms.integration.table.winUI.presentation: 'Renderiza en una textura compartida de Direct3D 11 importada y copia el resultado a una cadena de intercambio de composición conectada a {swapChainPanel}. Consulte {zenithViewWinUICs}.' +concepts.platforms.integration.table.wpf.integration: 'WPF' +concepts.platforms.integration.table.wpf.presentation: 'Importa una textura compartida de Direct3D 11 y copia su contenido, mediante interoperabilidad con Direct3D, a una superficie que muestra {d3DImage}. Consulte {surfaceCs}.' +concepts.platforms.integration.title: 'Framework y presentación' +concepts.platforms.lifecycle.context: 'Al crear adjuntos compatibles, utilice {descWidth}, {descHeight}, {descFormat} y {descSampleCount} de la textura de salida que proporciona el evento de renderizado. Esa textura indica las dimensiones reales del destino; no deben deducirse del tamaño de diseño del control ni de la escala de pantalla.' +concepts.platforms.lifecycle.description: 'La cadena de intercambio utiliza el ancho y el alto en píxeles del búfer de fotogramas, que pueden diferir del tamaño lógico de la ventana cuando hay escalado de pantalla. Aplace el renderizado y el redimensionamiento de la cadena mientras alguna dimensión sea cero. Obtenga {swapChainDrawable} en cada fotograma: la cadena de intercambio posee esta textura y puede sustituirla tras presentar o redimensionar.' +concepts.platforms.lifecycle.details: 'Si cambia el tamaño del búfer de fotogramas, espere a que terminen los usos pendientes de las imágenes anteriores en la GPU antes de llamar a {swapChainResize}. Para sustituir el destino nativo de presentación, espere del mismo modo y pase la nueva descripción de superficie y sus identificadores a {swapChainRefresh}. Al cerrar, libere la cadena de intercambio antes de destruir su destino nativo.' +concepts.platforms.lifecycle.guidance: 'Si la aplicación tiene texturas de profundidad o fuera de pantalla que siguen el tamaño de la ventana, vuelva a crearlas cuando cambie ese tamaño y actualice las constantes que contengan sus identificadores. La canalización se puede reutilizar mientras sigan coincidiendo los formatos y el número de muestras de los adjuntos. El {link} muestra esta separación entre las texturas que se redimensionan y la canalización reutilizable.' +concepts.platforms.lifecycle.guidance.link: 'renderizador de cubo giratorio' +concepts.platforms.lifecycle.title: 'Dimensiones y vida útil de la cadena de intercambio' +concepts.platforms.ownership.description: 'La aplicación posee el contexto asignado y sus recursos de renderizado; el control posee sus recursos de presentación. Cuando cambia {graphicsContext} en la vista, el planificador vuelve a crear los recursos del control para el nuevo contexto. Vuelva a crear también las canalizaciones, los búferes y las texturas de la aplicación para ese contexto.' +concepts.platforms.ownership.details: 'Antes de sustituir recursos de renderizado, detenga la actividad de fotogramas de la vista y espere al trabajo de la GPU que los utiliza. Solo entonces libere los recursos o el contexto anteriores. Al retirar la vista, la aplicación sigue siendo responsable de liberar el contexto que tenía asignado.' +concepts.platforms.ownership.guidance: 'El componente compartido {frameSchedulerCs} ejecuta los manejadores de eventos de cada fotograma mediante el distribuidor de la interfaz de la vista. Limite esos manejadores a actualizar la escena y grabar comandos: un trabajo prolongado en la CPU también retrasa la respuesta de la interfaz.' +concepts.platforms.ownership.title: 'Responsabilidades de aplicación y control' +concepts.platforms.surface.description: 'El {link} utiliza Silk.NET para crear la ventana y procesar sus eventos. Zenith.NET recibe los identificadores nativos y las dimensiones mediante una descripción {surface}, con la que crea una {swapChain}. La aplicación sigue siendo responsable de la ventana del sistema operativo.' +concepts.platforms.surface.description.link: 'tutorial del triángulo' +concepts.platforms.surface.details: 'Los identificadores nativos deben corresponder al backend:' +concepts.platforms.surface.guidance: 'El programa anfitrión de {appCs} admite Windows, macOS y X11. En Linux, la ventana proporciona identificadores Xlib, por lo que necesita XWayland para ejecutarse en una sesión Wayland. Una aplicación nativa de Wayland proporciona los identificadores de pantalla y superficie mediante {surfaceWayland}.' +concepts.platforms.surface.table.android.backend: 'Vulkan en Android.' +concepts.platforms.surface.table.apple.backend: 'Metal en plataformas Apple.' +concepts.platforms.surface.table.headings.backend: 'Backend y plataforma' +concepts.platforms.surface.table.headings.factory: 'Fábrica de superficies' +concepts.platforms.surface.table.headings.handles: 'Identificadores suministrados por el host' +concepts.platforms.surface.table.wayland.backend: 'Vulkan con un host Wayland nativo.' +concepts.platforms.surface.table.wayland.handles: 'Pantalla y superficie Wayland' +concepts.platforms.surface.table.win32.backend: 'DirectX 12 o Vulkan en Windows.' +concepts.platforms.surface.table.xlib.backend: 'Vulkan en Linux con X11 o XWayland.' +concepts.platforms.surface.table.xlib.handles: 'Pantalla y ventana X11' +concepts.platforms.surface.title: 'Superficies de presentación nativas' +concepts.platforms.title: 'Integración de plataforma' +concepts.resources.allocation.context: 'Los recursos colocados en un montículo dependen de su almacenamiento durante toda su vida útil. Después de su último uso en la GPU, libere los recursos antes de liberar el montículo.' +concepts.resources.allocation.description: 'Use un {heap} cuando la aplicación necesite gestionar las asignaciones por sí misma. Un montículo proporciona almacenamiento donde se colocan los recursos en desplazamientos explícitos en bytes; la aplicación elige esos desplazamientos y lleva el registro de las regiones ocupadas.' +concepts.resources.allocation.details: 'Para cada recurso, llame a {contextGetSizeAndAlignment} con la descripción de búfer o textura que se utilizará al crearlo. Reserve el tamaño devuelto en un desplazamiento múltiplo de la alineación indicada, dentro del montículo y sin solapar otra asignación en uso. Las texturas pueden necesitar relleno específico del backend; por eso, el número de píxeles y los bytes por píxel no bastan para calcular el tamaño de la asignación.' +concepts.resources.allocation.guidance: 'La residencia de un búfer colocado en un montículo debe coincidir con la del montículo. Para almacenar texturas, use un montículo exclusivo de la GPU.' +concepts.resources.allocation.title: 'Asignación en montículos' +concepts.resources.bufferUsages.table.constant.role: 'Parámetros de sombreador leídos a través de un enlace de búfer de constantes.' +concepts.resources.bufferUsages.table.headings.role: 'Rol' +concepts.resources.bufferUsages.table.headings.usage: 'Uso' +concepts.resources.bufferUsages.table.index.role: 'Índices utilizados por el dibujo indexado.' +concepts.resources.bufferUsages.table.indirect.role: 'Argumentos leídos por comandos de dibujo o despacho indirectos.' +concepts.resources.bufferUsages.table.none.role: 'No se declaran indicadores de uso del búfer.' +concepts.resources.bufferUsages.table.storageReadOnly.role: 'Datos del búfer disponibles mediante un enlace de sombreador de solo lectura.' +concepts.resources.bufferUsages.table.storageReadWrite.role: 'Datos del búfer disponibles mediante un enlace de sombreador de lectura y escritura.' +concepts.resources.bufferUsages.table.transferDst.role: 'Almacenamiento de destino para una copia de GPU.' +concepts.resources.bufferUsages.table.transferSrc.role: 'Datos de origen para una copia de GPU.' +concepts.resources.bufferUsages.table.vertex.role: 'Atributos de vértice que leen los comandos de dibujo.' +concepts.resources.bufferUsages.title: 'Usos de búfer' +concepts.resources.description: 'La descripción de un recurso establece cómo puede utilizar la aplicación su almacenamiento. Por ejemplo, una textura que se usa como destino de renderizado, se muestrea en un sombreador y se copia a la CPU necesita los indicadores de uso de las tres operaciones. La ubicación de memoria determina el acceso de la CPU; la sincronización y la gestión de la vida útil determinan cuándo se pueden usar los datos o liberar el almacenamiento.' +concepts.resources.memory.context: 'En los búferes accesibles desde la CPU, {map} proporciona la dirección desde la que se leen o escriben los datos. Ni el mapeo ni {unmap} esperan al trabajo de la GPU: antes de leer un resultado, la aplicación debe esperar a que termine la escritura que lo produce; antes de modificar esos mismos bytes, debe esperar a que terminen los accesos pendientes de la GPU.' +concepts.resources.memory.description: 'El campo {residency} de {bufferDesc} establece el acceso de CPU previsto para la asignación:' +concepts.resources.memory.details: 'La residencia expresa los requisitos de acceso de la CPU, también en sistemas donde CPU y GPU comparten memoria física. El triángulo utiliza {cpuWriteOnly} para inicializar directamente su pequeño búfer de vértices. Para geometría estática de mayor tamaño, puede ser más adecuado cargar los datos en almacenamiento exclusivo de la GPU.' +concepts.resources.memory.guidance: 'Las texturas creadas directamente mediante el contexto utilizan almacenamiento de la GPU. Por eso, {textureDesc} no tiene un campo de residencia; la aplicación intercambia sus datos con la memoria de la CPU mediante cargas y descargas.' +concepts.resources.memory.table.cpuReadOnly.cPUAccess: 'Solo lectura' +concepts.resources.memory.table.cpuReadOnly.typicalRole: 'Datos producidos por la GPU para su lectura en la CPU' +concepts.resources.memory.table.cpuWriteOnly.cPUAccess: 'Solo escritura' +concepts.resources.memory.table.cpuWriteOnly.typicalRole: 'Datos proporcionados o actualizados por la CPU' +concepts.resources.memory.table.gpuOnly.cPUAccess: 'Ninguno' +concepts.resources.memory.table.gpuOnly.typicalRole: 'Geometría estática y datos de trabajo de la GPU' +concepts.resources.memory.table.headings.cPUAccess: 'Acceso previsto de la CPU' +concepts.resources.memory.table.headings.residency: 'Residencia' +concepts.resources.memory.table.headings.typicalRole: 'Rol típico' +concepts.resources.memory.title: 'Acceso de CPU y ubicación de memoria' +concepts.resources.textureUsages.description: 'Los indicadores de transferencia describen si el recurso actúa como origen o destino de una copia en la GPU. La posibilidad de acceder directamente desde la CPU se decide por separado al elegir la ubicación de memoria.' +concepts.resources.textureUsages.details: 'Los indicadores de uso declaran las funciones que puede desempeñar una textura. Para pasar de una a otra se deben cumplir los requisitos de {link}; además, el dispositivo elegido debe admitir esos usos para el formato de la textura.' +concepts.resources.textureUsages.details.link: 'disposición y sincronización' +concepts.resources.textureUsages.table.colorAttachment.role: 'Un adjunto de color en una pasada de renderizado.' +concepts.resources.textureUsages.table.depthStencilAttachment.role: 'Un adjunto de profundidad y plantilla en una pasada de renderizado.' +concepts.resources.textureUsages.table.headings.role: 'Rol' +concepts.resources.textureUsages.table.headings.usage: 'Uso' +concepts.resources.textureUsages.table.none.role: 'No se declaran indicadores de uso de la textura.' +concepts.resources.textureUsages.table.sampled.role: 'Datos de textura leídos mediante un enlace de textura muestreada.' +concepts.resources.textureUsages.table.storage.role: 'Datos de textura disponibles para lectura o escritura del sombreador mediante un enlace de textura de almacenamiento.' +concepts.resources.textureUsages.table.transferDst.role: 'Almacenamiento de imagen de destino para una copia de GPU.' +concepts.resources.textureUsages.table.transferSrc.role: 'Datos de imagen de origen para una copia de GPU.' +concepts.resources.textureUsages.title: 'Usos de textura' +concepts.resources.title: 'Administración de recursos' +concepts.resources.transfers.context: 'Una descarga copia primero los datos de la GPU a un almacenamiento interno de lectura. La biblioteca los copia al destino de CPU indicado cuando recupera el búfer de comandos completado. La llamada a {wait} sobre el valor de envío de la descarga completa ambos pasos. Mantenga el destino asignado y la memoria administrada anclada hasta que esa llamada retorne.' +concepts.resources.transfers.description: 'Las cargas copian datos de la CPU a un recurso de la GPU; las descargas copian datos del recurso a la memoria de la CPU. Los métodos de búferes y texturas completan la transferencia antes de retornar:' +concepts.resources.transfers.details: 'Antes de llamar a estos métodos, resuelva los accesos en conflicto de otras colas. La espera interna del método abarca su propia transferencia y no establece una dependencia con otra cola. Cuando se copia directamente a través de memoria mapeada, corresponde al llamador esperar a los accesos de la GPU que entren en conflicto.' +concepts.resources.transfers.guidance: 'Para enviar transferencias junto con otro trabajo de la GPU, grábelas con {commandBufferUpload} o {commandBufferDownload}. La memoria de origen de una carga y la de destino de una descarga tienen requisitos de vida útil distintos:' +concepts.resources.transfers.item: 'Durante una llamada de carga, la biblioteca copia los datos de origen a un almacenamiento temporal de transferencia. Después, la GPU lee los datos desde ese almacenamiento, por lo que el puntero de origen de la aplicación solo debe permanecer válido hasta que retorna la llamada.' +concepts.resources.transfers.notes: 'En las transferencias de texturas, el paso de fila es la distancia en bytes entre filas consecutivas de datos de la CPU; el paso de sección es la distancia entre secciones de profundidad consecutivas. Estos valores permiten copiar los datos entre su organización en la CPU y el almacenamiento de la textura en la GPU. {link} explica por qué terminar la copia en la GPU y entregar los datos al destino de una descarga son pasos distintos.' +concepts.resources.transfers.notes.link: 'Sincronización' +concepts.resources.transfers.table.bufferDownload.transfer: 'Para {cpuReadOnly}, copia directamente desde la memoria mapeada. En los demás casos, envía la descarga a la cola de transferencia y espera a que termine.' +concepts.resources.transfers.table.bufferUpload.transfer: 'Para {cpuWriteOnly}, copia directamente a la memoria mapeada. En los demás casos, envía la carga a la cola de transferencia y espera a que termine.' +concepts.resources.transfers.table.headings.method: 'Método' +concepts.resources.transfers.table.headings.transfer: 'Comportamiento de transferencia' +concepts.resources.transfers.table.textureTransfers.method: '{textureUpload} / {textureDownload}' +concepts.resources.transfers.table.textureTransfers.transfer: 'Envía la copia y las transiciones de textura a la cola gráfica y espera a que terminen. El subrecurso seleccionado queda en la disposición final solicitada.' +concepts.resources.transfers.title: 'Transferencias inmediatas y grabadas' +concepts.resources.usages.description: '{bufferUsages} y {textureUsages} son enumeraciones de indicadores que declaran los usos de un recurso. Se asignan a {bufferDescUsages} y {textureDescUsages}, respectivamente. Para varios usos, se combinan los miembros necesarios mediante {value}.' +concepts.resources.usages.title: 'Usos de recursos' +concepts.resources.views.description: 'Una {bufferView} describe una región de un búfer y cómo se interpretan sus datos. Una {textureView} selecciona un intervalo de subrecursos y un tipo y formato de textura compatibles. Ambas se refieren al almacenamiento existente, con los usos declarados al crearlo. Los intervalos de las vistas describen el acceso, pero no garantizan una comprobación de límites uniforme en los sombreadores de todos los backends.' +concepts.resources.views.details: 'El identificador del propio recurso proporciona su vista predeterminada. Cree otra vista para seleccionar una región o una interpretación compatible diferente. Mantenga vivos tanto la vista como el recurso que la respalda hasta que la GPU termine de utilizarlos; un identificador no conserva ninguno de los dos objetos. Si sustituye alguno, actualice las constantes que contengan el {link} anterior.' +concepts.resources.views.details.link: 'identificador de recurso' +concepts.resources.views.title: 'Vistas y recursos subyacentes' +concepts.shaders.binding.context: 'El ejemplo asigna {inputTextureSampledHandle} a {input} y {outputTextureStorageHandle} a {output}. En Slang, el parámetro de tipo de {descriptorHandle} determina cómo se accede al recurso:' +concepts.shaders.binding.description: '{setConstantBuffer} selecciona un búfer existente y el desplazamiento de byte desde el que la canalización actual lee sus constantes. Cargue los parámetros en ese almacenamiento antes de que los utilice el sombreador. Si un trabajo anterior de la GPU todavía lee esos bytes, espere a que termine antes de actualizarlos.' +concepts.shaders.binding.details: 'Con el búfer de comandos, la canalización de cálculo, el búfer de constantes cargado y el número de grupos de hilos preparados, grabe el despacho en este orden. Seleccione primero la canalización, ya que el enlace del búfer de constantes se aplica a ella:' +concepts.shaders.binding.guidance: 'Aquí, {commandBuffer} graba un despacho con {computePipeline} y los parámetros almacenados en {constantBuffer}. El búfer necesita el uso {bufferUsagesConstant}, y el desplazamiento 0 selecciona su comienzo. Si varios registros de constantes comparten un búfer, el desplazamiento inicial de cada registro debe cumplir también la alineación de enlace del backend, con independencia de la disposición de sus campos internos.' +concepts.shaders.binding.notes: '{resourceHandle} contiene dos campos de 32 bits cuya interpretación depende del backend. Sus valores solo son válidos en el contexto donde se creó el recurso.' +concepts.shaders.binding.reference: 'El recurso y su vista deben conservarse hasta el último acceso del sombreador. Sustituir una textura o vista exige actualizar las constantes con el identificador anterior. Las reglas de propiedad se detallan en {link}.' +concepts.shaders.binding.reference.link: 'Administración de recursos' +concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: 'Lectura de elementos estructurados del tipo {t} del sombreador' +concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: 'Lectura y escritura de elementos estructurados del tipo {t} del sombreador' +concepts.shaders.binding.table.headings.access: 'Acceso previsto' +concepts.shaders.binding.table.headings.cHandle: 'Identificador de C#' +concepts.shaders.binding.table.headings.slangFieldType: 'Tipo de campo Slang' +concepts.shaders.binding.table.samplerHandle.access: 'Estado de muestreo de texturas' +concepts.shaders.binding.table.textureSampledHandle.access: 'Lectura de texturas' +concepts.shaders.binding.table.textureStorageHandle.access: 'Lectura y escritura de texturas de almacenamiento' +concepts.shaders.binding.title: 'Constantes e identificadores de recursos' +concepts.shaders.compilation.description: '{zenithCompiler} compila un punto de entrada Slang en un {shaderDesc}. {graphicsApi} selecciona DXIL para DirectX 12, una biblioteca Metal para Metal o SPIR-V para Vulkan.' +concepts.shaders.compilation.details: 'Con un contexto gráfico ya creado y llamado {context}, compile el sombreador del triángulo a partir de la copia situada junto al ejecutable:' +concepts.shaders.compilation.guidance: 'El nombre del punto de entrada {vSMain} debe coincidir con la declaración del archivo de sombreadores. Compile los sombreadores y cree las canalizaciones durante la inicialización; después, reutilice las canalizaciones al renderizar. Una vez creadas, los objetos sombreador se pueden liberar, como muestra {link}.' +concepts.shaders.compilation.guidance.link: 'Primer triángulo' +concepts.shaders.compilation.title: 'Compilación de sombreadores' +concepts.shaders.description: 'Las declaraciones de C# y Slang deben coincidir en la ubicación de cada valor y en la forma de acceder a él desde el sombreador. Las disposiciones de entrada describen los atributos de los vértices; las declaraciones de búferes del sombreador describen parámetros y arrays; los identificadores señalan los recursos que utiliza el sombreador.' +concepts.shaders.dispatch.description: '{dispatch} indica cuántos grupos de hilos se ejecutan. El ejemplo de cálculo declara {numthreads}, por lo que cada grupo contiene 16 × 16 hilos. Para cubrir una imagen, divida el ancho y el alto entre 16 y redondee cada resultado hacia arriba: una imagen de 17 × 19 necesita 2 × 2 grupos. El sombreador comprueba las coordenadas de cada hilo y omite los que quedan fuera de la imagen.' +concepts.shaders.dispatch.details: 'El tamaño de grupo declarado está disponible en {shaderDescThreadGroupSize} y permite calcular los grupos que se pasan a {dispatch}. {computeShaderRendererCs} muestra el cálculo completo. Después del despacho, el acceso a la imagen resultante debe seguir los requisitos descritos en {link}.' +concepts.shaders.dispatch.details.link: 'Sincronización' +concepts.shaders.dispatch.title: 'Grupos de hilos' +concepts.shaders.layout.context: 'Las {link} muestran esta organización con las dimensiones de una imagen y dos identificadores de textura. Los desplazamientos explícitos indican dónde comienza cada campo. La declaración utiliza {systemRuntimeInteropServices} y {zenithNET}:' +concepts.shaders.layout.context.link: 'constantes de C# del ejemplo de cálculo' +concepts.shaders.layout.description: 'Para la entrada de vértices, {inputLayout} describe el formato, el desplazamiento y la semántica de cada atributo, junto con el paso entre vértices. El triángulo coloca una posición {float3} antes de un color {float4}: el color comienza en el desplazamiento de byte 12 y cada vértice ocupa 28 bytes. {inputLayoutAdd} calcula esta disposición compacta a partir de los formatos. Si la estructura de C# contiene relleno, indique desplazamientos y un paso que lo tengan en cuenta.' +concepts.shaders.layout.details: 'Los búferes de constantes contienen parámetros del sombreador, y los búferes estructurados contienen arrays de elementos tipados. Su disposición sigue las declaraciones de Slang, no {inputLayout}. Ajuste los desplazamientos, tamaños de elemento y relleno de C# a la disposición del sombreador compilado. Un tipo no administrado de C# se puede copiar byte a byte, pero su disposición en memoria no tiene por qué coincidir con la del sombreador; un {float3} empaquetado para un vértice puede necesitar otra alineación en un búfer del sombreador.' +concepts.shaders.layout.guidance: 'Los parámetros del sombreador pueden incluir identificadores de recursos además de valores ordinarios. Un identificador se refiere a almacenamiento ya existente, por lo que copiarlo a un búfer de constantes no copia el contenido del recurso.' +concepts.shaders.layout.notes: 'La declaración correspondiente en {computeShaderSlang} es:' +concepts.shaders.layout.reference: 'Las dos dimensiones ocupan los primeros ocho bytes, seguidas de dos identificadores de ocho bytes cada uno. El ejemplo de C# reserva 256 bytes para el registro completo. El tamaño de otros registros se debe calcular a partir de sus propios campos y requisitos de disposición y alineación.' +concepts.shaders.layout.title: 'Disposición de los datos' +concepts.shaders.matrices.description: 'El compilador almacena las matrices por filas contiguas. El {link} sitúa tres valores {matrix4x4} en los desplazamientos 0, 64 y 128. Su {detail} aplica {mulVectorMatrix} en el orden modelo, vista y proyección.' +concepts.shaders.matrices.description.detail: 'sombreador' +concepts.shaders.matrices.description.link: 'renderizador de cubo giratorio' +concepts.shaders.matrices.details: 'El orden de almacenamiento define la disposición de los elementos de la matriz en memoria; el de multiplicación define la transformación. Las convenciones de C# y Slang deben coincidir.' +concepts.shaders.matrices.title: 'Convenciones matriciales' +concepts.shaders.title: 'Datos de sombreadores y enlace' +concepts.synchronization.backends.description: 'DirectX 12 y Vulkan codifican las transiciones de textura como cambios de disposición y acceso. En Metal, la implementación de {transition} de Zenith.NET no realiza una operación equivalente. El backend de Metal agrupa los comandos en codificadores de renderizado y cálculo e inserta barreras de visibilidad cuando termina un codificador. Las operaciones dependientes dentro del mismo codificador, como los despachos de cálculo sucesivos, utilizan llamadas explícitas a {barrier}.' +concepts.synchronization.backends.details: 'En el {link}, iniciar la pasada gráfica termina el codificador de cálculo y hace visible su salida para el trabajo gráfico. Dos despachos de cálculo consecutivos permanecen en el mismo codificador, de modo que necesitan una barrera aunque se grabe una transición de textura entre ellos. Por eso, una secuencia de comandos portable debe contemplar tanto las dependencias de acceso como las disposiciones de textura.' +concepts.synchronization.backends.details.link: 'ejemplo de cálculo' +concepts.synchronization.backends.title: 'Comportamiento de los backends' +concepts.synchronization.barriers.context: 'Elija etapas que incluyan los accesos implicados y que admita la cola. {barrierStagesAll} incluye todas las etapas admitidas; seleccione un conjunto más reducido si la dependencia solo afecta a esas etapas.' +concepts.synchronization.barriers.description: 'Considere dos despachos de cálculo grabados en el mismo búfer de comandos: el primero escribe datos de simulación y el segundo los lee. Coloque una barrera entre ambos para que el segundo vea las escrituras completadas. En un búfer de almacenamiento, esto ordena los accesos sin una transición de disposición de textura:' +concepts.synchronization.barriers.details: 'El primer argumento identifica las etapas que producen los datos; el segundo, las que los consumen. Juntos describen el orden de ejecución y la visibilidad de memoria necesarios entre los dos despachos.' +concepts.synchronization.barriers.guidance: 'La {link} aplica este patrón entre los pasos de simulación. Cada barrera va después del despacho que produce los datos y antes del que los utiliza.' +concepts.synchronization.barriers.guidance.link: 'simulación FluidTank' +concepts.synchronization.barriers.title: 'Barreras de canalización' +concepts.synchronization.dependencies.description: 'Para cada recurso, identifique los accesos que afectan a los mismos datos. Si alguno escribe, conserve el orden necesario entre ellos. Dos lecturas no entran en conflicto, aunque siguen vigentes los requisitos de disposición de textura y presentación. Las actualizaciones de la CPU y la liberación de recursos también deben esperar a que la GPU termine de utilizar el almacenamiento afectado.' +concepts.synchronization.dependencies.details: 'El mecanismo se elige según dónde se ejecutan las operaciones:' +concepts.synchronization.dependencies.guidance: 'Una carga de trabajo puede necesitar varios mecanismos. Por ejemplo, una textura producida en otra cola necesita una dependencia entre envíos y la disposición adecuada para su siguiente uso. Ninguna de estas operaciones exige bloquear la CPU, salvo que esta necesite acceder a los datos o liberarlos.' +concepts.synchronization.dependencies.table.cpuAccess.mechanism: 'Llamar a {wait} en el valor de finalización correspondiente.' +concepts.synchronization.dependencies.table.cpuAccess.situation: 'El acceso de la CPU o la liberación de recursos depende de la finalización en la GPU' +concepts.synchronization.dependencies.table.crossQueue.mechanism: 'Pase el {timelineValue} del productor a {submit} del consumidor.' +concepts.synchronization.dependencies.table.crossQueue.situation: 'Una cola consume datos producidos en otra' +concepts.synchronization.dependencies.table.headings.mechanism: 'Mecanismo' +concepts.synchronization.dependencies.table.headings.situation: 'Situación' +concepts.synchronization.dependencies.table.layoutChange.mechanism: '{commandBufferTransition} con sus disposiciones anterior y siguiente.' +concepts.synchronization.dependencies.table.layoutChange.situation: 'Un subrecurso de textura cambia cómo se utiliza' +concepts.synchronization.dependencies.table.pipelineStages.mechanism: '{commandBufferBarrier} con las etapas productora y consumidora.' +concepts.synchronization.dependencies.table.pipelineStages.situation: 'Etapas de GPU dependientes en un flujo de comandos' +concepts.synchronization.dependencies.title: 'Dependencias de acceso' +concepts.synchronization.description: 'La sincronización establece el orden de acceso a los datos compartidos y permite que las operaciones posteriores vean los resultados que necesitan. En una dependencia de escritura a lectura, quien escribe es el productor y quien lee es el consumidor. Las barreras y las transiciones coordinan los accesos de la GPU; las líneas de tiempo conectan envíos y permiten que la CPU espere a que termine el trabajo de la GPU.' +concepts.synchronization.layouts.context: 'Use {undefined} como disposición anterior cuando se pueda descartar el contenido, por ejemplo, en una imagen nueva o en un adjunto que se vaya a borrar por completo. Para conservarlo para una carga, un muestreo o una acumulación, indique la disposición del acceso anterior.' +concepts.synchronization.layouts.description: 'Los indicadores de uso declaran las funciones permitidas de una textura. {textureLayout} describe cómo se accede a un subrecurso, identificado por un nivel de mip y una capa de array, en un punto concreto de la secuencia de comandos. Cuando cambia ese acceso, grabe una transición. En el ejemplo de cálculo, la textura de salida se escribe en disposición {storage} y después se prepara para muestrearla en una pasada gráfica:' +concepts.synchronization.layouts.details: '{outputTexture} se creó con {sampledStorage}, y el subrecurso seleccionado está en {storage}. {default} elige el nivel mip 0 y la capa 0. Los demás niveles y capas no cambian.' +concepts.synchronization.layouts.guidance: 'En {transition}, indique la disposición del uso anterior del subrecurso. La aplicación debe mantener actualizado este estado al grabar comandos y pasar texturas entre las etapas de renderizado.' +concepts.synchronization.layouts.title: 'Disposiciones de textura' +concepts.synchronization.readback.description: '{isCompleted} informa de la finalización en la GPU. Una descarga grabada tiene un paso adicional: copiar el resultado del almacenamiento interno de lectura a la memoria de destino de la aplicación.' +concepts.synchronization.readback.details: '{commandBufferDownload} graba la copia de la GPU a ese almacenamiento interno. Una vez terminado el envío, la biblioteca realiza la copia de CPU al recuperar el búfer de comandos completado. Llamar a {wait} sobre el valor de envío de la descarga espera a la GPU y procesa los búferes completados de esa cola, con lo que termina ambos pasos. Mantenga el destino asignado y la memoria administrada anclada hasta que retorne la llamada.' +concepts.synchronization.readback.guidance: 'Consultar {isCompleted} por sí solo no realiza la copia final de CPU. Esperar en otra cola tampoco recupera los búferes completados de la cola de descarga. {link} describe cuándo las cargas y descargas utilizan acceso directo o almacenamiento temporal de transferencia.' +concepts.synchronization.readback.guidance.link: 'Administración de recursos' +concepts.synchronization.readback.title: 'Finalización de la lectura en CPU' +concepts.synchronization.reuse.description: 'El triángulo espera a que termine cada fotograma antes de reutilizar sus datos. Para solapar fotogramas, reserve almacenamiento modificable para cada uno de los que estén en curso y registre cuándo vuelve a estar disponible. Antes de cambiar datos, espere al trabajo de la GPU que todavía acceda a esos bytes; antes de liberar un recurso, espere a todos sus usos pendientes.' +concepts.synchronization.reuse.details: 'El redimensionamiento y el cierre siguen la misma regla: impedir nuevos usos, esperar a que terminen los existentes y sustituir o liberar los recursos. Respete ese orden antes de llamar a {swapChainResize} o liberar recursos o el contexto. Como el triángulo ya espera en cada fotograma, puede redimensionar entre las llamadas a sus funciones de respuesta.' +concepts.synchronization.reuse.guidance: '{swapChainPresent} señala un punto de la cola gráfica y espera a él después de la presentación. Por tanto, el triángulo sigue esperando al presentar aunque se elimine la espera explícita del envío. El trabajo independiente de otras colas necesita su propio seguimiento de finalización.' +concepts.synchronization.reuse.title: 'Reutilización de recursos' +concepts.synchronization.timelines.context: 'Si la CPU necesita leer el resultado, sobrescribir los datos compartidos o liberar los recursos cuando termine el consumidor, espere a ese envío:' +concepts.synchronization.timelines.description: 'Una línea de tiempo identifica la finalización con valores crecientes. {submit} devuelve un {timelineValue} con la línea y el valor del envío. Los campos numéricos {value} de líneas distintas no se comparan directamente.' +concepts.synchronization.timelines.details: 'Sean {producer} y {consumer} búferes grabados en dos colas del mismo contexto, donde el segundo usa los datos del primero. Su envío establece esta dependencia:' +concepts.synchronization.timelines.guidance: 'La cola consumidora espera al valor de finalización recibido antes de ejecutar sus comandos. La CPU puede continuar sin llamar a {producedWait}. Conserve los recursos compartidos hasta que se complete {consumed} y grabe las transiciones de textura que necesite el acceso del consumidor.' +concepts.synchronization.timelines.notes: 'El valor que devuelve {queueTimelineSignal} también permite esperar con {wait} o establecer una dependencia para otra cola. {signal} coloca ese punto de finalización después del trabajo ya enviado; la GPU lo alcanza cuando termina dicho trabajo.' +concepts.synchronization.timelines.title: 'Líneas de tiempo y dependencias entre colas' +concepts.synchronization.title: 'Sincronización' +home.actions.reference: 'Explorar API' +home.actions.tutorial: 'Comenzar con un triángulo' +home.entries.description: 'Tutoriales, ejemplos y referencia de la API' +home.entries.label: 'Secciones de la documentación' +home.entries.reference.action: 'Explorar la API' +home.entries.reference.category: 'Referencia' +home.entries.reference.description: 'Consultar tipos, miembros y declaraciones de la API' +home.entries.reference.title: 'Referencia de la API' +home.entries.samples.action: 'Examinar ejemplos' +home.entries.samples.category: 'Ejemplos' +home.entries.samples.description: 'Ejemplos ejecutables de técnicas gráficas y de cálculo' +home.entries.samples.title: 'Ejemplos' +home.entries.title: 'Documentación' +home.entries.tutorial.action: 'Iniciar tutorial' +home.entries.tutorial.category: 'Tutorial' +home.entries.tutorial.description: 'De un proyecto vacío al primer triángulo en pantalla' +home.entries.tutorial.title: 'Primer triángulo' +home.introduction.accent: 'con .NET' +home.introduction.description: 'Zenith.NET ofrece una API común de gráficos y cálculo para DirectX, Metal y Vulkan' +home.introduction.title: 'Gráficos multiplataforma{lineBreak}{accent}' +home.meta.description: 'Desarrollo gráfico y de cálculo multiplataforma en .NET con una API común para DirectX, Metal y Vulkan' +home.scene.description: 'Geometría interactiva en rotación. Arrastre o utilice las flechas para cambiar la vista.' +home.scene.label: 'Visualización geométrica' +home.scene.surface: 'Superficie' +home.scene.wireframe: 'Estructura alámbrica' +home.title: 'API gráfica para .NET' +learning.concepts.description: 'Criterios para elegir usos de recursos, describir datos de sombreadores y coordinar la ejecución en la GPU' +learning.concepts.execution.description: 'Grabación, envío y tiempo de vida de los recursos' +learning.concepts.platforms.description: 'Presentación nativa y controles de renderizado' +learning.concepts.resources.description: 'Usos de recursos, ubicación de memoria y vistas' +learning.concepts.shaders.description: 'Convenciones de disposición y enlace entre C# y Slang' +learning.concepts.synchronization.description: 'Dependencias, visibilidad y finalización' +learning.concepts.title: 'Conceptos básicos' +learning.description: 'Empiece por el tutorial del triángulo para crear su primera aplicación. Después, consulte los conceptos de gestión de recursos, datos de sombreadores y sincronización, o elija un ejemplo de la técnica que quiera implementar.' +learning.entries.samples.action: 'Examinar ejemplos' +learning.entries.samples.description: 'Implementaciones C# y Slang de geometría, cálculo, consultas de rayos y sombreado de mallas' +learning.entries.tutorial.action: 'Abrir tutorial' +learning.entries.tutorial.description: 'Una aplicación de consola que abre una ventana y renderiza un triángulo' +learning.meta.description: 'Tutoriales y conceptos del modelo de programación de Zenith.NET' +learning.title: 'Aprender' +reference.description: 'Referencia de recursos, comandos e integración de plataformas' +reference.entries.commands.description: 'Comandos gráficos, de cálculo y de transferencia' +reference.entries.commands.label: 'Registrar comandos' +reference.entries.context.description: 'Creación de recursos GPU para el backend elegido' +reference.entries.context.label: 'Empezar aquí' +reference.meta.description: 'Espacios de nombres, tipos y miembros de Zenith.NET' +reference.navigation.core: 'Referencia de la API principal' +reference.title: 'Referencia de la API' +samples.computeShader.description: 'El ejemplo carga la imagen {assetsTexturesShokoPng}, la convierte a escala de grises en un despacho de cálculo y muestra la textura resultante. La conversión se ejecuta una vez; los fotogramas siguientes muestran el mismo resultado. El renderizador ilustra cómo enlazar texturas para muestreo y escritura, redondear hacia arriba el número de grupos de hilos para cubrir la imagen y comprobar sus límites en el sombreador.' +samples.computeShader.details: '{computeShaderRendererCs} · {computeShaderSlang}' +samples.computeShader.title: 'Sombreador de cálculo' +samples.cube.description: 'El cubo añade dibujo indexado, matrices de modelo, vista y proyección en un búfer de constantes y prueba de profundidad. Su textura de profundidad y plantilla {d32FloatS8UInt} se recrea al redimensionar.' +samples.cube.details: '{spinningCubeRendererCs} · {spinningCubeSlang}' +samples.cube.title: 'Cubo giratorio' +samples.description: 'Cada ejemplo reúne un renderizador C# y su sombreador Slang en torno a una técnica. La configuración completa y la secuencia de renderizado se explican en {link}.' +samples.description.link: 'Primer triángulo' +samples.execution.description: 'Ejecute el proyecto {link} y elija un ejemplo en el menú de la consola.' +samples.execution.description.link: 'ZenithTutorials' +samples.execution.title: 'Ejecución de ejemplos' +samples.host.description: '{appCs} inicializa contexto, ventana y cadena de intercambio. En cada fotograma obtiene un búfer, llama al renderizador, envía los comandos y presenta el resultado. {iRendererCs} define actualización, renderizado, redimensionamiento y liberación.' +samples.host.details: 'Los renderizadores de cálculo y trazado de rayos producen texturas fuera de pantalla. {texturePresenterCs} y {presentTextureSlang} las dibujan en la textura de salida actual; después, el programa anfitrión compartido envía los comandos y presenta el fotograma.' +samples.host.title: 'Host y presentación' +samples.indirectDrawing.description: 'El dibujo indirecto representa varias instancias de cubo mediante un búfer de argumentos de dibujo indexado y un búfer estructurado con datos por instancia. La CPU proporciona los argumentos y actualiza las transformaciones.' +samples.indirectDrawing.details: '{indirectDrawingRendererCs} · {indirectDrawingSlang}' +samples.indirectDrawing.title: 'Dibujo indirecto' +samples.meshShading.description: 'Un sombreador de tareas descarta las instancias de esferas no visibles y pasa los índices restantes al sombreador de mallas, que genera la geometría. El renderizador comprueba {contextCapabilitiesMeshShadingSupported} antes de crear la canalización.' +samples.meshShading.details: '{meshShadingRendererCs} · {meshShadingSlang}' +samples.meshShading.title: 'Sombreado de mallas' +samples.rayTracing.description: 'El ejemplo construye estructuras de aceleración de nivel inferior y superior para un suelo y esferas procedurales, y realiza consultas de rayos dentro de un sombreador de cálculo. Comprueba {contextCapabilitiesRayTracingSupported} antes de la inicialización.' +samples.rayTracing.details: '{rayTracingRendererCs} · {rayTracingSlang}' +samples.rayTracing.title: 'Trazado de rayos' +samples.title: 'Ejemplos' +samples.triangle.description: 'El triángulo asocia un búfer de vértices con su disposición de entrada y dibuja tres vértices mediante una canalización gráfica.' +samples.triangle.details: '{helloTriangleRendererCs} · {helloTriangleSlang} · {link}' +samples.triangle.details.link: 'Tutorial completo' +samples.triangle.title: 'Hola triángulo' +samples.workloads.description: 'El {link} del repositorio principal contiene aplicaciones de mayor escala que utilizan el código fuente de la biblioteca.' +samples.workloads.description.link: 'directorio Experiments' +samples.workloads.details: 'Las aplicaciones con ventana usan los mismos caminos de Windows, macOS y Linux/X11. {link} describe los controles Avalonia, WinForms, WPF, WinUI/Uno y MAUI, su ciclo de fotogramas y sus implementaciones.' +samples.workloads.details.link: 'Integración de plataforma' +samples.workloads.table.cornellBox.example: '{link}' +samples.workloads.table.cornellBox.example.link: 'CornellBox' +samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: 'Trazado de caminos, reducción de ruido, asignación de tonos, aumento de resolución y controles ImGui. Requiere soporte de trazado de rayos.' +samples.workloads.table.fluidTank.example: '{link}' +samples.workloads.table.fluidTank.example.link: 'FluidTank' +samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: 'Simulación de fluidos por cálculo, dependencias entre etapas de simulación y renderizado de superficies multipasada.' +samples.workloads.table.headings.example: 'Ejemplo' +samples.workloads.table.headings.whatItDemonstratesAndRequires: 'Técnicas y requisitos' +samples.workloads.table.inkCanvas.example: '{link}' +samples.workloads.table.inkCanvas.example.link: 'InkCanvas' +samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: 'Dibujo con Skia y control de entrada en una ventana nativa. Requiere el backend y la biblioteca nativa de Skia para la plataforma de destino.' +samples.workloads.table.platformDetection.example: '{link}' +samples.workloads.table.platformDetection.example.link: 'PlatformDetection' +samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: 'Intenta crear un contexto para cada backend e informa de las capacidades del dispositivo. Si un intento falla, lo muestra como no compatible; la causa puede estar en el dispositivo, el controlador o una dependencia de ejecución ausente.' +samples.workloads.title: 'Aplicaciones de mayor escala' +tutorial.context.description: 'Un {graphicsContext} conecta la aplicación con la GPU mediante un backend y proporciona los métodos para crear los recursos de renderizado.' +tutorial.context.details: 'Inserte la inicialización del contexto {emphasis}:' +tutorial.context.details.emphasis: 'después de las directivas using, antes de {iWindowWindow}' +tutorial.context.guidance: 'Cada rama selecciona el backend de la plataforma y solicita la validación. Los mensajes de {validationMessage} aparecen en la consola.' +tutorial.context.imports: 'Añada las siguientes directivas using al principio de {programCs}:' +tutorial.context.title: 'Contexto gráfico' +tutorial.description: 'Este tutorial parte de un proyecto de consola .NET vacío para crear una aplicación que abre una ventana y dibuja un triángulo de colores.' +tutorial.details: 'El tutorial tiene tres puntos de comprobación: una ventana vacía, un fondo de color uniforme y el triángulo de colores. Ejecute la aplicación en cada uno antes de continuar con el siguiente paso.' +tutorial.draw.context: 'Los argumentos para {draw} son:' +tutorial.draw.description: 'En {windowRender}, sustituya {addTheTriangleDrawCommandsHereLater} por estos comandos entre {beginRenderPass} y {endRenderPass}:' +tutorial.draw.details: '{setPipeline} selecciona sombreadores y estado. Debe preceder al enlace de vértices porque el backend lo interpreta según la disposición de entrada de la canalización.' +tutorial.draw.guidance: '{setVertexBufferVertexBuffer} enlaza los datos de vértices ya cargados desde el desplazamiento de byte 0 a la ranura de entrada 0, que corresponde a la única entrada de {inputLayouts}.' +tutorial.draw.notes: 'Estas llamadas graban los comandos de dibujo. La llamada existente a {submitWait} los envía y espera a que termine la GPU; después, {present} solicita que se muestre la imagen completada. Conserve el borrado al inicio de la pasada para que la zona exterior al triángulo tenga un color de fondo definido.' +tutorial.draw.table.firstInstance.meaning: 'Comenzar la numeración de instancias en cero.' +tutorial.draw.table.firstVertex.meaning: 'Comenzar con el primer vértice en el búfer.' +tutorial.draw.table.headings.argument: 'Argumento' +tutorial.draw.table.headings.description: 'Valor' +tutorial.draw.table.headings.meaning: 'Significado' +tutorial.draw.table.instanceCount.meaning: 'Dibujar una copia del triángulo.' +tutorial.draw.table.vertexCount.meaning: 'Leer tres vértices.' +tutorial.draw.title: 'Comandos de dibujo' +tutorial.execution.description: 'Compile y ejecute el proyecto {firstTriangle}.' +tutorial.execution.details: 'Debería aparecer un triángulo sobre un fondo oscuro, rojo arriba, verde abajo a la derecha y azul abajo a la izquierda. La interpolación de los colores de los vértices forma un degradado suave en el interior.' +tutorial.execution.guidance: 'Al redimensionar, cambian las dimensiones de la imagen en píxeles, pero las coordenadas de los vértices permanecen iguales. El área de visualización adapta esas coordenadas al nuevo ancho y alto, por lo que el triángulo se deforma si cambia la relación de aspecto de la ventana.' +tutorial.execution.title: 'Ejecución de la aplicación' +tutorial.frame.commands.context: 'Después de {endRenderPass}, la segunda transición prepara la textura de salida para su presentación. {submit} termina la grabación y envía el búfer de comandos; {wait} bloquea el hilo hasta que termina ese envío. A continuación, {present} solicita que se muestre la imagen renderizada.' +tutorial.frame.commands.description: 'Una pasada de renderizado agrupa las operaciones de dibujo que escriben en los mismos adjuntos. En esta pasada, la textura de salida de la cadena de intercambio recibe el color. {colorAttachmentClear} indica cómo inicializar ese adjunto con un color RGBA y conservar su contenido al terminar la pasada. {beginRenderPass} graba el inicio de la pasada con estos ajustes.' +tutorial.frame.commands.details: 'La colección contiene un adjunto de color. {null} indica que la pasada no tiene adjunto de profundidad y plantilla.' +tutorial.frame.commands.guidance: '{beginRenderPass} configura el área de visualización y el rectángulo de recorte para cubrir todo el adjunto. El área de visualización transforma las coordenadas de renderizado en posiciones de píxeles; el rectángulo de recorte limita dónde se puede escribir.' +tutorial.frame.commands.title: 'Borrado, envío y presentación' +tutorial.frame.description: 'Comience por rellenar la ventana con un color de fondo. Esta operación se llama borrado. Cuando el fondo aparece, la superficie, el envío y la presentación ya funcionan juntos y se pueden añadir los vértices y los sombreadores del triángulo.' +tutorial.frame.details: 'Silk.NET invoca el callback cuando corresponde producir un fotograma. El argumento de tiempo transcurrido no se usa y se denomina {value}. Registre el callback {emphasis}:' +tutorial.frame.details.emphasis: 'antes de {windowRun}' +tutorial.frame.target.description: '{graphicsQueueCommandBuffer} devuelve un búfer listo para grabar. La grabación describe trabajo GPU; la ejecución comienza después del envío.' +tutorial.frame.target.details: 'La disposición de una textura describe el acceso que necesita una operación. La primera llamada a {transition} prepara la textura de salida para usarla como adjunto de color. Aquí, {default} selecciona el nivel de mip 0 y la capa 0 del array, es decir, la imagen base de la textura. Como esta pasada borra toda la imagen, {undefined} permite descartar su contenido anterior.' +tutorial.frame.target.guidance: 'Obtenga la textura de salida en cada fotograma, ya que la presentación puede seleccionar una imagen distinta.' +tutorial.frame.target.title: 'Preparación de la salida' +tutorial.frame.title: 'Primer fotograma' +tutorial.geometry.data.description: 'Añada el array de vértices {emphasis}. Mantenga también las siguientes inicializaciones de recursos antes de este callback, en el orden indicado.' +tutorial.geometry.data.description.emphasis: 'antes de {windowRender}' +tutorial.geometry.data.details: 'Cada entrada construye un {vertex}; las dos expresiones {new} internas aportan posición {vector3} y color {vector4}. Las posiciones forman los vértices superior, inferior derecho e inferior izquierdo. El sombreador añade {w} como cuarta coordenada. Con w = 1, x e y son coordenadas normalizadas del dispositivo: -1 y +1 delimitan la imagen y 0 marca el centro, independientemente de los píxeles.' +tutorial.geometry.data.guidance: 'Cada color tiene componentes rojo, verde, azul y alfa, con alfa igual a 1. Los tres vértices tienen z = 0 y están en el mismo plano.' +tutorial.geometry.data.title: 'Posiciones y colores' +tutorial.geometry.description: 'Cada uno de los tres vértices tiene una posición y un color. La GPU determina la forma del triángulo a partir de las posiciones e interpola los colores por su superficie.' +tutorial.geometry.format.description: 'Añada la declaración del vértice {emphasis}:' +tutorial.geometry.format.description.emphasis: 'al final de {programCs}, después de las instrucciones de limpieza' +tutorial.geometry.format.details: '{file} limita el tipo a {programCs}, y {layoutKindSequential} mantiene los campos en su orden de declaración. {position} contiene tres valores de coma flotante de 32 bits y comienza en el desplazamiento de byte 0; {color} contiene cuatro y comienza en el desplazamiento de byte 12. Cada vértice ocupa, por tanto, 28 bytes. La disposición de entrada describirá esta organización para que la GPU lea los campos correctamente.' +tutorial.geometry.format.imports: 'Añada estas directivas using al principio de {programCs} para utilizar los tipos vectoriales y el atributo que define la disposición de la estructura:' +tutorial.geometry.format.title: 'Representación del vértice' +tutorial.geometry.title: 'Datos de vértices' +tutorial.geometry.upload.context: '{fixed} impide que el recolector de basura mueva el array mientras se usa su dirección. En este búfer escribible por la CPU, {upload} mapea la memoria, copia los bytes y deshace el mapeo antes de retornar. El array solo debe permanecer anclado durante la llamada. Cargue los vértices una vez durante la inicialización y conserve el búfer hasta que termine el renderizado.' +tutorial.geometry.upload.description: 'Guarde los vértices en un {buffer} para que la GPU pueda leerlos al dibujar. Añada la asignación y la carga de datos justo después del array:' +tutorial.geometry.upload.details: '{sizeofVertexVerticesLength} equivale a tres vértices de 28 bytes, 84 bytes en total. {bufferUsagesVertex} declara acceso de entrada, y {cpuWriteOnly} permite inicialización directa por CPU. El paso del descriptor registra el tamaño del elemento; la disposición posterior define cada atributo.' +tutorial.geometry.upload.guidance: 'La asignación no inicializa el contenido del búfer. {upload} copia el array al desplazamiento de destino 0 utilizando el puntero de origen y el número de bytes de la descripción de datos.' +tutorial.geometry.upload.imports: 'En {programCs}, añada {bufferAlias} a las directivas using para distinguir el tipo de búfer de Zenith.NET de {systemBuffer}.' +tutorial.geometry.upload.notes: 'Coloque {vertexBufferDispose} justo antes de {swapChainDispose} al final de {programCs}. {link} trata el almacenamiento exclusivo de GPU y las cargas para geometrías mayores.' +tutorial.geometry.upload.notes.link: 'Administración de recursos' +tutorial.geometry.upload.title: 'Asignación y carga del búfer' +tutorial.input.description: 'La GPU necesita saber dónde se guardan los atributos de cada vértice, como la posición y el color. La disposición de entrada indica su formato y desplazamiento, además del paso: la distancia en bytes hasta el siguiente vértice. Añada este código después de crear los sombreadores:' +tutorial.input.details: '{inputLayoutAdd} sitúa cada atributo a continuación del anterior y suma su tamaño al paso entre vértices. Calcula los desplazamientos a partir de los formatos indicados, sin inspeccionar la estructura de C#. Para estos dos campos, la disposición resultante es:' +tutorial.input.guidance: 'El valor predeterminado de {semanticIndex} es cero, que corresponde a {pOSITION0} y {cOLOR0} en el sombreador. La posición y el color se almacenan juntos en un búfer de vértices, por lo que la canalización utiliza una sola disposición de entrada en la ranura 0. Si cambia el orden de los campos o el relleno de la estructura de C#, ajuste también esta disposición.' +tutorial.input.table.headings.byteOffset: 'Desplazamiento de bytes' +tutorial.input.table.headings.cField: 'Campo de C#' +tutorial.input.table.headings.format: 'Formato' +tutorial.input.table.headings.shaderInput: 'Entrada del sombreador' +tutorial.input.table.nextVertex.cField: 'Siguiente vértice' +tutorial.input.table.nextVertex.format: 'Paso total: 28 bytes' +tutorial.input.table.nextVertex.shaderInput: 'Siguiente registro de entrada' +tutorial.input.table.vertexColor.format: '{float4} (16 bytes)' +tutorial.input.table.vertexPosition.format: '{float3} (12 bytes)' +tutorial.input.title: 'Disposición de entrada de vértices' +tutorial.lifecycle.description: 'Cada fotograma sigue esta secuencia:' +tutorial.lifecycle.details: 'Al cerrar la ventana, {run} retorna y la ejecución continúa en el código de limpieza. Como cada fotograma ya ha esperado a que terminen sus comandos, los recursos que utilizaban se pueden liberar. El bloque completo de limpieza después de {windowRun} es:' +tutorial.lifecycle.guidance: 'Libere la cadena de intercambio antes de destruir su ventana nativa y el contexto después de sus recursos. La cola recicla los búferes de comandos enviados, y la cadena de intercambio gestiona la textura de salida; ninguno necesita una llamada independiente a {dispose}.' +tutorial.lifecycle.title: 'Ciclo del fotograma y limpieza' +tutorial.pipeline.behavior: 'Tras la disposición de entrada, cree la canalización:' +tutorial.pipeline.context: '{cullNone} desactiva el descarte de caras, de modo que el triángulo se dibuja tanto si sus vértices aparecen en sentido horario como antihorario.' +tutorial.pipeline.description: 'Una {graphicsPipeline} reúne la disposición de los vértices, los dos sombreadores y los ajustes para ensamblar primitivas y escribir en los adjuntos.' +tutorial.pipeline.details: 'Los sombreadores procesan vértices y fragmentos. Los demás ajustes de la canalización controlan el ensamblado de primitivas, el descarte de caras, la prueba de profundidad y la mezcla de colores:' +tutorial.pipeline.guidance: 'El formato debe coincidir con el adjunto de la pasada, por lo que procede de {swapChainDescFormat}. {count1} especifica una muestra por píxel.' +tutorial.pipeline.item: '{triangleList} ensambla cada grupo de tres vértices consecutivos en un triángulo.' +tutorial.pipeline.notes: '{depthNone} desactiva pruebas y escrituras de profundidad, de acuerdo con la ausencia de ese adjunto.' +tutorial.pipeline.reference: '{opaque} desactiva la mezcla. El color del fragmento sustituye así el fondo dentro del triángulo.' +tutorial.pipeline.title: 'Canalización gráfica' +tutorial.pipeline.usage: 'Los objetos de sombreador pueden liberarse tras crear la canalización. Mantenga la canalización durante el renderizado y añada {pipelineDispose} antes de {vertexBufferDispose} en la limpieza.' +tutorial.presentation.title: 'Contexto gráfico y presentación' +tutorial.project.context: 'Active {emphasis} ({allowUnsafeBlocks}) en la configuración de compilación. Las llamadas nativas de ventana y la carga de vértices necesitan código no seguro.' +tutorial.project.context.emphasis: 'Permitir código no seguro' +tutorial.project.description: 'Cree un proyecto de consola C# llamado {firstTriangle} que tenga como destino .NET 10.' +tutorial.project.details: 'Añada los siguientes paquetes NuGet al proyecto:' +tutorial.project.guidance: '{zenithNET} aporta la API común y los tres paquetes de backend sus implementaciones. {zenithNETCompiler} compila los sombreadores Slang que se presentan a continuación. Silk.NET crea la ventana y procesa eventos.' +tutorial.project.title: 'Configuración del proyecto' +tutorial.requirements.context: 'El {link} y su {detail} proporcionan las implementaciones de referencia del tutorial.' +tutorial.requirements.context.detail: 'host compartido' +tutorial.requirements.context.link: 'ejemplo Hola triángulo' +tutorial.requirements.description: 'Necesita el {emphasis} y conocimientos básicos de C#. La aplicación tiene {net10} como framework de destino. La GPU y el controlador deben admitir el backend elegido para su plataforma:' +tutorial.requirements.description.emphasis: 'SDK de .NET 10' +tutorial.requirements.guidance: 'Zenith.NET renderiza en una superficie nativa proporcionada por la aplicación. Silk.NET.Windowing crea la ventana y procesa eventos. En macOS se utiliza una capa Metal, representada por {cAMetalLayerCs}, que el código auxiliar conecta a la ventana.' +tutorial.requirements.table.headings.graphicsBackend: 'Backend gráfico' +tutorial.requirements.table.headings.platform: 'Plataforma' +tutorial.requirements.table.linux.graphicsBackend: 'Vulkan 1.4' +tutorial.requirements.table.linux.platform: 'Linux (X11 o XWayland)' +tutorial.requirements.table.macOS.graphicsBackend: 'Metal 4' +tutorial.requirements.table.macOS.platform: 'macOS' +tutorial.requirements.table.windows.graphicsBackend: 'DirectX 12' +tutorial.requirements.table.windows.platform: 'Windows' +tutorial.requirements.title: 'Requisitos previos' +tutorial.resize.context: 'Compile y ejecute la aplicación de nuevo. El fondo debe seguir ocupando toda la ventana al cambiar su tamaño: cada nueva pasada ajusta el área de visualización y el rectángulo de recorte a las dimensiones del adjunto. Conserve la función de renderizado; el triángulo se dibujará dentro de esta misma pasada.' +tutorial.resize.description: 'La cadena de intercambio debe adaptarse a los cambios de tamaño del búfer de fotogramas. Registre una función para {framebufferResize} después de la función de renderizado y antes de {windowRun}:' +tutorial.resize.details: 'Responda a los {link}, que se miden en píxeles, en lugar de a los cambios de tamaño lógico de la ventana. Si al minimizar la ventana alguna dimensión pasa a ser cero, la función de redimensionamiento mantiene la cadena de intercambio tal como está. La función de renderizado también retorna mientras alguna dimensión sea cero, de modo que el renderizado se reanuda cuando el búfer de fotogramas vuelve a tener un tamaño válido.' +tutorial.resize.details.link: 'cambios de tamaño del búfer de fotogramas' +tutorial.resize.guidance: 'La función de renderizado espera a que termine cada fotograma enviado antes de llamar a {present}. Por ello, la función de redimensionamiento puede sustituir las imágenes de la cadena de intercambio sin interrumpir trabajo de un fotograma anterior. El artículo {link} explica la relación entre la finalización del trabajo y la vida útil de los recursos.' +tutorial.resize.guidance.link: 'Sincronización' +tutorial.resize.title: 'Redimensionamiento' +tutorial.shaders.compilation.context: '{appContextBaseDirectory} permite cargar la copia del sombreador situada en el directorio de salida de la aplicación. Así, el archivo se busca en el mismo lugar aunque la aplicación se inicie desde otro directorio de trabajo.' +tutorial.shaders.compilation.description: 'Para {triangleSlang}, establezca {emphasis} en {detail}. La compilación copiará el archivo junto al ejecutable.' +tutorial.shaders.compilation.description.detail: 'Copiar si es posterior' +tutorial.shaders.compilation.description.emphasis: 'Copiar en el directorio de salida' +tutorial.shaders.compilation.details: 'En {programCs}, añada la inicialización de sombreadores después de cargar los vértices y antes del callback:' +tutorial.shaders.compilation.guidance: '{zenithCompiler} compila el código fuente para {contextGraphicsApi}, y {createShader} crea un objeto sombreador a partir de la descripción compilada. Los nombres de punto de entrada {vSMain} y {fSMain} seleccionan las dos funciones definidas en el archivo Slang.' +tutorial.shaders.compilation.title: 'Compilación de sombreadores' +tutorial.shaders.context: '{fSInput} conecta las dos etapas del sombreador. El sombreador de vértices escribe en {sVPOSITION} una posición en el espacio de recorte, que la GPU utiliza para determinar qué parte del triángulo es visible. El campo {cOLOR0} transporta el color del vértice, que se interpola sobre el triángulo antes de llegar al sombreador de fragmentos. Su tipo y su semántica deben coincidir en ambas etapas.' +tutorial.shaders.description: 'Los sombreadores son programas que se ejecutan en la GPU. El sombreador de vértices determina la posición de cada vértice, y el sombreador de fragmentos determina el color en cada posición cubierta de la imagen. Ambos se escribirán en un mismo archivo Slang, con un punto de entrada propio para cada etapa: la función por la que comienza su ejecución.' +tutorial.shaders.details: 'Cree {triangleSlang} con estas estructuras de entrada y salida:' +tutorial.shaders.fragment.description: 'Añada el punto de entrada de fragmentos al mismo archivo:' +tutorial.shaders.fragment.details: 'La rasterización determina qué zonas de la imagen cubre el triángulo y genera fragmentos en esas posiciones. Cada fragmento recibe un color interpolado a partir de los colores de los tres vértices. {fSMain} devuelve ese color, y {sVTARGET} dirige el resultado al primer adjunto de color.' +tutorial.shaders.fragment.title: 'Sombreado de fragmentos' +tutorial.shaders.guidance: '{vSInput} define las entradas del sombreador de vértices. {pOSITION0} y {cOLOR0} identifican atributos por semántica; los nombres C# no establecen esa correspondencia.' +tutorial.shaders.title: 'Etapas de sombreado' +tutorial.shaders.vertex.description: 'Añada el punto de entrada de vértices a {triangleSlang}:' +tutorial.shaders.vertex.details: 'La GPU invoca este punto para cada vértice, incorpora la coordenada homogénea {w} y transmite el color. La posición se divide después por w. Aquí vale 1, por lo que x, y y z no cambian y se interpretan como coordenadas normalizadas del dispositivo.' +tutorial.shaders.vertex.title: 'Sombreado de vértices' +tutorial.surface.description: 'Defina el destino de presentación nativo {emphasis}:' +tutorial.surface.description.emphasis: 'después de {windowCenter} y antes de {windowRun}' +tutorial.surface.details: 'El búfer de fotogramas es la imagen de la ventana en píxeles. {surface} describe el destino nativo de presentación y sus dimensiones; {framebufferSize} proporciona el tamaño en píxeles. Con el escalado de pantalla, este puede diferir del tamaño lógico de la ventana.' +tutorial.surface.guidance: 'La superficie proporciona los identificadores nativos del backend: una ventana Win32 en Windows, una pantalla y una ventana X11 en Linux o la capa Metal conectada en macOS.' +tutorial.surface.title: 'Superficie nativa' +tutorial.swapChain.context: 'La cadena depende del contexto y de la ventana. Sustituya {windowDispose} al final de {programCs} por este orden de liberación:' +tutorial.swapChain.description: 'Cree la cadena inmediatamente después de describir la superficie:' +tutorial.swapChain.details: 'La {swapChain} gestiona las imágenes presentadas. {drawable} suministra la actual como {texture}, el recurso de imagen de la API. Tras renderizar, {present} solicita mostrarla y avanza a la siguiente.' +tutorial.swapChain.guidance: '{b8G8R8A8UNorm} almacena cuatro canales de 8 bits en orden azul, verde, rojo y alfa. {uNorm} hace corresponder 0–255 con 0–1. La salida sigue siendo RGBA lógico; el formato define su almacenamiento. La canalización usa {swapChainDescFormat} para coincidir con el adjunto.' +tutorial.swapChain.title: 'Cadena de intercambio' +tutorial.title: 'Primer triángulo' +tutorial.troubleshooting.description: 'Utilice los diagnósticos de consola y los tres puntos de control para localizar el fallo:' +tutorial.troubleshooting.details: 'El {link} y el {detail} permiten contrastar datos, disposición y dibujo. El ejemplo separa ventana y envío en un host común; el tutorial mantiene el flujo en {programCs}. {context} introduce dibujo indexado, transformaciones y profundidad.' +tutorial.troubleshooting.details.context: 'Cubo giratorio' +tutorial.troubleshooting.details.detail: 'sombreador Slang' +tutorial.troubleshooting.details.link: 'renderizador de ejemplo' +tutorial.troubleshooting.table.backend.check: 'Compruebe que el backend seleccionado sea compatible con el dispositivo y el controlador de gráficos instalado.' +tutorial.troubleshooting.table.backend.symptom: 'Falla la creación del backend' +tutorial.troubleshooting.table.drawing.check: 'Compruebe el tamaño de la carga, la disposición de entrada, la selección de la canalización y la ubicación de los comandos de dibujo dentro de la pasada de renderizado.' +tutorial.troubleshooting.table.drawing.symptom: 'Aparece el fondo pero no el triángulo' +tutorial.troubleshooting.table.headings.check: 'Comprobación' +tutorial.troubleshooting.table.headings.symptom: 'Síntoma' +tutorial.troubleshooting.table.input.check: 'Compruebe el paso de 28 bytes y los desplazamientos de posición/color de 0 y 12.' +tutorial.troubleshooting.table.input.symptom: 'Las posiciones o colores de los vértices están dañados' +tutorial.troubleshooting.table.shaders.check: 'Compruebe el archivo {triangleSlang} copiado, la ortografía del punto de entrada y el diagnóstico notificado por el compilador.' +tutorial.troubleshooting.table.shaders.symptom: 'El fondo se muestra, pero falla la carga de los sombreadores' +tutorial.troubleshooting.table.window.check: 'Confirme que el proyecto .NET se compila y que el paso de solo ventana se ejecuta en una sesión de escritorio. En Linux, compruebe que X11 o XWayland estén disponibles.' +tutorial.troubleshooting.table.window.symptom: 'No se abre ninguna ventana' +tutorial.troubleshooting.title: 'Diagnóstico de problemas' +tutorial.window.description: 'Descargue {cocoaHelperCs} en el directorio del proyecto. Esta clase auxiliar conecta la capa Metal a la ventana de macOS.' +tutorial.window.details: 'Sustituya el contenido generado de {programCs} por el código siguiente. Usa instrucciones de nivel superior que se ejecutan en orden, sin un método {main} explícito. Las siguientes secciones indicarán dónde añadir cada fragmento:' +tutorial.window.guidance: '{graphicsAPINone} deja la creación del contexto gráfico a Zenith.NET. {initialize} crea la ventana nativa y permite acceder a los identificadores del sistema de ventanas. {center} la coloca en el centro de la pantalla. {run} procesa los eventos hasta que se cierra; después se ejecuta {dispose} para liberarla.' +tutorial.window.notes: 'Compile y ejecute la aplicación. Compruebe que puede abrir, mover, redimensionar y cerrar la ventana. Su contenido aún no está definido porque no se han enviado comandos de renderizado. Cierre la ventana antes de continuar.' +tutorial.window.title: 'Creación de la ventana' +ui.action.copy: 'Copiar' +ui.action.navigate: 'Navegar' +ui.action.open: 'Abrir' +ui.action.source: 'Ver código fuente' +ui.api.browse: 'Examinar espacios de nombres y tipos.' +ui.api.clearTypeSearch: 'Borrar búsqueda de tipos' +ui.api.findType: 'Buscar un tipo' +ui.api.loadError: 'No se pudieron cargar los tipos. Recargue esta página para intentarlo de nuevo.' +ui.api.loadingNamespaces: 'Cargando espacios de nombres…' +ui.api.loadingTypes: 'Cargando tipos…' +ui.api.matchingTypes: 'Tipos coincidentes' +ui.api.namespace: 'Espacio de nombres' +ui.api.namespaces: 'Espacios de nombres' +ui.api.noNamespaceTypes: 'No hay tipos en este espacio de nombres.' +ui.api.noTypes: 'No hay tipos coincidentes.' +ui.api.types: 'Tipos' +ui.content.reference: 'Referencia' +ui.content.source: 'Código fuente' +ui.content.tutorial: 'Tutorial' +ui.contents.close: 'Cerrar el índice' +ui.contents.open: 'Abrir el índice' +ui.contents.title: 'Índice' +ui.footer.caption: 'API gráfica para .NET' +ui.footer.label: 'Pie de página' +ui.language.label: 'Idioma' +ui.language.unavailable: 'No traducido' +ui.members.clear: 'Borrar búsqueda de miembros' +ui.members.close: 'Cerrar buscador de miembros' +ui.members.empty: 'No hay miembros coincidentes.' +ui.members.open: 'Ir al miembro' +ui.members.placeholder: 'Nombre o firma…' +ui.members.search: 'Buscar miembros' +ui.members.title: 'Buscar un miembro' +ui.members.undeclared: 'Este tipo no tiene miembros declarados.' +ui.navigation.api: 'API' +ui.navigation.concepts: 'Conceptos' +ui.navigation.home: 'Inicio' +ui.navigation.label: 'Navegación principal' ui.navigation.skip: Ir al contenido -ui.navigation.toggle: "Alternar navegación" -ui.outline.title: "En esta página" -ui.reference.assembly: "Ensamblado" -ui.reference.classes: "Clases" -ui.reference.constructors: "Constructores" -ui.reference.declaration: "Declaración de tipo C#" -ui.reference.delegates: "Delegados" -ui.reference.derived: "Tipos derivados" -ui.reference.enums: "Enumeraciones" -ui.reference.events: "Eventos" -ui.reference.examples: "Ejemplos" -ui.reference.exceptions: "Excepciones" -ui.reference.extensionMethods: "Métodos de extensión" -ui.reference.fields: "Campos" -ui.reference.implementations: "Implementaciones explícitas de interfaz" -ui.reference.implements: "Implementa" -ui.reference.inheritance: "Herencia" -ui.reference.inheritedMembers: "Miembros heredados" -ui.reference.interfaces: "Interfaces" -ui.reference.metadata: "Metadatos de tipo" -ui.reference.methods: "Métodos" -ui.reference.namespace: "Espacio de nombres" -ui.reference.open: "Abrir referencia de {name}" -ui.reference.operators: "Operadores" -ui.reference.parameters: "Parámetros" -ui.reference.properties: "Propiedades" -ui.reference.related: "Vea también" -ui.reference.relationships: "Herencia y metadatos" -ui.reference.remarks: "Comentarios" -ui.reference.returns: "Devuelve" -ui.reference.structs: "Estructuras" -ui.reference.typeParameters: "Parámetros de tipo" -ui.reference.value: "Valor" -ui.reference.values: "Valores" -ui.search.close: "Cerrar búsqueda" -ui.search.empty: "No hay resultados para «{query}»." -ui.search.hint: "Busque en tutoriales, conceptos, ejemplos y en la referencia de la API." -ui.search.loading: "Cargando búsqueda…" -ui.search.more: "Mostrar más resultados" -ui.search.pending: "Buscando…" -ui.search.placeholder: "¿Qué está buscando?" -ui.search.resultCount: "Resultados: {count}" -ui.search.title: "Buscar en la documentación" -ui.search.unavailable: "La búsqueda no está disponible. Aún puede abrir las páginas siguientes." +ui.navigation.toggle: 'Alternar navegación' +ui.outline.title: 'En esta página' +ui.reference.assembly: 'Ensamblado' +ui.reference.classes: 'Clases' +ui.reference.constructors: 'Constructores' +ui.reference.declaration: 'Declaración de tipo C#' +ui.reference.delegates: 'Delegados' +ui.reference.derived: 'Tipos derivados' +ui.reference.enums: 'Enumeraciones' +ui.reference.events: 'Eventos' +ui.reference.examples: 'Ejemplos' +ui.reference.exceptions: 'Excepciones' +ui.reference.extensionMethods: 'Métodos de extensión' +ui.reference.fields: 'Campos' +ui.reference.implementations: 'Implementaciones explícitas de interfaz' +ui.reference.implements: 'Implementa' +ui.reference.inheritance: 'Herencia' +ui.reference.inheritedMembers: 'Miembros heredados' +ui.reference.interfaces: 'Interfaces' +ui.reference.metadata: 'Metadatos de tipo' +ui.reference.methods: 'Métodos' +ui.reference.namespace: 'Espacio de nombres' +ui.reference.open: 'Abrir referencia de {name}' +ui.reference.operators: 'Operadores' +ui.reference.parameters: 'Parámetros' +ui.reference.properties: 'Propiedades' +ui.reference.related: 'Vea también' +ui.reference.relationships: 'Herencia y metadatos' +ui.reference.remarks: 'Comentarios' +ui.reference.returns: 'Devuelve' +ui.reference.structs: 'Estructuras' +ui.reference.typeParameters: 'Parámetros de tipo' +ui.reference.value: 'Valor' +ui.reference.values: 'Valores' +ui.search.close: 'Cerrar búsqueda' +ui.search.empty: 'No hay resultados para «{query}».' +ui.search.hint: 'Busque en tutoriales, conceptos, ejemplos y en la referencia de la API.' +ui.search.loading: 'Cargando búsqueda…' +ui.search.more: 'Mostrar más resultados' +ui.search.pending: 'Buscando…' +ui.search.placeholder: '¿Qué está buscando?' +ui.search.resultCount: 'Resultados: {count}' +ui.search.title: 'Buscar en la documentación' +ui.search.unavailable: 'La búsqueda no está disponible. Aún puede abrir las páginas siguientes.' diff --git a/documents/locales/es-ES/translation.md b/documents/locales/es-ES/translation.md index e766d010..ef2e35c6 100644 --- a/documents/locales/es-ES/translation.md +++ b/documents/locales/es-ES/translation.md @@ -2,7 +2,7 @@ ## Recursos y estructura -El [diccionario de recursos en inglés](../en-US/strings.yml) es la única fuente del texto. Las normas del proyecto están en la [guía de mantenimiento de la documentación](../../authoring.md). Para iniciar una traducción, copie el archivo inglés completo como `strings.yml` en este directorio. Conserve la primera línea `### YamlMime:Resources` y la codificación UTF-8. En futuras revisiones, incorpore los cambios del original sin sobrescribir las traducciones existentes. Este archivo `translation.md` se conserva permanentemente y no se publica en el sitio. +El [diccionario de recursos en inglés](../en-US/strings.yml) es la única fuente del texto. Las normas del proyecto están en la [guía de mantenimiento de la documentación](../../maintenance.md). Para iniciar una traducción, copie el archivo inglés completo como `strings.yml` en este directorio. Conserve la primera línea `### YamlMime:Resources` y la codificación UTF-8. En futuras revisiones, incorpore los cambios del original sin sobrescribir las traducciones existentes. Este archivo `translation.md` se conserva permanentemente y no se publica en el sitio. La navegación, el orden de los capítulos, las anclas, los enlaces, el formato, el código y las imágenes se mantienen fuera de `locales/` y se comparten entre idiomas. No cree aquí artículos, TOC, plantillas, scripts ni configuraciones. @@ -65,21 +65,21 @@ Antes de entregar, compruebe las claves y los marcadores. Revise la página de i ## Terminología -| Término inglés | Forma acordada | -| --- | --- | -| API / GPU / RHI | Conservar las siglas y explicarlas según el original | -| barrier | barrera | -| buffer | búfer; conservar `Buffer` | -| command buffer | búfer de comandos | -| command queue | cola de comandos | -| drawable | textura de salida del fotograma actual; conservar `Drawable`, sin asumir que sea una imagen de la cadena de intercambio | -| graphics context | contexto gráfico | -| pipeline | canalización | -| readback | lectura de datos desde la GPU | -| render pass | pasada de renderizado | -| resource | recurso | -| shader | sombreador | -| swap chain | cadena de intercambio | -| texture | textura | -| timeline | línea de tiempo | -| upload | carga de datos a la GPU | +| Término inglés | Forma acordada | +| ---------------- | ----------------------------------------------------------------------------------------------------------------------- | +| API / GPU / RHI | Conservar las siglas y explicarlas según el original | +| barrier | barrera | +| buffer | búfer; conservar `Buffer` | +| command buffer | búfer de comandos | +| command queue | cola de comandos | +| drawable | textura de salida del fotograma actual; conservar `Drawable`, sin asumir que sea una imagen de la cadena de intercambio | +| graphics context | contexto gráfico | +| pipeline | canalización | +| readback | lectura de datos desde la GPU | +| render pass | pasada de renderizado | +| resource | recurso | +| shader | sombreador | +| swap chain | cadena de intercambio | +| texture | textura | +| timeline | línea de tiempo | +| upload | carga de datos a la GPU | diff --git a/documents/locales/fr-FR/strings.yml b/documents/locales/fr-FR/strings.yml index 8f27a0e6..8e1a4d1e 100644 --- a/documents/locales/fr-FR/strings.yml +++ b/documents/locales/fr-FR/strings.yml @@ -1,91 +1,91 @@ ### YamlMime:Resources -concepts.execution.context.description: "Un {graphicsContext} relie l’application à un périphérique GPU par un backend donné et fournit ses files graphiques, de calcul et de transfert. Les ressources utilisées ensemble doivent appartenir au même contexte : tampons, textures, shaders, pipelines et handles ne peuvent pas être liés d’un contexte à un autre." -concepts.execution.context.details: "{capabilities} indique le nom du périphérique et les fonctions prises en charge. Vérifiez {rayTracingSupported} et {meshShadingSupported} avant de créer les ressources nécessaires à ces fonctions. Les exemples de {link} et de {detail} effectuent ces vérifications à l’initialisation." +concepts.execution.context.description: 'Un {graphicsContext} relie l’application à un périphérique GPU par un backend donné et fournit ses files graphiques, de calcul et de transfert. Les ressources utilisées ensemble doivent appartenir au même contexte : tampons, textures, shaders, pipelines et handles ne peuvent pas être liés d’un contexte à un autre.' +concepts.execution.context.details: '{capabilities} indique le nom du périphérique et les fonctions prises en charge. Vérifiez {rayTracingSupported} et {meshShadingSupported} avant de créer les ressources nécessaires à ces fonctions. Les exemples de {link} et de {detail} effectuent ces vérifications à l’initialisation.' concepts.execution.context.details.detail: mesh shading concepts.execution.context.details.link: lancer de rayons -concepts.execution.context.title: "Contexte graphique" -concepts.execution.description: "Le travail du GPU se prépare sur le CPU : l’application crée des ressources, enregistre les commandes qui les utilisent, puis les soumet à une file. Le CPU peut ensuite poursuivre son exécution pendant que le GPU traite ces commandes. Les ressources nécessaires doivent rester disponibles jusqu’à la fin de ce traitement." -concepts.execution.ownership.description: "La propriété détermine qui libère un objet ; l’achèvement sur le GPU détermine quand il peut être libéré. Un appel à {dispose} libère les ressources natives même si des références C# à l’objet existent encore. Soumettre des commandes ne transfère pas la propriété de leurs ressources à la file." -concepts.execution.ownership.details: "À l’arrêt, cesser les nouvelles soumissions et attendre la dernière utilisation des ressources sur chaque file concernée. Libérer ensuite les ressources de l’application, puis le contexte. Celui-ci libère ses files et ses objets auxiliaires internes ; cette dernière étape doit donc intervenir après la fin du travail de l’application." -concepts.execution.ownership.guidance: "Pendant le rendu, suivre l’achèvement des accès aux données à modifier ou aux ressources à remplacer. Attendre la fin de ces accès avant de modifier ou de libérer la mémoire concernée. L’article {link} explique comment les vues et les ressources sous-jacentes s’inscrivent dans ce modèle de durée de vie." +concepts.execution.context.title: 'Contexte graphique' +concepts.execution.description: 'Le travail du GPU se prépare sur le CPU : l’application crée des ressources, enregistre les commandes qui les utilisent, puis les soumet à une file. Le CPU peut ensuite poursuivre son exécution pendant que le GPU traite ces commandes. Les ressources nécessaires doivent rester disponibles jusqu’à la fin de ce traitement.' +concepts.execution.ownership.description: 'La propriété détermine qui libère un objet ; l’achèvement sur le GPU détermine quand il peut être libéré. Un appel à {dispose} libère les ressources natives même si des références C# à l’objet existent encore. Soumettre des commandes ne transfère pas la propriété de leurs ressources à la file.' +concepts.execution.ownership.details: 'À l’arrêt, cesser les nouvelles soumissions et attendre la dernière utilisation des ressources sur chaque file concernée. Libérer ensuite les ressources de l’application, puis le contexte. Celui-ci libère ses files et ses objets auxiliaires internes ; cette dernière étape doit donc intervenir après la fin du travail de l’application.' +concepts.execution.ownership.guidance: 'Pendant le rendu, suivre l’achèvement des accès aux données à modifier ou aux ressources à remplacer. Attendre la fin de ces accès avant de modifier ou de libérer la mémoire concernée. L’article {link} explique comment les vues et les ressources sous-jacentes s’inscrivent dans ce modèle de durée de vie.' concepts.execution.ownership.guidance.link: Gestion des ressources concepts.execution.ownership.table.applicationResources.object: Ressources créées par l’application concepts.execution.ownership.table.applicationResources.ownership: L’application les libère après leur dernière utilisation par le GPU. concepts.execution.ownership.table.commandBuffers.object: Tampons de commandes empruntés concepts.execution.ownership.table.commandBuffers.ownership: La file les gère et les recycle. concepts.execution.ownership.table.headings.object: Objet -concepts.execution.ownership.table.headings.ownership: "Responsabilité de libération" +concepts.execution.ownership.table.headings.ownership: 'Responsabilité de libération' concepts.execution.ownership.table.queues.object: Files de contexte et leurs lignes de temps concepts.execution.ownership.table.queues.ownership: Le contexte et les files les gèrent. concepts.execution.ownership.table.swapChainDrawable.ownership: La chaîne d’échange la gère. -concepts.execution.ownership.title: "Propriété et durée de vie" -concepts.execution.pipelines.description: "Un pipeline graphique définit les shaders, la disposition des attributs de sommets, l’assemblage des primitives, les formats d’attachement et l’état de rendu. Il doit être sélectionné avant les liaisons de sommets, d’indices ou de constantes. Ses formats et son nombre d’échantillons doivent correspondre à la passe de rendu." -concepts.execution.pipelines.details: "Un pipeline de calcul sélectionne le point d’entrée du shader pour un lancement de calcul. Lier le pipeline et ses constantes avant ce lancement, en dehors d’une passe de rendu graphique." -concepts.execution.pipelines.guidance: "Le {link} présente la séquence graphique. L’{detail} ajoute un lancement de calcul avant la passe graphique qui en affiche le résultat." +concepts.execution.ownership.title: 'Propriété et durée de vie' +concepts.execution.pipelines.description: 'Un pipeline graphique définit les shaders, la disposition des attributs de sommets, l’assemblage des primitives, les formats d’attachement et l’état de rendu. Il doit être sélectionné avant les liaisons de sommets, d’indices ou de constantes. Ses formats et son nombre d’échantillons doivent correspondre à la passe de rendu.' +concepts.execution.pipelines.details: 'Un pipeline de calcul sélectionne le point d’entrée du shader pour un lancement de calcul. Lier le pipeline et ses constantes avant ce lancement, en dehors d’une passe de rendu graphique.' +concepts.execution.pipelines.guidance: 'Le {link} présente la séquence graphique. L’{detail} ajoute un lancement de calcul avant la passe graphique qui en affiche le résultat.' concepts.execution.pipelines.guidance.detail: exemple de calcul concepts.execution.pipelines.guidance.link: rappel de rendu du triangle -concepts.execution.pipelines.title: "État du pipeline" -concepts.execution.queues.description: "{graphicsQueue} constitue le point de départ habituel lorsqu’une image combine dessin, calcul et copies. Regrouper les opérations dépendantes dans une même file simplifie leur ordonnancement." -concepts.execution.queues.details: "Des files distinctes permettent de soumettre séparément des tâches indépendantes, mais ne correspondent pas nécessairement à des moteurs matériels indépendants. Elles sont utiles lorsque les tâches peuvent bénéficier d’une exécution partiellement simultanée. Lorsqu’une file utilise les données produites par une autre, leurs soumissions doivent être reliées par une dépendance explicite." -concepts.execution.queues.guidance: "Dans une même file, des opérations dépendantes peuvent aussi nécessiter des barrières ou des transitions de texture pour que les accès ultérieurs voient les écritures précédentes. Ces dépendances mémoire sont distinctes de l’ordre de soumission. L’article {link} explique comment les exprimer." +concepts.execution.pipelines.title: 'État du pipeline' +concepts.execution.queues.description: '{graphicsQueue} constitue le point de départ habituel lorsqu’une image combine dessin, calcul et copies. Regrouper les opérations dépendantes dans une même file simplifie leur ordonnancement.' +concepts.execution.queues.details: 'Des files distinctes permettent de soumettre séparément des tâches indépendantes, mais ne correspondent pas nécessairement à des moteurs matériels indépendants. Elles sont utiles lorsque les tâches peuvent bénéficier d’une exécution partiellement simultanée. Lorsqu’une file utilise les données produites par une autre, leurs soumissions doivent être reliées par une dépendance explicite.' +concepts.execution.queues.guidance: 'Dans une même file, des opérations dépendantes peuvent aussi nécessiter des barrières ou des transitions de texture pour que les accès ultérieurs voient les écritures précédentes. Ces dépendances mémoire sont distinctes de l’ordre de soumission. L’article {link} explique comment les exprimer.' concepts.execution.queues.guidance.link: Synchronisation -concepts.execution.queues.table.computeQueue.workToRecord: "Lancements de calcul et transferts compatibles, sans passe graphique." -concepts.execution.queues.table.graphicsQueue.workToRecord: "Passes de rendu, dessin, calcul et transferts." +concepts.execution.queues.table.computeQueue.workToRecord: 'Lancements de calcul et transferts compatibles, sans passe graphique.' +concepts.execution.queues.table.graphicsQueue.workToRecord: 'Passes de rendu, dessin, calcul et transferts.' concepts.execution.queues.table.headings.queue: File -concepts.execution.queues.table.headings.workToRecord: "Opérations prises en charge" -concepts.execution.queues.table.transferQueue.workToRecord: "Transferts vers ou depuis le GPU et copies, sans dessin ni lancement de calcul." -concepts.execution.queues.title: "Choix des files" -concepts.execution.recording.context: "La file récupère les tampons de commandes terminés pour les réutiliser. Pour chaque enregistrement, obtenir un tampon avec {queueCommandBuffer}, l’enregistrer depuis un seul thread à la fois et le soumettre une seule fois. Après la soumission, le laisser à la file : ne plus le modifier, le soumettre à nouveau ou le libérer." -concepts.execution.recording.description: "{queueCommandBuffer} renvoie un {commandBuffer} dont l’enregistrement a commencé. Une fois les opérations et leurs dépendances enregistrées, appeler {submit} une seule fois. La soumission termine l’enregistrement et fournit une {timelineValue} qui identifie le point d’achèvement de cette file." -concepts.execution.recording.details: "Après l’enregistrement d’une image dans {commandBuffer}, le tutoriel soumet le tampon et attend son achèvement :" -concepts.execution.recording.guidance: "L’enregistrement construit la séquence de commandes ; {submit} en planifie l’exécution. Un appel à {wait} bloque ensuite le thread CPU jusqu’à la fin de la soumission. Dans le tutoriel, la boucle de rendu reste ainsi facile à suivre : chaque image est terminée avant que la suivante commence." -concepts.execution.recording.title: "Enregistrement et soumission" +concepts.execution.queues.table.headings.workToRecord: 'Opérations prises en charge' +concepts.execution.queues.table.transferQueue.workToRecord: 'Transferts vers ou depuis le GPU et copies, sans dessin ni lancement de calcul.' +concepts.execution.queues.title: 'Choix des files' +concepts.execution.recording.context: 'La file récupère les tampons de commandes terminés pour les réutiliser. Pour chaque enregistrement, obtenir un tampon avec {queueCommandBuffer}, l’enregistrer depuis un seul thread à la fois et le soumettre une seule fois. Après la soumission, le laisser à la file : ne plus le modifier, le soumettre à nouveau ou le libérer.' +concepts.execution.recording.description: '{queueCommandBuffer} renvoie un {commandBuffer} dont l’enregistrement a commencé. Une fois les opérations et leurs dépendances enregistrées, appeler {submit} une seule fois. La soumission termine l’enregistrement et fournit une {timelineValue} qui identifie le point d’achèvement de cette file.' +concepts.execution.recording.details: 'Après l’enregistrement d’une image dans {commandBuffer}, le tutoriel soumet le tampon et attend son achèvement :' +concepts.execution.recording.guidance: 'L’enregistrement construit la séquence de commandes ; {submit} en planifie l’exécution. Un appel à {wait} bloque ensuite le thread CPU jusqu’à la fin de la soumission. Dans le tutoriel, la boucle de rendu reste ainsi facile à suivre : chaque image est terminée avant que la suivante commence.' +concepts.execution.recording.title: 'Enregistrement et soumission' concepts.execution.title: Modèle d’exécution -concepts.platforms.description: "La présentation est gérée par l’application ou par un contrôle d’interface. Ce choix détermine qui obtient la texture de sortie de l’image, enregistre et soumet les commandes, puis présente le résultat. Cette texture de sortie est appelée drawable." -concepts.platforms.frame.context: "Enregistrer les liaisons de pipeline et les commandes de dessin dans la passe, puis la terminer avant que le gestionnaire retourne. Le contrôle soumet les commandes et présente le résultat. Le gestionnaire ne doit ni soumettre le tampon de commandes ni libérer l’un ou l’autre des objets fournis. S’il modifie le layout de la texture de sortie, il doit rétablir {colorAttachment} avant de retourner pour permettre au contrôle d’effectuer la transition finale." -concepts.platforms.frame.description: "Les contrôles implémentent {iZenithView}. L’application assigne {graphicsContext}, met à jour la scène dans {updateRequested} et enregistre le rendu dans {renderRequested} à partir de {renderEventArgs}." -concepts.platforms.frame.details: "Pour chaque image, le contrôle obtient une texture de sortie et un tampon de commandes, passe la texture au layout {colorAttachment}, puis appelle les gestionnaires de mise à jour et de rendu. Il soumet ensuite les commandes enregistrées et présente l’image par le mécanisme du framework." -concepts.platforms.frame.guidance: "Ajouter {usingZenithNET} au fichier. Pour un {iZenithView} initialisé, nommé {view} et associé à un contexte graphique, enregistrer ce gestionnaire afin de remplir sa texture de sortie avec une couleur :" -concepts.platforms.frame.notes: "La transition initiale utilise {undefined}, ce qui autorise l’abandon du contenu précédent. Dessiner ou réinitialiser l’image entière à chaque rendu. Pour conserver une accumulation ou un résultat en cache, utiliser une texture appartenant à l’application, puis dessiner cette texture dans la sortie du contrôle." -concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat} fournit le format de couleur par défaut de ces intégrations." -concepts.platforms.frame.title: "Rendu par un contrôle UI" -concepts.platforms.integration.context: "WinForms, WPF et l’intégration Windows de WinUI s’exécutent sous Windows. Pour MAUI, installer la charge de travail de la plateforme cible et enregistrer le gestionnaire du contrôle avec {useZenithView}, comme dans {extensionsCs}." -concepts.platforms.integration.description: "L’interface d’événements est commune, mais la présentation dépend du framework :" -concepts.platforms.integration.details: "Ces implémentations diffèrent par la façon dont l’image GPU rejoint l’interface. La lecture vers un bitmap copie les pixels en mémoire CPU avant l’affichage. L’interopérabilité par texture partagée évite cette copie CPU, mais peut encore nécessiter des copies GPU et de la synchronisation. Pour choisir une intégration, considérer ce chemin de présentation en plus de l’événement commun {renderRequested}." -concepts.platforms.integration.guidance: "Ajoutez le paquet d’intégration correspondant à votre framework d’interface via NuGet. Pour Avalonia, utilisez {avaloniaPackage}." +concepts.platforms.description: 'La présentation est gérée par l’application ou par un contrôle d’interface. Ce choix détermine qui obtient la texture de sortie de l’image, enregistre et soumet les commandes, puis présente le résultat. Cette texture de sortie est appelée drawable.' +concepts.platforms.frame.context: 'Enregistrer les liaisons de pipeline et les commandes de dessin dans la passe, puis la terminer avant que le gestionnaire retourne. Le contrôle soumet les commandes et présente le résultat. Le gestionnaire ne doit ni soumettre le tampon de commandes ni libérer l’un ou l’autre des objets fournis. S’il modifie le layout de la texture de sortie, il doit rétablir {colorAttachment} avant de retourner pour permettre au contrôle d’effectuer la transition finale.' +concepts.platforms.frame.description: 'Les contrôles implémentent {iZenithView}. L’application assigne {graphicsContext}, met à jour la scène dans {updateRequested} et enregistre le rendu dans {renderRequested} à partir de {renderEventArgs}.' +concepts.platforms.frame.details: 'Pour chaque image, le contrôle obtient une texture de sortie et un tampon de commandes, passe la texture au layout {colorAttachment}, puis appelle les gestionnaires de mise à jour et de rendu. Il soumet ensuite les commandes enregistrées et présente l’image par le mécanisme du framework.' +concepts.platforms.frame.guidance: 'Ajouter {usingZenithNET} au fichier. Pour un {iZenithView} initialisé, nommé {view} et associé à un contexte graphique, enregistrer ce gestionnaire afin de remplir sa texture de sortie avec une couleur :' +concepts.platforms.frame.notes: 'La transition initiale utilise {undefined}, ce qui autorise l’abandon du contenu précédent. Dessiner ou réinitialiser l’image entière à chaque rendu. Pour conserver une accumulation ou un résultat en cache, utiliser une texture appartenant à l’application, puis dessiner cette texture dans la sortie du contrôle.' +concepts.platforms.frame.reference: '{zenithViewHelperDrawableFormat} fournit le format de couleur par défaut de ces intégrations.' +concepts.platforms.frame.title: 'Rendu par un contrôle UI' +concepts.platforms.integration.context: 'WinForms, WPF et l’intégration Windows de WinUI s’exécutent sous Windows. Pour MAUI, installer la charge de travail de la plateforme cible et enregistrer le gestionnaire du contrôle avec {useZenithView}, comme dans {extensionsCs}.' +concepts.platforms.integration.description: 'L’interface d’événements est commune, mais la présentation dépend du framework :' +concepts.platforms.integration.details: 'Ces implémentations diffèrent par la façon dont l’image GPU rejoint l’interface. La lecture vers un bitmap copie les pixels en mémoire CPU avant l’affichage. L’interopérabilité par texture partagée évite cette copie CPU, mais peut encore nécessiter des copies GPU et de la synchronisation. Pour choisir une intégration, considérer ce chemin de présentation en plus de l’événement commun {renderRequested}.' +concepts.platforms.integration.guidance: 'Ajoutez le paquet d’intégration correspondant à votre framework d’interface via NuGet. Pour Avalonia, utilisez {avaloniaPackage}.' concepts.platforms.integration.table.avalonia.integration: Avalonia -concepts.platforms.integration.table.avalonia.presentation: "Effectue le rendu dans une texture, puis copie les pixels en mémoire CPU dans {writeableBitmap}. Implémentation : {zenithViewCs} et {surfaceCs}." +concepts.platforms.integration.table.avalonia.presentation: 'Effectue le rendu dans une texture, puis copie les pixels en mémoire CPU dans {writeableBitmap}. Implémentation : {zenithViewCs} et {surfaceCs}.' concepts.platforms.integration.table.headings.integration: Intégration -concepts.platforms.integration.table.headings.presentation: "Mécanisme de présentation" +concepts.platforms.integration.table.headings.presentation: 'Mécanisme de présentation' concepts.platforms.integration.table.maui.integration: .NET MAUI concepts.platforms.integration.table.maui.presentation: Utilise des surfaces natives sur Android, iOS et Mac Catalyst, et la composition par texture partagée sous Windows. Voir les {link}. concepts.platforms.integration.table.maui.presentation.link: implémentations de plateforme concepts.platforms.integration.table.uno.integration: Voie Uno -concepts.platforms.integration.table.uno.presentation: "Copie les pixels en mémoire CPU dans {writeableBitmap}. Implémentation : {zenithViewUnoCs}." +concepts.platforms.integration.table.uno.presentation: 'Copie les pixels en mémoire CPU dans {writeableBitmap}. Implémentation : {zenithViewUnoCs}.' concepts.platforms.integration.table.winForms.integration: WinForms concepts.platforms.integration.table.winForms.presentation: Crée une chaîne d’échange Zenith.NET pour le {hWND} du contrôle. Voir {zenithViewCs}. concepts.platforms.integration.table.winUI.integration: WinUI sous Windows -concepts.platforms.integration.table.winUI.presentation: "Effectue le rendu dans une texture partagée Direct3D 11 importée, puis copie le résultat vers une chaîne d’échange de composition attachée à {swapChainPanel}. Voir {zenithViewWinUICs}." +concepts.platforms.integration.table.winUI.presentation: 'Effectue le rendu dans une texture partagée Direct3D 11 importée, puis copie le résultat vers une chaîne d’échange de composition attachée à {swapChainPanel}. Voir {zenithViewWinUICs}.' concepts.platforms.integration.table.wpf.integration: WPF -concepts.platforms.integration.table.wpf.presentation: "Importe une texture partagée Direct3D 11, puis copie son contenu, par interopérabilité Direct3D, vers une surface affichée par {d3DImage}. Voir {surfaceCs}." -concepts.platforms.integration.title: "Framework et présentation" -concepts.platforms.lifecycle.context: "Pour créer des attachements compatibles, utiliser {descWidth}, {descHeight}, {descFormat} et {descSampleCount} de la texture de sortie fournie par l’événement de rendu. Cette texture donne les dimensions réelles de la cible ; elles ne doivent pas être déduites de la taille du contrôle dans la mise en page ni de l’échelle d’affichage." -concepts.platforms.lifecycle.description: "La chaîne d’échange utilise la largeur et la hauteur du framebuffer en pixels, qui peuvent différer des dimensions logiques de la fenêtre avec la mise à l’échelle de l’affichage. Différer le rendu et le redimensionnement tant qu’une dimension est nulle. Obtenir {swapChainDrawable} pour chaque image : la chaîne d’échange possède cette texture et peut la remplacer après une présentation ou un redimensionnement." -concepts.platforms.lifecycle.details: "Lors d’un changement de dimensions du framebuffer, attendre les accès GPU en cours aux anciennes images avant d’appeler {swapChainResize}. Pour remplacer la cible native de présentation, transmettre sa nouvelle description et ses handles à {swapChainRefresh}, une fois ces accès terminés. À l’arrêt, libérer la chaîne d’échange avant de détruire sa cible native." -concepts.platforms.lifecycle.guidance: "Si les textures de profondeur ou hors écran de l’application suivent la taille de la fenêtre, les recréer quand celle-ci change et mettre à jour les constantes contenant leurs handles. Le pipeline reste utilisable tant que les formats des attachements et les nombres d’échantillons correspondent. Le {link} montre comment recréer les textures tout en conservant le pipeline." +concepts.platforms.integration.table.wpf.presentation: 'Importe une texture partagée Direct3D 11, puis copie son contenu, par interopérabilité Direct3D, vers une surface affichée par {d3DImage}. Voir {surfaceCs}.' +concepts.platforms.integration.title: 'Framework et présentation' +concepts.platforms.lifecycle.context: 'Pour créer des attachements compatibles, utiliser {descWidth}, {descHeight}, {descFormat} et {descSampleCount} de la texture de sortie fournie par l’événement de rendu. Cette texture donne les dimensions réelles de la cible ; elles ne doivent pas être déduites de la taille du contrôle dans la mise en page ni de l’échelle d’affichage.' +concepts.platforms.lifecycle.description: 'La chaîne d’échange utilise la largeur et la hauteur du framebuffer en pixels, qui peuvent différer des dimensions logiques de la fenêtre avec la mise à l’échelle de l’affichage. Différer le rendu et le redimensionnement tant qu’une dimension est nulle. Obtenir {swapChainDrawable} pour chaque image : la chaîne d’échange possède cette texture et peut la remplacer après une présentation ou un redimensionnement.' +concepts.platforms.lifecycle.details: 'Lors d’un changement de dimensions du framebuffer, attendre les accès GPU en cours aux anciennes images avant d’appeler {swapChainResize}. Pour remplacer la cible native de présentation, transmettre sa nouvelle description et ses handles à {swapChainRefresh}, une fois ces accès terminés. À l’arrêt, libérer la chaîne d’échange avant de détruire sa cible native.' +concepts.platforms.lifecycle.guidance: 'Si les textures de profondeur ou hors écran de l’application suivent la taille de la fenêtre, les recréer quand celle-ci change et mettre à jour les constantes contenant leurs handles. Le pipeline reste utilisable tant que les formats des attachements et les nombres d’échantillons correspondent. Le {link} montre comment recréer les textures tout en conservant le pipeline.' concepts.platforms.lifecycle.guidance.link: moteur de rendu du cube en rotation -concepts.platforms.lifecycle.title: "Dimensions et durée de vie de la chaîne d’échange" -concepts.platforms.ownership.description: "L’application possède le contexte assigné et ses ressources de rendu ; le contrôle possède ses ressources de présentation. Lorsque la propriété {graphicsContext} de la vue change, l’ordonnanceur recrée les ressources du contrôle pour le nouveau contexte. L’application doit également recréer ses pipelines, tampons et textures pour ce contexte." -concepts.platforms.ownership.details: "Avant de remplacer des ressources de rendu, arrêter le traitement des images de la vue et attendre le travail GPU qui les utilise. Libérer ensuite seulement les anciennes ressources ou le contexte. L’application reste responsable de la libération du contexte assigné lors du retrait de la vue." -concepts.platforms.ownership.guidance: "Le {frameSchedulerCs} commun exécute les gestionnaires d’image via le dispatcher de l’interface de la vue. Limiter leur travail à la mise à jour de la scène et à l’enregistrement des commandes : un traitement CPU prolongé à cet endroit retarde aussi l’interface." -concepts.platforms.ownership.title: "Responsabilités de l’application et du contrôle" -concepts.platforms.surface.description: "Le {link} utilise Silk.NET pour créer la fenêtre et traiter ses événements. Zenith.NET reçoit les handles natifs et les dimensions dans une description {surface}, à partir de laquelle il crée une {swapChain}. L’application reste responsable de la fenêtre du système d’exploitation." -concepts.platforms.surface.description.link: "tutoriel du triangle" -concepts.platforms.surface.details: "Les handles natifs doivent correspondre au backend :" -concepts.platforms.surface.guidance: "L’hôte des exemples dans {appCs} prend en charge Windows, macOS et X11. Sous Linux, sa fenêtre fournit des handles Xlib ; une session Wayland doit donc disposer de XWayland pour l’exécuter. Une application Wayland native transmet ses handles de display et de surface via {surfaceWayland}." +concepts.platforms.lifecycle.title: 'Dimensions et durée de vie de la chaîne d’échange' +concepts.platforms.ownership.description: 'L’application possède le contexte assigné et ses ressources de rendu ; le contrôle possède ses ressources de présentation. Lorsque la propriété {graphicsContext} de la vue change, l’ordonnanceur recrée les ressources du contrôle pour le nouveau contexte. L’application doit également recréer ses pipelines, tampons et textures pour ce contexte.' +concepts.platforms.ownership.details: 'Avant de remplacer des ressources de rendu, arrêter le traitement des images de la vue et attendre le travail GPU qui les utilise. Libérer ensuite seulement les anciennes ressources ou le contexte. L’application reste responsable de la libération du contexte assigné lors du retrait de la vue.' +concepts.platforms.ownership.guidance: 'Le {frameSchedulerCs} commun exécute les gestionnaires d’image via le dispatcher de l’interface de la vue. Limiter leur travail à la mise à jour de la scène et à l’enregistrement des commandes : un traitement CPU prolongé à cet endroit retarde aussi l’interface.' +concepts.platforms.ownership.title: 'Responsabilités de l’application et du contrôle' +concepts.platforms.surface.description: 'Le {link} utilise Silk.NET pour créer la fenêtre et traiter ses événements. Zenith.NET reçoit les handles natifs et les dimensions dans une description {surface}, à partir de laquelle il crée une {swapChain}. L’application reste responsable de la fenêtre du système d’exploitation.' +concepts.platforms.surface.description.link: 'tutoriel du triangle' +concepts.platforms.surface.details: 'Les handles natifs doivent correspondre au backend :' +concepts.platforms.surface.guidance: 'L’hôte des exemples dans {appCs} prend en charge Windows, macOS et X11. Sous Linux, sa fenêtre fournit des handles Xlib ; une session Wayland doit donc disposer de XWayland pour l’exécuter. Une application Wayland native transmet ses handles de display et de surface via {surfaceWayland}.' concepts.platforms.surface.table.android.backend: Vulkan sous Android. concepts.platforms.surface.table.apple.backend: Metal sur les plateformes Apple. -concepts.platforms.surface.table.headings.backend: "Backend et plateforme" +concepts.platforms.surface.table.headings.backend: 'Backend et plateforme' concepts.platforms.surface.table.headings.factory: Fabrique de surface concepts.platforms.surface.table.headings.handles: Handles fournis par l’hôte concepts.platforms.surface.table.wayland.backend: Vulkan avec un hôte Wayland natif. @@ -93,268 +93,268 @@ concepts.platforms.surface.table.wayland.handles: Affichage et surface Wayland concepts.platforms.surface.table.win32.backend: DirectX 12 ou Vulkan sous Windows. concepts.platforms.surface.table.xlib.backend: Vulkan sous Linux avec X11 ou XWayland. concepts.platforms.surface.table.xlib.handles: Affichage et fenêtre X11 -concepts.platforms.surface.title: "Surfaces de présentation natives" +concepts.platforms.surface.title: 'Surfaces de présentation natives' concepts.platforms.title: Intégration de plateforme -concepts.resources.allocation.context: "Les ressources placées dans un tas dépendent de sa mémoire pendant toute leur durée de vie. Après leur dernière utilisation par le GPU, libérer les ressources avant de libérer le tas." -concepts.resources.allocation.description: "Un {heap} permet à l’application de gérer elle-même les allocations. Il fournit une mémoire où placer les ressources à des décalages explicites en octets. L’application choisit ces emplacements et suit les régions occupées." -concepts.resources.allocation.details: "Pour chaque ressource, appeler {contextGetSizeAndAlignment} avec la description de tampon ou de texture qui servira à sa création. Réserver la taille renvoyée à un décalage multiple de l’alignement demandé, dans les limites du tas et sans chevaucher une allocation encore active. La taille d’une texture peut inclure du remplissage propre au backend ; le nombre de pixels et le nombre d’octets par pixel ne suffisent donc pas à calculer la taille de son allocation." -concepts.resources.allocation.guidance: "Un tampon placé dans un tas doit déclarer la même résidence que ce tas. Pour les textures, utiliser un tas destiné exclusivement au GPU." -concepts.resources.allocation.title: "Allocation dans un tas" +concepts.resources.allocation.context: 'Les ressources placées dans un tas dépendent de sa mémoire pendant toute leur durée de vie. Après leur dernière utilisation par le GPU, libérer les ressources avant de libérer le tas.' +concepts.resources.allocation.description: 'Un {heap} permet à l’application de gérer elle-même les allocations. Il fournit une mémoire où placer les ressources à des décalages explicites en octets. L’application choisit ces emplacements et suit les régions occupées.' +concepts.resources.allocation.details: 'Pour chaque ressource, appeler {contextGetSizeAndAlignment} avec la description de tampon ou de texture qui servira à sa création. Réserver la taille renvoyée à un décalage multiple de l’alignement demandé, dans les limites du tas et sans chevaucher une allocation encore active. La taille d’une texture peut inclure du remplissage propre au backend ; le nombre de pixels et le nombre d’octets par pixel ne suffisent donc pas à calculer la taille de son allocation.' +concepts.resources.allocation.guidance: 'Un tampon placé dans un tas doit déclarer la même résidence que ce tas. Pour les textures, utiliser un tas destiné exclusivement au GPU.' +concepts.resources.allocation.title: 'Allocation dans un tas' concepts.resources.bufferUsages.table.constant.role: Paramètres de shader lus via une liaison de tampon de constantes. -concepts.resources.bufferUsages.table.headings.role: "Rôle" +concepts.resources.bufferUsages.table.headings.role: 'Rôle' concepts.resources.bufferUsages.table.headings.usage: Usage concepts.resources.bufferUsages.table.index.role: Indices utilisés par le dessin indexé. -concepts.resources.bufferUsages.table.indirect.role: "Arguments lus par les commandes de dessin indirect ou de lancement indirect de calcul." -concepts.resources.bufferUsages.table.none.role: "Aucun indicateur d’usage du tampon n’est déclaré." -concepts.resources.bufferUsages.table.storageReadOnly.role: "Données de tampon accessibles via une liaison de shader en lecture seule." -concepts.resources.bufferUsages.table.storageReadWrite.role: "Données de tampon accessibles via une liaison de shader en lecture et écriture." -concepts.resources.bufferUsages.table.transferDst.role: "Stockage de destination d’une copie GPU." -concepts.resources.bufferUsages.table.transferSrc.role: "Données sources d’une copie GPU." +concepts.resources.bufferUsages.table.indirect.role: 'Arguments lus par les commandes de dessin indirect ou de lancement indirect de calcul.' +concepts.resources.bufferUsages.table.none.role: 'Aucun indicateur d’usage du tampon n’est déclaré.' +concepts.resources.bufferUsages.table.storageReadOnly.role: 'Données de tampon accessibles via une liaison de shader en lecture seule.' +concepts.resources.bufferUsages.table.storageReadWrite.role: 'Données de tampon accessibles via une liaison de shader en lecture et écriture.' +concepts.resources.bufferUsages.table.transferDst.role: 'Stockage de destination d’une copie GPU.' +concepts.resources.bufferUsages.table.transferSrc.role: 'Données sources d’une copie GPU.' concepts.resources.bufferUsages.table.vertex.role: Attributs de sommets récupérés pour le dessin. concepts.resources.bufferUsages.title: Usages de tampon -concepts.resources.description: "La description d’une ressource définit les usages autorisés de sa mémoire. Par exemple, une texture servant de cible de rendu, échantillonnée par un shader et recopiée vers le CPU doit déclarer les indicateurs d’usage correspondant aux trois opérations. Le placement mémoire détermine l’accès CPU ; la synchronisation et la gestion de la durée de vie déterminent quand accéder aux données ou libérer la mémoire." -concepts.resources.memory.context: "Pour les tampons accessibles au CPU, {map} fournit l’adresse à laquelle lire ou écrire les données. Ni le mapping ni {unmap} n’attendent le travail du GPU. L’application doit attendre la fin d’une écriture GPU avant d’en lire le résultat, et la fin des accès GPU en cours avant de modifier les mêmes octets." -concepts.resources.memory.description: "Le champ {residency} de {bufferDesc} précise l’accès CPU prévu à l’allocation :" -concepts.resources.memory.details: "La résidence exprime les besoins d’accès du CPU, y compris lorsque CPU et GPU partagent la même mémoire physique. Le triangle utilise {cpuWriteOnly} pour initialiser directement son petit tampon de sommets. Pour une géométrie statique plus volumineuse, un transfert vers une mémoire destinée exclusivement au GPU peut être plus adapté." -concepts.resources.memory.guidance: "Les textures créées directement par le contexte utilisent de la mémoire GPU. {textureDesc} ne comporte donc pas de champ de résidence. L’application échange leurs données avec la mémoire CPU au moyen de transferts vers et depuis le GPU." -concepts.resources.memory.table.cpuReadOnly.cPUAccess: "Lecture seule" -concepts.resources.memory.table.cpuReadOnly.typicalRole: "Données produites par le GPU pour être relues par le CPU" -concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "Écriture seule" -concepts.resources.memory.table.cpuWriteOnly.typicalRole: "Données fournies ou mises à jour par le CPU" -concepts.resources.memory.table.gpuOnly.cPUAccess: "Aucun" -concepts.resources.memory.table.gpuOnly.typicalRole: "Géométrie statique et données de travail du GPU" -concepts.resources.memory.table.headings.cPUAccess: "Accès CPU prévu" +concepts.resources.description: 'La description d’une ressource définit les usages autorisés de sa mémoire. Par exemple, une texture servant de cible de rendu, échantillonnée par un shader et recopiée vers le CPU doit déclarer les indicateurs d’usage correspondant aux trois opérations. Le placement mémoire détermine l’accès CPU ; la synchronisation et la gestion de la durée de vie déterminent quand accéder aux données ou libérer la mémoire.' +concepts.resources.memory.context: 'Pour les tampons accessibles au CPU, {map} fournit l’adresse à laquelle lire ou écrire les données. Ni le mapping ni {unmap} n’attendent le travail du GPU. L’application doit attendre la fin d’une écriture GPU avant d’en lire le résultat, et la fin des accès GPU en cours avant de modifier les mêmes octets.' +concepts.resources.memory.description: 'Le champ {residency} de {bufferDesc} précise l’accès CPU prévu à l’allocation :' +concepts.resources.memory.details: 'La résidence exprime les besoins d’accès du CPU, y compris lorsque CPU et GPU partagent la même mémoire physique. Le triangle utilise {cpuWriteOnly} pour initialiser directement son petit tampon de sommets. Pour une géométrie statique plus volumineuse, un transfert vers une mémoire destinée exclusivement au GPU peut être plus adapté.' +concepts.resources.memory.guidance: 'Les textures créées directement par le contexte utilisent de la mémoire GPU. {textureDesc} ne comporte donc pas de champ de résidence. L’application échange leurs données avec la mémoire CPU au moyen de transferts vers et depuis le GPU.' +concepts.resources.memory.table.cpuReadOnly.cPUAccess: 'Lecture seule' +concepts.resources.memory.table.cpuReadOnly.typicalRole: 'Données produites par le GPU pour être relues par le CPU' +concepts.resources.memory.table.cpuWriteOnly.cPUAccess: 'Écriture seule' +concepts.resources.memory.table.cpuWriteOnly.typicalRole: 'Données fournies ou mises à jour par le CPU' +concepts.resources.memory.table.gpuOnly.cPUAccess: 'Aucun' +concepts.resources.memory.table.gpuOnly.typicalRole: 'Géométrie statique et données de travail du GPU' +concepts.resources.memory.table.headings.cPUAccess: 'Accès CPU prévu' concepts.resources.memory.table.headings.residency: Résidence concepts.resources.memory.table.headings.typicalRole: Rôle typique -concepts.resources.memory.title: "Accès CPU et placement mémoire" -concepts.resources.textureUsages.description: "Les indicateurs de transfert précisent si la ressource sert de source ou de destination d’une copie GPU. La possibilité pour le CPU d’accéder directement à sa mémoire relève d’un choix distinct : le placement mémoire." -concepts.resources.textureUsages.details: "Les indicateurs d’usage déclarent les rôles possibles d’une texture. Le passage d’un rôle à un autre doit respecter les exigences de {link}. Le périphérique doit également prendre en charge les usages demandés pour le format choisi." -concepts.resources.textureUsages.details.link: "layout et synchronisation" -concepts.resources.textureUsages.table.colorAttachment.role: "Un attachement de couleur dans une passe de rendu." -concepts.resources.textureUsages.table.depthStencilAttachment.role: "Un attachement de profondeur et de stencil dans une passe de rendu." -concepts.resources.textureUsages.table.headings.role: "Rôle" +concepts.resources.memory.title: 'Accès CPU et placement mémoire' +concepts.resources.textureUsages.description: 'Les indicateurs de transfert précisent si la ressource sert de source ou de destination d’une copie GPU. La possibilité pour le CPU d’accéder directement à sa mémoire relève d’un choix distinct : le placement mémoire.' +concepts.resources.textureUsages.details: 'Les indicateurs d’usage déclarent les rôles possibles d’une texture. Le passage d’un rôle à un autre doit respecter les exigences de {link}. Le périphérique doit également prendre en charge les usages demandés pour le format choisi.' +concepts.resources.textureUsages.details.link: 'layout et synchronisation' +concepts.resources.textureUsages.table.colorAttachment.role: 'Un attachement de couleur dans une passe de rendu.' +concepts.resources.textureUsages.table.depthStencilAttachment.role: 'Un attachement de profondeur et de stencil dans une passe de rendu.' +concepts.resources.textureUsages.table.headings.role: 'Rôle' concepts.resources.textureUsages.table.headings.usage: Usage -concepts.resources.textureUsages.table.none.role: "Aucun indicateur d’usage de la texture n’est déclaré." -concepts.resources.textureUsages.table.sampled.role: "Données de texture lues via une liaison de texture échantillonnée." -concepts.resources.textureUsages.table.storage.role: "Données de texture accessibles via une liaison de texture de stockage pour les lectures ou écritures des shaders." -concepts.resources.textureUsages.table.transferDst.role: "Stockage de l’image de destination d’une copie GPU." -concepts.resources.textureUsages.table.transferSrc.role: "Données de l’image source d’une copie GPU." +concepts.resources.textureUsages.table.none.role: 'Aucun indicateur d’usage de la texture n’est déclaré.' +concepts.resources.textureUsages.table.sampled.role: 'Données de texture lues via une liaison de texture échantillonnée.' +concepts.resources.textureUsages.table.storage.role: 'Données de texture accessibles via une liaison de texture de stockage pour les lectures ou écritures des shaders.' +concepts.resources.textureUsages.table.transferDst.role: 'Stockage de l’image de destination d’une copie GPU.' +concepts.resources.textureUsages.table.transferSrc.role: 'Données de l’image source d’une copie GPU.' concepts.resources.textureUsages.title: Usages de texture concepts.resources.title: Gestion des ressources -concepts.resources.transfers.context: "Un transfert depuis le GPU copie d’abord les données dans une mémoire de lecture interne. La bibliothèque les copie ensuite vers la destination CPU fournie lorsqu’elle récupère le tampon de commandes terminé. Appeler {wait} sur la valeur de soumission de ce transfert achève les deux étapes. Jusqu’au retour de cet appel, conserver la mémoire de destination et maintenir épinglée toute mémoire managée utilisée." -concepts.resources.transfers.description: "Les transferts vers le GPU copient des données CPU dans une ressource ; les transferts depuis le GPU copient les données d’une ressource en mémoire CPU. Les méthodes des tampons et des textures terminent ce transfert avant de retourner :" -concepts.resources.transfers.details: "Avant ces appels, résoudre les conflits d’accès avec les autres files. L’attente effectuée dans une méthode ne couvre que son propre transfert ; elle n’établit pas de dépendance avec une autre file. Pour les chemins qui accèdent directement à la mémoire mappée, il revient entièrement à l’appelant d’attendre les accès GPU en conflit." -concepts.resources.transfers.guidance: "Pour soumettre des transferts avec d’autres opérations GPU, les enregistrer avec {commandBufferUpload} ou {commandBufferDownload}. La mémoire source d’un transfert vers le GPU et la mémoire de destination d’un transfert depuis le GPU ont des exigences de durée de vie différentes :" -concepts.resources.transfers.item: "Pendant l’appel de transfert vers le GPU, la bibliothèque copie les données source dans une mémoire de transfert temporaire. Le GPU lit ensuite cette copie intermédiaire. Le pointeur source de l’application n’est donc nécessaire que jusqu’au retour de l’appel." -concepts.resources.transfers.notes: "Pour les transferts de texture, le pas de ligne est la distance en octets entre deux lignes successives des données CPU ; le pas de tranche est la distance entre deux tranches de profondeur. Ces valeurs permettent de copier les données entre la mémoire CPU et la texture GPU. L’article {link} explique pourquoi l’achèvement sur le GPU et la copie vers la destination CPU sont deux étapes distinctes." +concepts.resources.transfers.context: 'Un transfert depuis le GPU copie d’abord les données dans une mémoire de lecture interne. La bibliothèque les copie ensuite vers la destination CPU fournie lorsqu’elle récupère le tampon de commandes terminé. Appeler {wait} sur la valeur de soumission de ce transfert achève les deux étapes. Jusqu’au retour de cet appel, conserver la mémoire de destination et maintenir épinglée toute mémoire managée utilisée.' +concepts.resources.transfers.description: 'Les transferts vers le GPU copient des données CPU dans une ressource ; les transferts depuis le GPU copient les données d’une ressource en mémoire CPU. Les méthodes des tampons et des textures terminent ce transfert avant de retourner :' +concepts.resources.transfers.details: 'Avant ces appels, résoudre les conflits d’accès avec les autres files. L’attente effectuée dans une méthode ne couvre que son propre transfert ; elle n’établit pas de dépendance avec une autre file. Pour les chemins qui accèdent directement à la mémoire mappée, il revient entièrement à l’appelant d’attendre les accès GPU en conflit.' +concepts.resources.transfers.guidance: 'Pour soumettre des transferts avec d’autres opérations GPU, les enregistrer avec {commandBufferUpload} ou {commandBufferDownload}. La mémoire source d’un transfert vers le GPU et la mémoire de destination d’un transfert depuis le GPU ont des exigences de durée de vie différentes :' +concepts.resources.transfers.item: 'Pendant l’appel de transfert vers le GPU, la bibliothèque copie les données source dans une mémoire de transfert temporaire. Le GPU lit ensuite cette copie intermédiaire. Le pointeur source de l’application n’est donc nécessaire que jusqu’au retour de l’appel.' +concepts.resources.transfers.notes: 'Pour les transferts de texture, le pas de ligne est la distance en octets entre deux lignes successives des données CPU ; le pas de tranche est la distance entre deux tranches de profondeur. Ces valeurs permettent de copier les données entre la mémoire CPU et la texture GPU. L’article {link} explique pourquoi l’achèvement sur le GPU et la copie vers la destination CPU sont deux étapes distinctes.' concepts.resources.transfers.notes.link: Synchronisation -concepts.resources.transfers.table.bufferDownload.transfer: "Copie directement depuis la mémoire mappée pour {cpuReadOnly}. Sinon, soumet le transfert à la file de transfert et attend qu’il soit terminé." -concepts.resources.transfers.table.bufferUpload.transfer: "Copie directement dans la mémoire mappée pour {cpuWriteOnly}. Sinon, soumet le transfert à la file de transfert et attend qu’il soit terminé." +concepts.resources.transfers.table.bufferDownload.transfer: 'Copie directement depuis la mémoire mappée pour {cpuReadOnly}. Sinon, soumet le transfert à la file de transfert et attend qu’il soit terminé.' +concepts.resources.transfers.table.bufferUpload.transfer: 'Copie directement dans la mémoire mappée pour {cpuWriteOnly}. Sinon, soumet le transfert à la file de transfert et attend qu’il soit terminé.' concepts.resources.transfers.table.headings.method: Méthode -concepts.resources.transfers.table.headings.transfer: "Comportement du transfert" -concepts.resources.transfers.table.textureTransfers.method: "{textureUpload} / {textureDownload}" -concepts.resources.transfers.table.textureTransfers.transfer: "Soumet la copie et les transitions de texture à la file graphique, puis attend leur achèvement. La sous-ressource sélectionnée reste dans le layout final demandé." -concepts.resources.transfers.title: "Transferts immédiats et enregistrés" -concepts.resources.usages.description: "{bufferUsages} et {textureUsages} sont des énumérations d’indicateurs qui déclarent les usages d’une ressource. Leurs valeurs sont affectées à {bufferDescUsages} et {textureDescUsages}, respectivement. Plusieurs membres peuvent être combinés avec {value} pour déclarer plusieurs usages." -concepts.resources.usages.title: "Usages des ressources" -concepts.resources.views.description: "Une {bufferView} décrit une région de tampon et l’interprétation de ses données. Une {textureView} sélectionne une plage de sous-ressources, ainsi qu’un type de texture et un format compatibles. Toutes deux désignent une mémoire existante, avec les usages déclarés à sa création. Les plages des vues décrivent l’accès, mais n’offrent pas de contrôle des limites uniforme dans les shaders sur tous les backends." -concepts.resources.views.details: "Le handle propre à une ressource fournit sa vue par défaut. Créer une vue distincte pour sélectionner une autre région ou une autre interprétation compatible. La vue et sa ressource sous-jacente doivent rester disponibles jusqu’à la fin de leur utilisation par le GPU : un handle ne maintient aucun de ces objets en vie. Si l’un d’eux est remplacé, mettre à jour les constantes contenant l’ancien {link}." -concepts.resources.views.details.link: "handle de ressource" -concepts.resources.views.title: "Vues et ressources sous-jacentes" -concepts.shaders.binding.context: "L’exemple de calcul affecte {inputTextureSampledHandle} à {input} et {outputTextureStorageHandle} à {output}. En Slang, le paramètre de type de {descriptorHandle} définit l’accès à la ressource :" -concepts.shaders.binding.description: "{setConstantBuffer} sélectionne un tampon existant et le décalage en octets à partir duquel le pipeline courant lit ses constantes. Transférer les paramètres dans cette mémoire avant leur utilisation par le shader. Si un travail GPU antérieur lit encore les mêmes octets, attendre sa fin avant de les mettre à jour." -concepts.shaders.binding.details: "Préparer le tampon de commandes, le pipeline de calcul, le tampon de constantes rempli et le nombre de groupes de threads. Enregistrer ensuite le calcul dans l’ordre ci-dessous. Sélectionner d’abord le pipeline, car la liaison du tampon de constantes s’applique à ce pipeline :" -concepts.shaders.binding.guidance: "Ici, {commandBuffer} enregistre un calcul avec {computePipeline} et les paramètres de {constantBuffer}. Le tampon doit déclarer l’usage {bufferUsagesConstant} ; le décalage 0 sélectionne son début. Si plusieurs enregistrements de constantes partagent un tampon, le décalage de chacun doit aussi respecter l’alignement de liaison du backend, indépendamment de la disposition des champs à l’intérieur de l’enregistrement." -concepts.shaders.binding.notes: "{resourceHandle} contient deux champs de 32 bits dont l’interprétation dépend du backend. Leurs valeurs ne sont valables que dans le contexte où la ressource a été créée." -concepts.shaders.binding.reference: "Conserver la ressource et toute vue utilisée pour obtenir son handle jusqu’à la fin du dernier accès du shader. Lorsqu’une texture ou une vue est remplacée, mettre à jour les constantes contenant encore son ancien handle. Les règles de propriété sont détaillées dans {link}." +concepts.resources.transfers.table.headings.transfer: 'Comportement du transfert' +concepts.resources.transfers.table.textureTransfers.method: '{textureUpload} / {textureDownload}' +concepts.resources.transfers.table.textureTransfers.transfer: 'Soumet la copie et les transitions de texture à la file graphique, puis attend leur achèvement. La sous-ressource sélectionnée reste dans le layout final demandé.' +concepts.resources.transfers.title: 'Transferts immédiats et enregistrés' +concepts.resources.usages.description: '{bufferUsages} et {textureUsages} sont des énumérations d’indicateurs qui déclarent les usages d’une ressource. Leurs valeurs sont affectées à {bufferDescUsages} et {textureDescUsages}, respectivement. Plusieurs membres peuvent être combinés avec {value} pour déclarer plusieurs usages.' +concepts.resources.usages.title: 'Usages des ressources' +concepts.resources.views.description: 'Une {bufferView} décrit une région de tampon et l’interprétation de ses données. Une {textureView} sélectionne une plage de sous-ressources, ainsi qu’un type de texture et un format compatibles. Toutes deux désignent une mémoire existante, avec les usages déclarés à sa création. Les plages des vues décrivent l’accès, mais n’offrent pas de contrôle des limites uniforme dans les shaders sur tous les backends.' +concepts.resources.views.details: 'Le handle propre à une ressource fournit sa vue par défaut. Créer une vue distincte pour sélectionner une autre région ou une autre interprétation compatible. La vue et sa ressource sous-jacente doivent rester disponibles jusqu’à la fin de leur utilisation par le GPU : un handle ne maintient aucun de ces objets en vie. Si l’un d’eux est remplacé, mettre à jour les constantes contenant l’ancien {link}.' +concepts.resources.views.details.link: 'handle de ressource' +concepts.resources.views.title: 'Vues et ressources sous-jacentes' +concepts.shaders.binding.context: 'L’exemple de calcul affecte {inputTextureSampledHandle} à {input} et {outputTextureStorageHandle} à {output}. En Slang, le paramètre de type de {descriptorHandle} définit l’accès à la ressource :' +concepts.shaders.binding.description: '{setConstantBuffer} sélectionne un tampon existant et le décalage en octets à partir duquel le pipeline courant lit ses constantes. Transférer les paramètres dans cette mémoire avant leur utilisation par le shader. Si un travail GPU antérieur lit encore les mêmes octets, attendre sa fin avant de les mettre à jour.' +concepts.shaders.binding.details: 'Préparer le tampon de commandes, le pipeline de calcul, le tampon de constantes rempli et le nombre de groupes de threads. Enregistrer ensuite le calcul dans l’ordre ci-dessous. Sélectionner d’abord le pipeline, car la liaison du tampon de constantes s’applique à ce pipeline :' +concepts.shaders.binding.guidance: 'Ici, {commandBuffer} enregistre un calcul avec {computePipeline} et les paramètres de {constantBuffer}. Le tampon doit déclarer l’usage {bufferUsagesConstant} ; le décalage 0 sélectionne son début. Si plusieurs enregistrements de constantes partagent un tampon, le décalage de chacun doit aussi respecter l’alignement de liaison du backend, indépendamment de la disposition des champs à l’intérieur de l’enregistrement.' +concepts.shaders.binding.notes: '{resourceHandle} contient deux champs de 32 bits dont l’interprétation dépend du backend. Leurs valeurs ne sont valables que dans le contexte où la ressource a été créée.' +concepts.shaders.binding.reference: 'Conserver la ressource et toute vue utilisée pour obtenir son handle jusqu’à la fin du dernier accès du shader. Lorsqu’une texture ou une vue est remplacée, mettre à jour les constantes contenant encore son ancien handle. Les règles de propriété sont détaillées dans {link}.' concepts.shaders.binding.reference.link: Gestion des ressources -concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: "Lecture d’éléments structurés de type {t} dans le shader" -concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: "Lecture et écriture d’éléments structurés de type {t} dans le shader" +concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: 'Lecture d’éléments structurés de type {t} dans le shader' +concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: 'Lecture et écriture d’éléments structurés de type {t} dans le shader' concepts.shaders.binding.table.headings.access: Accès prévu -concepts.shaders.binding.table.headings.cHandle: "Handle C#" +concepts.shaders.binding.table.headings.cHandle: 'Handle C#' concepts.shaders.binding.table.headings.slangFieldType: Type de champ Slang -concepts.shaders.binding.table.samplerHandle.access: "État d’échantillonnage des textures" -concepts.shaders.binding.table.textureSampledHandle.access: "Lecture de textures" -concepts.shaders.binding.table.textureStorageHandle.access: "Lecture et écriture de textures de stockage" -concepts.shaders.binding.title: "Constantes et handles de ressources" -concepts.shaders.compilation.description: "{zenithCompiler} compile un point d’entrée Slang en {shaderDesc}. {graphicsApi} détermine la cible : DXIL pour DirectX 12, bibliothèque Metal pour Metal, SPIR-V pour Vulkan." -concepts.shaders.compilation.details: "Avec un contexte graphique nommé {context} déjà créé, compiler le shader du triangle à partir de la copie placée à côté de l’exécutable :" -concepts.shaders.compilation.guidance: "Le nom de point d’entrée {vSMain} doit correspondre à la déclaration dans le fichier de shader. Compiler les shaders et créer les pipelines à l’initialisation, puis réutiliser les pipelines pendant le rendu. Les objets shader peuvent être libérés une fois le pipeline créé, comme dans le tutoriel {link}." +concepts.shaders.binding.table.samplerHandle.access: 'État d’échantillonnage des textures' +concepts.shaders.binding.table.textureSampledHandle.access: 'Lecture de textures' +concepts.shaders.binding.table.textureStorageHandle.access: 'Lecture et écriture de textures de stockage' +concepts.shaders.binding.title: 'Constantes et handles de ressources' +concepts.shaders.compilation.description: '{zenithCompiler} compile un point d’entrée Slang en {shaderDesc}. {graphicsApi} détermine la cible : DXIL pour DirectX 12, bibliothèque Metal pour Metal, SPIR-V pour Vulkan.' +concepts.shaders.compilation.details: 'Avec un contexte graphique nommé {context} déjà créé, compiler le shader du triangle à partir de la copie placée à côté de l’exécutable :' +concepts.shaders.compilation.guidance: 'Le nom de point d’entrée {vSMain} doit correspondre à la déclaration dans le fichier de shader. Compiler les shaders et créer les pipelines à l’initialisation, puis réutiliser les pipelines pendant le rendu. Les objets shader peuvent être libérés une fois le pipeline créé, comme dans le tutoriel {link}.' concepts.shaders.compilation.guidance.link: Premier triangle -concepts.shaders.compilation.title: "Compilation des shaders" -concepts.shaders.description: "Les déclarations C# et Slang doivent s’accorder sur l’emplacement de chaque valeur et sur son accès par le shader. Les dispositions d’entrée décrivent les attributs de sommets ; les déclarations de tampons dans les shaders décrivent les paramètres et les tableaux ; les handles identifient les ressources utilisées par le shader." -concepts.shaders.dispatch.description: "{dispatch} indique le nombre de groupes de threads à exécuter. L’exemple de calcul déclare {numthreads} : chaque groupe contient donc 16 × 16 threads. Pour couvrir l’image, diviser sa largeur et sa hauteur par 16, puis arrondir chaque résultat à l’entier supérieur. Une image de 17 × 19 pixels demande ainsi 2 × 2 groupes. Le shader vérifie les coordonnées de chaque thread et ignore ceux qui sont hors de l’image." -concepts.shaders.dispatch.details: "La taille de groupe déclarée est disponible dans {shaderDescThreadGroupSize} et permet de calculer le nombre de groupes à transmettre à {dispatch}. Le calcul complet figure dans {computeShaderRendererCs}. Les accès ultérieurs à l’image produite doivent respecter les conditions décrites dans {link}." +concepts.shaders.compilation.title: 'Compilation des shaders' +concepts.shaders.description: 'Les déclarations C# et Slang doivent s’accorder sur l’emplacement de chaque valeur et sur son accès par le shader. Les dispositions d’entrée décrivent les attributs de sommets ; les déclarations de tampons dans les shaders décrivent les paramètres et les tableaux ; les handles identifient les ressources utilisées par le shader.' +concepts.shaders.dispatch.description: '{dispatch} indique le nombre de groupes de threads à exécuter. L’exemple de calcul déclare {numthreads} : chaque groupe contient donc 16 × 16 threads. Pour couvrir l’image, diviser sa largeur et sa hauteur par 16, puis arrondir chaque résultat à l’entier supérieur. Une image de 17 × 19 pixels demande ainsi 2 × 2 groupes. Le shader vérifie les coordonnées de chaque thread et ignore ceux qui sont hors de l’image.' +concepts.shaders.dispatch.details: 'La taille de groupe déclarée est disponible dans {shaderDescThreadGroupSize} et permet de calculer le nombre de groupes à transmettre à {dispatch}. Le calcul complet figure dans {computeShaderRendererCs}. Les accès ultérieurs à l’image produite doivent respecter les conditions décrites dans {link}.' concepts.shaders.dispatch.details.link: Synchronisation -concepts.shaders.dispatch.title: "Groupes de threads" -concepts.shaders.layout.context: "Les {link} illustrent cette organisation avec les dimensions de l’image et deux handles de textures. Des décalages explicites indiquent le début de chaque champ. La déclaration utilise {systemRuntimeInteropServices} et {zenithNET} :" -concepts.shaders.layout.context.link: "constantes C# de l’exemple de calcul" -concepts.shaders.layout.description: "Pour les sommets, {inputLayout} décrit le format, le décalage et la sémantique de chaque attribut, ainsi que le pas entre sommets. Dans le triangle, une position {float3} précède une couleur {float4} : la couleur commence au décalage de 12 octets et chaque sommet occupe 28 octets. {inputLayoutAdd} calcule cette disposition compacte à partir des formats des éléments. Si la structure C# contient du remplissage, les décalages et le pas doivent en tenir compte." -concepts.shaders.layout.details: "Les tampons de constantes contiennent des paramètres de shader, et les tampons structurés des tableaux d’éléments typés. Leur disposition suit les déclarations Slang, et non {inputLayout}. Les décalages des champs C#, les tailles des éléments et le remplissage doivent correspondre à la disposition mémoire du shader compilé. Un type C# non managé peut être copié sous forme d’octets, mais sa disposition mémoire ne correspond pas nécessairement à celle attendue par le shader : un {float3} compact dans un sommet peut nécessiter un autre alignement dans un tampon de shader." -concepts.shaders.layout.guidance: "Les paramètres de shader peuvent contenir des handles de ressources en plus des valeurs ordinaires. Un handle désigne une mémoire déjà allouée : le copier dans un tampon de constantes ne copie donc pas le contenu de la ressource." -concepts.shaders.layout.notes: "La déclaration correspondante dans {computeShaderSlang} est :" -concepts.shaders.layout.reference: "Les deux dimensions occupent les huit premiers octets, suivis de deux handles de huit octets chacun. L’exemple C# réserve 256 octets pour l’ensemble de l’enregistrement. Pour un autre enregistrement, déterminer la taille à partir de ses propres champs et des contraintes de disposition et d’alignement." -concepts.shaders.layout.title: "Disposition des données" -concepts.shaders.matrices.description: "Le compilateur choisit un stockage des matrices par lignes contiguës. Le {link} place trois valeurs {matrix4x4} aux décalages de 0, 64 et 128 octets. Son {detail} applique {mulVectorMatrix} dans l’ordre modèle, vue et projection." +concepts.shaders.dispatch.title: 'Groupes de threads' +concepts.shaders.layout.context: 'Les {link} illustrent cette organisation avec les dimensions de l’image et deux handles de textures. Des décalages explicites indiquent le début de chaque champ. La déclaration utilise {systemRuntimeInteropServices} et {zenithNET} :' +concepts.shaders.layout.context.link: 'constantes C# de l’exemple de calcul' +concepts.shaders.layout.description: 'Pour les sommets, {inputLayout} décrit le format, le décalage et la sémantique de chaque attribut, ainsi que le pas entre sommets. Dans le triangle, une position {float3} précède une couleur {float4} : la couleur commence au décalage de 12 octets et chaque sommet occupe 28 octets. {inputLayoutAdd} calcule cette disposition compacte à partir des formats des éléments. Si la structure C# contient du remplissage, les décalages et le pas doivent en tenir compte.' +concepts.shaders.layout.details: 'Les tampons de constantes contiennent des paramètres de shader, et les tampons structurés des tableaux d’éléments typés. Leur disposition suit les déclarations Slang, et non {inputLayout}. Les décalages des champs C#, les tailles des éléments et le remplissage doivent correspondre à la disposition mémoire du shader compilé. Un type C# non managé peut être copié sous forme d’octets, mais sa disposition mémoire ne correspond pas nécessairement à celle attendue par le shader : un {float3} compact dans un sommet peut nécessiter un autre alignement dans un tampon de shader.' +concepts.shaders.layout.guidance: 'Les paramètres de shader peuvent contenir des handles de ressources en plus des valeurs ordinaires. Un handle désigne une mémoire déjà allouée : le copier dans un tampon de constantes ne copie donc pas le contenu de la ressource.' +concepts.shaders.layout.notes: 'La déclaration correspondante dans {computeShaderSlang} est :' +concepts.shaders.layout.reference: 'Les deux dimensions occupent les huit premiers octets, suivis de deux handles de huit octets chacun. L’exemple C# réserve 256 octets pour l’ensemble de l’enregistrement. Pour un autre enregistrement, déterminer la taille à partir de ses propres champs et des contraintes de disposition et d’alignement.' +concepts.shaders.layout.title: 'Disposition des données' +concepts.shaders.matrices.description: 'Le compilateur choisit un stockage des matrices par lignes contiguës. Le {link} place trois valeurs {matrix4x4} aux décalages de 0, 64 et 128 octets. Son {detail} applique {mulVectorMatrix} dans l’ordre modèle, vue et projection.' concepts.shaders.matrices.description.detail: shader concepts.shaders.matrices.description.link: moteur de rendu du cube en rotation -concepts.shaders.matrices.details: "L’ordre de stockage définit la disposition des éléments de matrice en mémoire ; l’ordre de multiplication définit la transformation. Les conventions C# et Slang doivent correspondre." -concepts.shaders.matrices.title: "Conventions matricielles" +concepts.shaders.matrices.details: 'L’ordre de stockage définit la disposition des éléments de matrice en mémoire ; l’ordre de multiplication définit la transformation. Les conventions C# et Slang doivent correspondre.' +concepts.shaders.matrices.title: 'Conventions matricielles' concepts.shaders.title: Données de shaders et liaison -concepts.synchronization.backends.description: "DirectX 12 et Vulkan encodent les transitions de texture sous forme de changements de layout et d’accès. L’implémentation de {transition} dans Zenith.NET n’effectue pas d’opération équivalente sur Metal. Le backend Metal regroupe les commandes dans des encodeurs de rendu et de calcul, puis insère des barrières de visibilité à la fermeture d’un encodeur. Les opérations dépendantes dans un même encodeur, comme deux calculs successifs, utilisent des appels explicites à {barrier}." -concepts.synchronization.backends.details: "Dans l’{link}, l’ouverture de la passe de rendu ferme l’encodeur de calcul et rend sa sortie visible aux commandes graphiques. Deux calculs successifs restent en revanche dans le même encodeur. Leur dépendance exige donc une barrière, même si une transition de texture est enregistrée entre eux. Les séquences de commandes portables doivent ainsi tenir compte des dépendances d’accès autant que des layouts de texture." +concepts.synchronization.backends.description: 'DirectX 12 et Vulkan encodent les transitions de texture sous forme de changements de layout et d’accès. L’implémentation de {transition} dans Zenith.NET n’effectue pas d’opération équivalente sur Metal. Le backend Metal regroupe les commandes dans des encodeurs de rendu et de calcul, puis insère des barrières de visibilité à la fermeture d’un encodeur. Les opérations dépendantes dans un même encodeur, comme deux calculs successifs, utilisent des appels explicites à {barrier}.' +concepts.synchronization.backends.details: 'Dans l’{link}, l’ouverture de la passe de rendu ferme l’encodeur de calcul et rend sa sortie visible aux commandes graphiques. Deux calculs successifs restent en revanche dans le même encodeur. Leur dépendance exige donc une barrière, même si une transition de texture est enregistrée entre eux. Les séquences de commandes portables doivent ainsi tenir compte des dépendances d’accès autant que des layouts de texture.' concepts.synchronization.backends.details.link: exemple de calcul -concepts.synchronization.backends.title: "Comportement des backends" -concepts.synchronization.barriers.context: "Choisir des étapes qui couvrent les accès concernés et sont prises en charge par la file. {barrierStagesAll} inclut toutes les étapes disponibles ; une sélection plus restreinte convient lorsque la dépendance ne concerne que certaines d’entre elles." -concepts.synchronization.barriers.description: "Considérons deux calculs enregistrés dans le même tampon de commandes : le premier écrit des données de simulation, le second les lit. Une barrière entre les deux garantit que le second voit les écritures achevées. Pour un tampon de stockage, elle ordonne les accès sans transition de layout de texture :" -concepts.synchronization.barriers.details: "Le premier argument indique les étapes qui ont produit les données ; le second indique celles qui vont les utiliser. Ensemble, ils décrivent l’ordre d’exécution et la visibilité mémoire nécessaires entre les deux calculs." -concepts.synchronization.barriers.guidance: "La {link} applique ce principe entre les étapes de simulation. Chaque barrière suit le calcul qui produit les données et précède celui qui les utilise." +concepts.synchronization.backends.title: 'Comportement des backends' +concepts.synchronization.barriers.context: 'Choisir des étapes qui couvrent les accès concernés et sont prises en charge par la file. {barrierStagesAll} inclut toutes les étapes disponibles ; une sélection plus restreinte convient lorsque la dépendance ne concerne que certaines d’entre elles.' +concepts.synchronization.barriers.description: 'Considérons deux calculs enregistrés dans le même tampon de commandes : le premier écrit des données de simulation, le second les lit. Une barrière entre les deux garantit que le second voit les écritures achevées. Pour un tampon de stockage, elle ordonne les accès sans transition de layout de texture :' +concepts.synchronization.barriers.details: 'Le premier argument indique les étapes qui ont produit les données ; le second indique celles qui vont les utiliser. Ensemble, ils décrivent l’ordre d’exécution et la visibilité mémoire nécessaires entre les deux calculs.' +concepts.synchronization.barriers.guidance: 'La {link} applique ce principe entre les étapes de simulation. Chaque barrière suit le calcul qui produit les données et précède celui qui les utilise.' concepts.synchronization.barriers.guidance.link: simulation FluidTank -concepts.synchronization.barriers.title: "Barrières de pipeline" -concepts.synchronization.dependencies.description: "Pour chaque ressource, repérer les accès qui portent sur les mêmes données. Si l’un d’eux écrit, préserver l’ordre requis entre eux. Deux lectures ne sont pas en conflit, même si les contraintes de layout et de présentation continuent de s’appliquer. Les mises à jour CPU et la libération des ressources doivent aussi attendre que le GPU ait fini d’utiliser la mémoire concernée." -concepts.synchronization.dependencies.details: "Le mécanisme dépend du lieu d’exécution des opérations :" -concepts.synchronization.dependencies.guidance: "Un traitement peut nécessiter plusieurs mécanismes. Une texture produite sur une autre file demande par exemple une dépendance entre soumissions et le layout adapté à son prochain usage. Ces opérations ne nécessitent de bloquer le CPU que si celui-ci doit lui-même accéder aux données ou libérer leur mémoire." +concepts.synchronization.barriers.title: 'Barrières de pipeline' +concepts.synchronization.dependencies.description: 'Pour chaque ressource, repérer les accès qui portent sur les mêmes données. Si l’un d’eux écrit, préserver l’ordre requis entre eux. Deux lectures ne sont pas en conflit, même si les contraintes de layout et de présentation continuent de s’appliquer. Les mises à jour CPU et la libération des ressources doivent aussi attendre que le GPU ait fini d’utiliser la mémoire concernée.' +concepts.synchronization.dependencies.details: 'Le mécanisme dépend du lieu d’exécution des opérations :' +concepts.synchronization.dependencies.guidance: 'Un traitement peut nécessiter plusieurs mécanismes. Une texture produite sur une autre file demande par exemple une dépendance entre soumissions et le layout adapté à son prochain usage. Ces opérations ne nécessitent de bloquer le CPU que si celui-ci doit lui-même accéder aux données ou libérer leur mémoire.' concepts.synchronization.dependencies.table.cpuAccess.mechanism: Appeler {wait} sur la valeur d’achèvement pertinente. -concepts.synchronization.dependencies.table.cpuAccess.situation: "Un accès CPU ou une libération de ressource dépend de la fin du travail GPU" -concepts.synchronization.dependencies.table.crossQueue.mechanism: "Transmettre la valeur {timelineValue} du producteur à l’appel {submit} du consommateur." -concepts.synchronization.dependencies.table.crossQueue.situation: "Une file utilise des données produites sur une autre file" +concepts.synchronization.dependencies.table.cpuAccess.situation: 'Un accès CPU ou une libération de ressource dépend de la fin du travail GPU' +concepts.synchronization.dependencies.table.crossQueue.mechanism: 'Transmettre la valeur {timelineValue} du producteur à l’appel {submit} du consommateur.' +concepts.synchronization.dependencies.table.crossQueue.situation: 'Une file utilise des données produites sur une autre file' concepts.synchronization.dependencies.table.headings.mechanism: Mécanisme concepts.synchronization.dependencies.table.headings.situation: Situation -concepts.synchronization.dependencies.table.layoutChange.mechanism: "{commandBufferTransition} avec ses layouts précédent et suivant." +concepts.synchronization.dependencies.table.layoutChange.mechanism: '{commandBufferTransition} avec ses layouts précédent et suivant.' concepts.synchronization.dependencies.table.layoutChange.situation: Une sous-ressource de texture modifie sa façon d’être utilisée -concepts.synchronization.dependencies.table.pipelineStages.mechanism: "{commandBufferBarrier} avec les étapes productrice et consommatrice." +concepts.synchronization.dependencies.table.pipelineStages.mechanism: '{commandBufferBarrier} avec les étapes productrice et consommatrice.' concepts.synchronization.dependencies.table.pipelineStages.situation: Étapes GPU dépendantes dans un flux de commandes -concepts.synchronization.dependencies.title: "Dépendances d’accès" -concepts.synchronization.description: "La synchronisation fixe l’ordre dans lequel les opérations accèdent aux données partagées et garantit que les suivantes voient les résultats dont elles ont besoin. Dans une dépendance entre écriture et lecture, l’opération qui écrit produit les données et celle qui lit les consomme. Les barrières et les transitions de texture coordonnent les accès GPU ; les lignes de temps relient les soumissions et permettent au CPU d’attendre la fin du travail GPU." -concepts.synchronization.layouts.context: "Utiliser {undefined} comme layout précédent lorsque le contenu peut être abandonné, par exemple pour une nouvelle image ou un attachement entièrement réinitialisé. Pour conserver le contenu afin de le charger, de l’échantillonner ou de l’accumuler, utiliser le layout de l’accès précédent." -concepts.synchronization.layouts.description: "Les indicateurs d’usage d’une texture déclarent ses rôles autorisés. {textureLayout} décrit l’accès à une sous-ressource à un moment donné de la séquence de commandes. Cette sous-ressource est identifiée par un niveau de mip et une couche de tableau. Lorsque l’accès change, enregistrer une transition. Par exemple, l’exemple de calcul écrit sa texture de sortie dans le layout {storage}, puis la prépare à être échantillonnée dans une passe graphique :" -concepts.synchronization.layouts.details: "{outputTexture} a l’usage {sampledStorage}, et la sous-ressource retenue est en {storage}. {default} sélectionne le niveau mip 0 et la couche 0. Les autres niveaux et couches ne sont pas modifiés." -concepts.synchronization.layouts.guidance: "Pour {transition}, fournir le layout de l’utilisation précédente de la sous-ressource. L’application suit cet état lorsqu’elle enregistre les commandes et transmet les textures entre étapes de rendu." -concepts.synchronization.layouts.title: "Layouts de texture" -concepts.synchronization.readback.description: "{isCompleted} indique la fin du travail GPU. Un transfert enregistré depuis le GPU comporte une étape supplémentaire : copier les données de la mémoire de lecture interne vers la destination de l’application." -concepts.synchronization.readback.details: "{commandBufferDownload} enregistre la copie GPU vers cette mémoire interne. Après la fin de la soumission, la bibliothèque effectue la copie CPU lorsqu’elle récupère le tampon de commandes terminé. Appeler {wait} sur la valeur de soumission de ce transfert attend le GPU et traite les tampons terminés de cette file, ce qui achève les deux étapes. Conserver la mémoire de destination et maintenir épinglée toute mémoire managée jusqu’au retour de l’appel." -concepts.synchronization.readback.guidance: "Interroger seulement {isCompleted} n’effectue pas la copie CPU finale. Attendre une autre file ne récupère pas non plus les tampons terminés de la file responsable du transfert. L’article {link} explique quand les transferts utilisent un accès direct à la mémoire ou un stockage intermédiaire." +concepts.synchronization.dependencies.title: 'Dépendances d’accès' +concepts.synchronization.description: 'La synchronisation fixe l’ordre dans lequel les opérations accèdent aux données partagées et garantit que les suivantes voient les résultats dont elles ont besoin. Dans une dépendance entre écriture et lecture, l’opération qui écrit produit les données et celle qui lit les consomme. Les barrières et les transitions de texture coordonnent les accès GPU ; les lignes de temps relient les soumissions et permettent au CPU d’attendre la fin du travail GPU.' +concepts.synchronization.layouts.context: 'Utiliser {undefined} comme layout précédent lorsque le contenu peut être abandonné, par exemple pour une nouvelle image ou un attachement entièrement réinitialisé. Pour conserver le contenu afin de le charger, de l’échantillonner ou de l’accumuler, utiliser le layout de l’accès précédent.' +concepts.synchronization.layouts.description: 'Les indicateurs d’usage d’une texture déclarent ses rôles autorisés. {textureLayout} décrit l’accès à une sous-ressource à un moment donné de la séquence de commandes. Cette sous-ressource est identifiée par un niveau de mip et une couche de tableau. Lorsque l’accès change, enregistrer une transition. Par exemple, l’exemple de calcul écrit sa texture de sortie dans le layout {storage}, puis la prépare à être échantillonnée dans une passe graphique :' +concepts.synchronization.layouts.details: '{outputTexture} a l’usage {sampledStorage}, et la sous-ressource retenue est en {storage}. {default} sélectionne le niveau mip 0 et la couche 0. Les autres niveaux et couches ne sont pas modifiés.' +concepts.synchronization.layouts.guidance: 'Pour {transition}, fournir le layout de l’utilisation précédente de la sous-ressource. L’application suit cet état lorsqu’elle enregistre les commandes et transmet les textures entre étapes de rendu.' +concepts.synchronization.layouts.title: 'Layouts de texture' +concepts.synchronization.readback.description: '{isCompleted} indique la fin du travail GPU. Un transfert enregistré depuis le GPU comporte une étape supplémentaire : copier les données de la mémoire de lecture interne vers la destination de l’application.' +concepts.synchronization.readback.details: '{commandBufferDownload} enregistre la copie GPU vers cette mémoire interne. Après la fin de la soumission, la bibliothèque effectue la copie CPU lorsqu’elle récupère le tampon de commandes terminé. Appeler {wait} sur la valeur de soumission de ce transfert attend le GPU et traite les tampons terminés de cette file, ce qui achève les deux étapes. Conserver la mémoire de destination et maintenir épinglée toute mémoire managée jusqu’au retour de l’appel.' +concepts.synchronization.readback.guidance: 'Interroger seulement {isCompleted} n’effectue pas la copie CPU finale. Attendre une autre file ne récupère pas non plus les tampons terminés de la file responsable du transfert. L’article {link} explique quand les transferts utilisent un accès direct à la mémoire ou un stockage intermédiaire.' concepts.synchronization.readback.guidance.link: Gestion des ressources -concepts.synchronization.readback.title: "Achèvement de la lecture CPU" -concepts.synchronization.reuse.description: "Le triangle attend la fin de chaque image avant de réutiliser ses données. Pour faire chevaucher le traitement de plusieurs images, réserver à chacune des données modifiables distinctes et suivre le moment où leur mémoire redevient disponible. Avant de modifier des données, attendre les accès GPU en cours aux mêmes octets ; avant de libérer une ressource, attendre toutes ses utilisations en cours." -concepts.synchronization.reuse.details: "Le redimensionnement et l’arrêt suivent la même règle : empêcher les nouveaux accès, attendre la fin des accès en cours, puis remplacer ou libérer les ressources. Respecter cet ordre avant {swapChainResize} ou avant de libérer les ressources ou le contexte. Le triangle attend déjà la fin de chaque image et peut donc redimensionner entre les rappels." -concepts.synchronization.reuse.guidance: "Après la présentation, {swapChainPresent} signale un point d’achèvement sur la file graphique et l’attend. Le triangle attend donc lors de la présentation même si l’attente explicite de sa soumission est retirée. Le travail soumis indépendamment à d’autres files demande son propre suivi d’achèvement." -concepts.synchronization.reuse.title: "Réutilisation des ressources" -concepts.synchronization.timelines.context: "Si le CPU doit lire le résultat, écraser les données partagées ou libérer les ressources après le consommateur, attendre cette soumission :" -concepts.synchronization.timelines.description: "Une ligne de temps repère les achèvements par valeurs croissantes. {submit} renvoie une {timelineValue} associant la ligne de temps à la valeur de soumission. Les champs numériques {value} de lignes distinctes ne se comparent pas directement." -concepts.synchronization.timelines.details: "Soient {producer} et {consumer}, deux tampons enregistrés sur des files du même contexte, le second utilisant les données du premier. Leur soumission exprime cette dépendance :" -concepts.synchronization.timelines.guidance: "La file consommatrice attend la valeur d’achèvement fournie avant d’exécuter ses commandes. Le CPU peut continuer sans appeler {producedWait}. Conserver les ressources partagées jusqu’à la fin de {consumed}, et enregistrer les transitions de texture requises par l’accès du consommateur." -concepts.synchronization.timelines.notes: "La valeur renvoyée par {queueTimelineSignal} peut elle aussi être attendue avec {wait} ou servir de dépendance à une autre file. {signal} place ce point d’achèvement après le travail déjà soumis ; le GPU l’atteint une fois ce travail terminé." -concepts.synchronization.timelines.title: "Lignes de temps et dépendances entre files" +concepts.synchronization.readback.title: 'Achèvement de la lecture CPU' +concepts.synchronization.reuse.description: 'Le triangle attend la fin de chaque image avant de réutiliser ses données. Pour faire chevaucher le traitement de plusieurs images, réserver à chacune des données modifiables distinctes et suivre le moment où leur mémoire redevient disponible. Avant de modifier des données, attendre les accès GPU en cours aux mêmes octets ; avant de libérer une ressource, attendre toutes ses utilisations en cours.' +concepts.synchronization.reuse.details: 'Le redimensionnement et l’arrêt suivent la même règle : empêcher les nouveaux accès, attendre la fin des accès en cours, puis remplacer ou libérer les ressources. Respecter cet ordre avant {swapChainResize} ou avant de libérer les ressources ou le contexte. Le triangle attend déjà la fin de chaque image et peut donc redimensionner entre les rappels.' +concepts.synchronization.reuse.guidance: 'Après la présentation, {swapChainPresent} signale un point d’achèvement sur la file graphique et l’attend. Le triangle attend donc lors de la présentation même si l’attente explicite de sa soumission est retirée. Le travail soumis indépendamment à d’autres files demande son propre suivi d’achèvement.' +concepts.synchronization.reuse.title: 'Réutilisation des ressources' +concepts.synchronization.timelines.context: 'Si le CPU doit lire le résultat, écraser les données partagées ou libérer les ressources après le consommateur, attendre cette soumission :' +concepts.synchronization.timelines.description: 'Une ligne de temps repère les achèvements par valeurs croissantes. {submit} renvoie une {timelineValue} associant la ligne de temps à la valeur de soumission. Les champs numériques {value} de lignes distinctes ne se comparent pas directement.' +concepts.synchronization.timelines.details: 'Soient {producer} et {consumer}, deux tampons enregistrés sur des files du même contexte, le second utilisant les données du premier. Leur soumission exprime cette dépendance :' +concepts.synchronization.timelines.guidance: 'La file consommatrice attend la valeur d’achèvement fournie avant d’exécuter ses commandes. Le CPU peut continuer sans appeler {producedWait}. Conserver les ressources partagées jusqu’à la fin de {consumed}, et enregistrer les transitions de texture requises par l’accès du consommateur.' +concepts.synchronization.timelines.notes: 'La valeur renvoyée par {queueTimelineSignal} peut elle aussi être attendue avec {wait} ou servir de dépendance à une autre file. {signal} place ce point d’achèvement après le travail déjà soumis ; le GPU l’atteint une fois ce travail terminé.' +concepts.synchronization.timelines.title: 'Lignes de temps et dépendances entre files' concepts.synchronization.title: Synchronisation home.actions.reference: Consulter l’API home.actions.tutorial: Commencer par un triangle -home.entries.description: "Tutoriels, exemples et référence API" -home.entries.label: "Rubriques de la documentation" +home.entries.description: 'Tutoriels, exemples et référence API' +home.entries.label: 'Rubriques de la documentation' home.entries.reference.action: Explorer l’API home.entries.reference.category: Référence -home.entries.reference.description: "Consulter les types, membres et déclarations de l’API" +home.entries.reference.description: 'Consulter les types, membres et déclarations de l’API' home.entries.reference.title: Référence de l’API home.entries.samples.action: Parcourir les exemples home.entries.samples.category: Exemples -home.entries.samples.description: "Des exemples exécutables de techniques graphiques et de calcul" +home.entries.samples.description: 'Des exemples exécutables de techniques graphiques et de calcul' home.entries.samples.title: Exemples -home.entries.title: "Documentation" +home.entries.title: 'Documentation' home.entries.tutorial.action: Démarrer le tutoriel home.entries.tutorial.category: Tutoriel -home.entries.tutorial.description: "D’un projet vide au premier triangle à l’écran" +home.entries.tutorial.description: 'D’un projet vide au premier triangle à l’écran' home.entries.tutorial.title: Premier triangle -home.introduction.accent: "avec .NET" -home.introduction.description: "Zenith.NET fournit une API commune pour le rendu et le calcul avec DirectX, Metal et Vulkan" -home.introduction.title: "Le rendu multiplateforme{lineBreak}{accent}" -home.meta.description: "Développez des applications graphiques et de calcul multiplateformes avec .NET et une API commune pour DirectX, Metal et Vulkan" -home.scene.description: "Géométrie en rotation interactive. Faire glisser ou utiliser les touches fléchées pour changer le point de vue." +home.introduction.accent: 'avec .NET' +home.introduction.description: 'Zenith.NET fournit une API commune pour le rendu et le calcul avec DirectX, Metal et Vulkan' +home.introduction.title: 'Le rendu multiplateforme{lineBreak}{accent}' +home.meta.description: 'Développez des applications graphiques et de calcul multiplateformes avec .NET et une API commune pour DirectX, Metal et Vulkan' +home.scene.description: 'Géométrie en rotation interactive. Faire glisser ou utiliser les touches fléchées pour changer le point de vue.' home.scene.label: Affichage de la géométrie home.scene.surface: Surface home.scene.wireframe: Fil de fer home.title: RHI moderne pour .NET -learning.concepts.description: "Choisir les usages des ressources, décrire les données des shaders et coordonner l’exécution GPU" -learning.concepts.execution.description: "Enregistrement, soumission et durée de vie des ressources" -learning.concepts.platforms.description: "Présentation native et contrôles de rendu UI" -learning.concepts.resources.description: "Usages des ressources, placement mémoire et vues" -learning.concepts.shaders.description: "Conventions de disposition et de liaison entre C# et Slang" -learning.concepts.synchronization.description: "Dépendances, visibilité et achèvement" +learning.concepts.description: 'Choisir les usages des ressources, décrire les données des shaders et coordonner l’exécution GPU' +learning.concepts.execution.description: 'Enregistrement, soumission et durée de vie des ressources' +learning.concepts.platforms.description: 'Présentation native et contrôles de rendu UI' +learning.concepts.resources.description: 'Usages des ressources, placement mémoire et vues' +learning.concepts.shaders.description: 'Conventions de disposition et de liaison entre C# et Slang' +learning.concepts.synchronization.description: 'Dépendances, visibilité et achèvement' learning.concepts.title: Concepts fondamentaux -learning.description: "Commencez par le tutoriel du triangle pour créer votre première application. Les articles de fond expliquent ensuite la gestion des ressources, les données des shaders et la synchronisation. Les exemples permettent d’aborder séparément chaque technique." +learning.description: 'Commencez par le tutoriel du triangle pour créer votre première application. Les articles de fond expliquent ensuite la gestion des ressources, les données des shaders et la synchronisation. Les exemples permettent d’aborder séparément chaque technique.' learning.entries.samples.action: Parcourir les exemples -learning.entries.samples.description: "Implémentations C# et Slang de géométrie, calcul, requêtes de rayons et mesh shading" +learning.entries.samples.description: 'Implémentations C# et Slang de géométrie, calcul, requêtes de rayons et mesh shading' learning.entries.tutorial.action: Ouvrir le tutoriel -learning.entries.tutorial.description: "Une application console qui ouvre une fenêtre et rend un triangle" -learning.meta.description: "Tutoriels et concepts du modèle de programmation de Zenith.NET" +learning.entries.tutorial.description: 'Une application console qui ouvre une fenêtre et rend un triangle' +learning.meta.description: 'Tutoriels et concepts du modèle de programmation de Zenith.NET' learning.title: Apprendre -reference.description: "Référence des ressources, commandes et intégrations de plateforme" -reference.entries.commands.description: "Commandes graphiques, de calcul et de transfert" -reference.entries.commands.label: "Enregistrer des commandes" -reference.entries.context.description: "Création de ressources GPU pour le backend sélectionné" +reference.description: 'Référence des ressources, commandes et intégrations de plateforme' +reference.entries.commands.description: 'Commandes graphiques, de calcul et de transfert' +reference.entries.commands.label: 'Enregistrer des commandes' +reference.entries.context.description: 'Création de ressources GPU pour le backend sélectionné' reference.entries.context.label: Commencer ici -reference.meta.description: "Espaces de noms, types et membres de Zenith.NET" -reference.navigation.core: "Référence de l’API principale" +reference.meta.description: 'Espaces de noms, types et membres de Zenith.NET' +reference.navigation.core: 'Référence de l’API principale' reference.title: Référence de l’API -samples.computeShader.description: "L’exemple charge l’image {assetsTexturesShokoPng}, la convertit en niveaux de gris par un calcul GPU et affiche la texture de sortie. La conversion n’a lieu qu’une fois ; les images suivantes affichent le même résultat. Le moteur de rendu montre comment lier des textures échantillonnées et accessibles en écriture, arrondir le nombre de groupes de threads à l’entier supérieur pour couvrir l’image et vérifier ses limites dans le shader." -samples.computeShader.details: "{computeShaderRendererCs} · {computeShaderSlang}" +samples.computeShader.description: 'L’exemple charge l’image {assetsTexturesShokoPng}, la convertit en niveaux de gris par un calcul GPU et affiche la texture de sortie. La conversion n’a lieu qu’une fois ; les images suivantes affichent le même résultat. Le moteur de rendu montre comment lier des textures échantillonnées et accessibles en écriture, arrondir le nombre de groupes de threads à l’entier supérieur pour couvrir l’image et vérifier ses limites dans le shader.' +samples.computeShader.details: '{computeShaderRendererCs} · {computeShaderSlang}' samples.computeShader.title: Shader de calcul -samples.cube.description: "Le cube ajoute le dessin indexé, les matrices de modèle, de vue et de projection dans un tampon de constantes, ainsi que le test de profondeur. Sa texture de profondeur et de stencil {d32FloatS8UInt} est recréée au redimensionnement." -samples.cube.details: "{spinningCubeRendererCs} · {spinningCubeSlang}" +samples.cube.description: 'Le cube ajoute le dessin indexé, les matrices de modèle, de vue et de projection dans un tampon de constantes, ainsi que le test de profondeur. Sa texture de profondeur et de stencil {d32FloatS8UInt} est recréée au redimensionnement.' +samples.cube.details: '{spinningCubeRendererCs} · {spinningCubeSlang}' samples.cube.title: Cube en rotation -samples.description: "Chaque exemple associe un moteur de rendu C# à son shader Slang et se concentre sur une technique. La configuration complète de l’application et la séquence de rendu sont décrites dans {link}." +samples.description: 'Chaque exemple associe un moteur de rendu C# à son shader Slang et se concentre sur une technique. La configuration complète de l’application et la séquence de rendu sont décrites dans {link}.' samples.description.link: Premier triangle -samples.execution.description: "Exécutez le projet {link} et choisissez un exemple dans le menu de la console." +samples.execution.description: 'Exécutez le projet {link} et choisissez un exemple dans le menu de la console.' samples.execution.description.link: ZenithTutorials -samples.execution.title: "Exécution des exemples" -samples.host.description: "{appCs} initialise le contexte, la fenêtre et la chaîne d’échange. À chaque image, l’hôte obtient un tampon de commandes, appelle le moteur choisi, soumet les commandes et présente le résultat. {iRendererCs} définit les opérations de mise à jour, de rendu, de redimensionnement et de libération." -samples.host.details: "Les moteurs de rendu de calcul et de lancer de rayons produisent des textures hors écran. {texturePresenterCs} et {presentTextureSlang} les dessinent dans la texture de sortie courante ; l’hôte commun soumet ensuite les commandes et présente l’image." -samples.host.title: "Hôte et présentation" -samples.indirectDrawing.description: "Le dessin indirect affiche plusieurs instances de cube à partir d’un tampon d’arguments de dessin indexé et d’un tampon structuré de données par instance. Le CPU fournit les arguments et actualise les transformations." -samples.indirectDrawing.details: "{indirectDrawingRendererCs} · {indirectDrawingSlang}" +samples.execution.title: 'Exécution des exemples' +samples.host.description: '{appCs} initialise le contexte, la fenêtre et la chaîne d’échange. À chaque image, l’hôte obtient un tampon de commandes, appelle le moteur choisi, soumet les commandes et présente le résultat. {iRendererCs} définit les opérations de mise à jour, de rendu, de redimensionnement et de libération.' +samples.host.details: 'Les moteurs de rendu de calcul et de lancer de rayons produisent des textures hors écran. {texturePresenterCs} et {presentTextureSlang} les dessinent dans la texture de sortie courante ; l’hôte commun soumet ensuite les commandes et présente l’image.' +samples.host.title: 'Hôte et présentation' +samples.indirectDrawing.description: 'Le dessin indirect affiche plusieurs instances de cube à partir d’un tampon d’arguments de dessin indexé et d’un tampon structuré de données par instance. Le CPU fournit les arguments et actualise les transformations.' +samples.indirectDrawing.details: '{indirectDrawingRendererCs} · {indirectDrawingSlang}' samples.indirectDrawing.title: Dessin indirect -samples.meshShading.description: "Un shader de tâches élimine les instances de sphères non visibles, puis transmet les indices restants au shader de maillage qui produit la géométrie. Le moteur vérifie {contextCapabilitiesMeshShadingSupported} avant de créer le pipeline." -samples.meshShading.details: "{meshShadingRendererCs} · {meshShadingSlang}" +samples.meshShading.description: 'Un shader de tâches élimine les instances de sphères non visibles, puis transmet les indices restants au shader de maillage qui produit la géométrie. Le moteur vérifie {contextCapabilitiesMeshShadingSupported} avant de créer le pipeline.' +samples.meshShading.details: '{meshShadingRendererCs} · {meshShadingSlang}' samples.meshShading.title: Mesh Shading -samples.rayTracing.description: "Cet exemple construit les structures d’accélération de niveau inférieur et supérieur d’un sol et de sphères procédurales, puis effectue des requêtes de rayons directement dans un shader de calcul. Il vérifie {contextCapabilitiesRayTracingSupported} avant l’initialisation." -samples.rayTracing.details: "{rayTracingRendererCs} · {rayTracingSlang}" +samples.rayTracing.description: 'Cet exemple construit les structures d’accélération de niveau inférieur et supérieur d’un sol et de sphères procédurales, puis effectue des requêtes de rayons directement dans un shader de calcul. Il vérifie {contextCapabilitiesRayTracingSupported} avant l’initialisation.' +samples.rayTracing.details: '{rayTracingRendererCs} · {rayTracingSlang}' samples.rayTracing.title: Lancer de rayons samples.title: Exemples -samples.triangle.description: "Le triangle associe un tampon de sommets à la disposition d’entrée correspondante et dessine trois sommets au moyen d’un pipeline graphique." -samples.triangle.details: "{helloTriangleRendererCs} · {helloTriangleSlang} · {link}" +samples.triangle.description: 'Le triangle associe un tampon de sommets à la disposition d’entrée correspondante et dessine trois sommets au moyen d’un pipeline graphique.' +samples.triangle.details: '{helloTriangleRendererCs} · {helloTriangleSlang} · {link}' samples.triangle.details.link: Tutoriel complet samples.triangle.title: Bonjour triangle -samples.workloads.description: "Le {link} du dépôt principal contient des applications plus complètes qui utilisent le code source de la bibliothèque." +samples.workloads.description: 'Le {link} du dépôt principal contient des applications plus complètes qui utilisent le code source de la bibliothèque.' samples.workloads.description.link: répertoire Experiments -samples.workloads.details: "Les applications fenêtrées utilisent les mêmes chemins Windows, macOS et Linux/X11. Les contrôles Avalonia, WinForms, WPF, WinUI/Uno et MAUI sont décrits dans {link}, avec leur cycle d’image et leur code d’implémentation." +samples.workloads.details: 'Les applications fenêtrées utilisent les mêmes chemins Windows, macOS et Linux/X11. Les contrôles Avalonia, WinForms, WPF, WinUI/Uno et MAUI sont décrits dans {link}, avec leur cycle d’image et leur code d’implémentation.' samples.workloads.details.link: Intégration de plateforme -samples.workloads.table.cornellBox.example: "{link}" +samples.workloads.table.cornellBox.example: '{link}' samples.workloads.table.cornellBox.example.link: CornellBox -samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: "Tracé de chemins, débruitage, mappage tonal, agrandissement de l’image et contrôles ImGui. Nécessite la prise en charge du lancer de rayons." -samples.workloads.table.fluidTank.example: "{link}" +samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: 'Tracé de chemins, débruitage, mappage tonal, agrandissement de l’image et contrôles ImGui. Nécessite la prise en charge du lancer de rayons.' +samples.workloads.table.fluidTank.example: '{link}' samples.workloads.table.fluidTank.example.link: FluidTank -samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: "Simulation de fluide par calcul, dépendances entre étapes de simulation et rendu de surface multipasse." +samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: 'Simulation de fluide par calcul, dépendances entre étapes de simulation et rendu de surface multipasse.' samples.workloads.table.headings.example: Exemple -samples.workloads.table.headings.whatItDemonstratesAndRequires: "Techniques et prérequis" -samples.workloads.table.inkCanvas.example: "{link}" +samples.workloads.table.headings.whatItDemonstratesAndRequires: 'Techniques et prérequis' +samples.workloads.table.inkCanvas.example: '{link}' samples.workloads.table.inkCanvas.example.link: InkCanvas samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: Dessin Skia et gestion des entrées dans une fenêtre native. Nécessite le backend et la bibliothèque native Skia pour la plateforme cible. -samples.workloads.table.platformDetection.example: "{link}" +samples.workloads.table.platformDetection.example: '{link}' samples.workloads.table.platformDetection.example.link: PlatformDetection -samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: "Tente de créer un contexte pour chaque backend et rapporte les capacités du périphérique. Un échec est indiqué comme une absence de prise en charge ; il peut provenir du périphérique, du pilote ou d’une dépendance d’exécution manquante." -samples.workloads.title: "Applications complètes" -tutorial.context.description: "Un {graphicsContext} relie l’application au GPU par l’intermédiaire d’un backend et fournit les méthodes de création des ressources de rendu." -tutorial.context.details: "Insérez l’initialisation du contexte {emphasis} :" +samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: 'Tente de créer un contexte pour chaque backend et rapporte les capacités du périphérique. Un échec est indiqué comme une absence de prise en charge ; il peut provenir du périphérique, du pilote ou d’une dépendance d’exécution manquante.' +samples.workloads.title: 'Applications complètes' +tutorial.context.description: 'Un {graphicsContext} relie l’application au GPU par l’intermédiaire d’un backend et fournit les méthodes de création des ressources de rendu.' +tutorial.context.details: 'Insérez l’initialisation du contexte {emphasis} :' tutorial.context.details.emphasis: après les directives using, avant {iWindowWindow} -tutorial.context.guidance: "Chaque branche sélectionne le backend de la plateforme et demande la validation. Les messages de {validationMessage} sont affichés dans la console." -tutorial.context.imports: "Ajoutez les directives using suivantes au début de {programCs} :" -tutorial.context.title: "Contexte graphique" -tutorial.description: "Ce tutoriel part d’un projet console .NET vide pour créer une application qui ouvre une fenêtre et dessine un triangle coloré." -tutorial.details: "Le tutoriel comporte trois étapes de vérification : une fenêtre vide, un fond uni, puis le triangle coloré. Exécutez l’application à chaque étape avant d’ajouter la partie suivante." -tutorial.draw.context: "Les arguments de {draw} sont :" -tutorial.draw.description: "Dans {windowRender}, remplacez {addTheTriangleDrawCommandsHereLater} par ces commandes, entre {beginRenderPass} et {endRenderPass} :" -tutorial.draw.details: "{setPipeline} sélectionne les shaders et l’état de rendu. Cet appel doit précéder la liaison du tampon de sommets, car le backend l’interprète selon la disposition d’entrée du pipeline." -tutorial.draw.guidance: "{setVertexBufferVertexBuffer} lie les données de sommets déjà transférées, à partir du décalage de 0 octet, à l’emplacement d’entrée 0. Celui-ci correspond à l’unique entrée de {inputLayouts}." -tutorial.draw.notes: "Ces appels enregistrent les commandes de dessin. L’appel {submitWait} déjà présent les soumet et attend que le GPU les termine ; {present} demande ensuite l’affichage de l’image achevée. Conservez l’initialisation avec la couleur de fond au début de la passe pour donner un contenu défini à la zone extérieure au triangle." +tutorial.context.guidance: 'Chaque branche sélectionne le backend de la plateforme et demande la validation. Les messages de {validationMessage} sont affichés dans la console.' +tutorial.context.imports: 'Ajoutez les directives using suivantes au début de {programCs} :' +tutorial.context.title: 'Contexte graphique' +tutorial.description: 'Ce tutoriel part d’un projet console .NET vide pour créer une application qui ouvre une fenêtre et dessine un triangle coloré.' +tutorial.details: 'Le tutoriel comporte trois étapes de vérification : une fenêtre vide, un fond uni, puis le triangle coloré. Exécutez l’application à chaque étape avant d’ajouter la partie suivante.' +tutorial.draw.context: 'Les arguments de {draw} sont :' +tutorial.draw.description: 'Dans {windowRender}, remplacez {addTheTriangleDrawCommandsHereLater} par ces commandes, entre {beginRenderPass} et {endRenderPass} :' +tutorial.draw.details: '{setPipeline} sélectionne les shaders et l’état de rendu. Cet appel doit précéder la liaison du tampon de sommets, car le backend l’interprète selon la disposition d’entrée du pipeline.' +tutorial.draw.guidance: '{setVertexBufferVertexBuffer} lie les données de sommets déjà transférées, à partir du décalage de 0 octet, à l’emplacement d’entrée 0. Celui-ci correspond à l’unique entrée de {inputLayouts}.' +tutorial.draw.notes: 'Ces appels enregistrent les commandes de dessin. L’appel {submitWait} déjà présent les soumet et attend que le GPU les termine ; {present} demande ensuite l’affichage de l’image achevée. Conservez l’initialisation avec la couleur de fond au début de la passe pour donner un contenu défini à la zone extérieure au triangle.' tutorial.draw.table.firstInstance.meaning: Commencer la numérotation des instances à zéro. tutorial.draw.table.firstVertex.meaning: Commencer avec le premier sommet dans le tampon. tutorial.draw.table.headings.argument: Argument @@ -362,131 +362,131 @@ tutorial.draw.table.headings.description: Valeur tutorial.draw.table.headings.meaning: Signification tutorial.draw.table.instanceCount.meaning: Dessiner une copie du triangle. tutorial.draw.table.vertexCount.meaning: Lire trois sommets. -tutorial.draw.title: "Commandes de dessin" -tutorial.execution.description: "Compilez et lancez le projet {firstTriangle}." -tutorial.execution.details: "Un triangle doit apparaître sur fond sombre, rouge en haut, vert en bas à droite et bleu en bas à gauche. L’interpolation des couleurs des sommets forme un dégradé continu à l’intérieur." -tutorial.execution.guidance: "Le redimensionnement modifie les dimensions de l’image en pixels, mais les coordonnées des sommets restent identiques. Le viewport les adapte à la nouvelle largeur et à la nouvelle hauteur. Le triangle s’étire donc lorsque le rapport largeur/hauteur de la fenêtre change." -tutorial.execution.title: "Exécution de l’application" -tutorial.frame.commands.context: "Après {endRenderPass}, la seconde transition prépare la sortie pour la présentation. {submit} termine l’enregistrement et soumet le tampon ; {wait} bloque jusqu’à l’achèvement. {present} demande ensuite l’affichage." -tutorial.frame.commands.description: "Une passe de rendu regroupe les opérations de dessin qui écrivent dans les mêmes attachements. Ici, la texture de sortie de la chaîne d’échange reçoit les couleurs produites par le rendu. {colorAttachmentClear} indique que cet attachement doit être initialisé avec une couleur RGBA et que son contenu doit être conservé à la fin de la passe. {beginRenderPass} enregistre le début de la passe avec ces paramètres." -tutorial.frame.commands.details: "La collection contient un attachement de couleur. {null} indique que la passe ne possède pas d’attachement de profondeur et de stencil." -tutorial.frame.commands.guidance: "{beginRenderPass} règle le viewport et le rectangle de découpe sur tout l’attachement. Le viewport convertit les coordonnées de rendu en positions de pixels ; le rectangle de découpe limite la zone où l’écriture est autorisée." -tutorial.frame.commands.title: "Effacement, soumission et présentation" -tutorial.frame.description: "Commencez par remplir la fenêtre d’une couleur de fond. Cette opération s’appelle l’effacement. Lorsque le fond s’affiche, la surface, la soumission et la présentation fonctionnent ensemble ; vous pouvez ajouter les sommets et les shaders du triangle." -tutorial.frame.details: "Silk.NET appelle le rappel de rendu lorsqu’une image doit être produite. L’argument de temps écoulé reste inutilisé et porte le nom {value}. Enregistrez le rappel {emphasis} :" +tutorial.draw.title: 'Commandes de dessin' +tutorial.execution.description: 'Compilez et lancez le projet {firstTriangle}.' +tutorial.execution.details: 'Un triangle doit apparaître sur fond sombre, rouge en haut, vert en bas à droite et bleu en bas à gauche. L’interpolation des couleurs des sommets forme un dégradé continu à l’intérieur.' +tutorial.execution.guidance: 'Le redimensionnement modifie les dimensions de l’image en pixels, mais les coordonnées des sommets restent identiques. Le viewport les adapte à la nouvelle largeur et à la nouvelle hauteur. Le triangle s’étire donc lorsque le rapport largeur/hauteur de la fenêtre change.' +tutorial.execution.title: 'Exécution de l’application' +tutorial.frame.commands.context: 'Après {endRenderPass}, la seconde transition prépare la sortie pour la présentation. {submit} termine l’enregistrement et soumet le tampon ; {wait} bloque jusqu’à l’achèvement. {present} demande ensuite l’affichage.' +tutorial.frame.commands.description: 'Une passe de rendu regroupe les opérations de dessin qui écrivent dans les mêmes attachements. Ici, la texture de sortie de la chaîne d’échange reçoit les couleurs produites par le rendu. {colorAttachmentClear} indique que cet attachement doit être initialisé avec une couleur RGBA et que son contenu doit être conservé à la fin de la passe. {beginRenderPass} enregistre le début de la passe avec ces paramètres.' +tutorial.frame.commands.details: 'La collection contient un attachement de couleur. {null} indique que la passe ne possède pas d’attachement de profondeur et de stencil.' +tutorial.frame.commands.guidance: '{beginRenderPass} règle le viewport et le rectangle de découpe sur tout l’attachement. Le viewport convertit les coordonnées de rendu en positions de pixels ; le rectangle de découpe limite la zone où l’écriture est autorisée.' +tutorial.frame.commands.title: 'Effacement, soumission et présentation' +tutorial.frame.description: 'Commencez par remplir la fenêtre d’une couleur de fond. Cette opération s’appelle l’effacement. Lorsque le fond s’affiche, la surface, la soumission et la présentation fonctionnent ensemble ; vous pouvez ajouter les sommets et les shaders du triangle.' +tutorial.frame.details: 'Silk.NET appelle le rappel de rendu lorsqu’une image doit être produite. L’argument de temps écoulé reste inutilisé et porte le nom {value}. Enregistrez le rappel {emphasis} :' tutorial.frame.details.emphasis: avant {windowRun} -tutorial.frame.target.description: "{graphicsQueueCommandBuffer} renvoie un tampon prêt à enregistrer. L’enregistrement décrit le travail GPU ; l’exécution ne commence qu’après soumission." -tutorial.frame.target.details: "Le layout d’une texture décrit le type d’accès nécessaire à une opération. Le premier appel à {transition} prépare la texture de sortie à servir d’attachement de couleur. Ici, {default} sélectionne le niveau de mip 0 et la couche de tableau 0, soit l’image de base de cette texture. Comme la passe remplit toute l’image avec la couleur de fond, {undefined} autorise l’abandon de son contenu précédent." -tutorial.frame.target.guidance: "Utilisez la texture de sortie courante à chaque image, car la présentation peut faire passer la chaîne d’échange à une autre texture." -tutorial.frame.target.title: "Préparation de la sortie" -tutorial.frame.title: "Première image" -tutorial.geometry.data.description: "Ajoutez le tableau de sommets {emphasis}. L’initialisation des ressources suivantes reste aussi avant ce rappel, dans l’ordre indiqué." +tutorial.frame.target.description: '{graphicsQueueCommandBuffer} renvoie un tampon prêt à enregistrer. L’enregistrement décrit le travail GPU ; l’exécution ne commence qu’après soumission.' +tutorial.frame.target.details: 'Le layout d’une texture décrit le type d’accès nécessaire à une opération. Le premier appel à {transition} prépare la texture de sortie à servir d’attachement de couleur. Ici, {default} sélectionne le niveau de mip 0 et la couche de tableau 0, soit l’image de base de cette texture. Comme la passe remplit toute l’image avec la couleur de fond, {undefined} autorise l’abandon de son contenu précédent.' +tutorial.frame.target.guidance: 'Utilisez la texture de sortie courante à chaque image, car la présentation peut faire passer la chaîne d’échange à une autre texture.' +tutorial.frame.target.title: 'Préparation de la sortie' +tutorial.frame.title: 'Première image' +tutorial.geometry.data.description: 'Ajoutez le tableau de sommets {emphasis}. L’initialisation des ressources suivantes reste aussi avant ce rappel, dans l’ordre indiqué.' tutorial.geometry.data.description.emphasis: avant {windowRender} -tutorial.geometry.data.details: "Chaque entrée construit un {vertex}. Les deux expressions {new} internes donnent sa position {vector3} et sa couleur {vector4}. Les positions définissent les coins supérieur, inférieur droit et inférieur gauche. Le shader de sommets ajoute {w} comme quatrième coordonnée. Avec w = 1, x et y sont des coordonnées normalisées du périphérique : -1 et +1 marquent les bords, 0 le centre, indépendamment des dimensions en pixels." -tutorial.geometry.data.guidance: "Chaque couleur comporte des composantes rouge, verte, bleue et alpha, avec alpha égal à 1. Les trois sommets sont dans le même plan, à z = 0." -tutorial.geometry.data.title: "Positions et couleurs" -tutorial.geometry.description: "Chacun des trois sommets possède une position et une couleur. Le GPU détermine la forme du triangle à partir des positions et interpole les couleurs sur sa surface." -tutorial.geometry.format.description: "Ajoutez la déclaration de sommet {emphasis} :" +tutorial.geometry.data.details: 'Chaque entrée construit un {vertex}. Les deux expressions {new} internes donnent sa position {vector3} et sa couleur {vector4}. Les positions définissent les coins supérieur, inférieur droit et inférieur gauche. Le shader de sommets ajoute {w} comme quatrième coordonnée. Avec w = 1, x et y sont des coordonnées normalisées du périphérique : -1 et +1 marquent les bords, 0 le centre, indépendamment des dimensions en pixels.' +tutorial.geometry.data.guidance: 'Chaque couleur comporte des composantes rouge, verte, bleue et alpha, avec alpha égal à 1. Les trois sommets sont dans le même plan, à z = 0.' +tutorial.geometry.data.title: 'Positions et couleurs' +tutorial.geometry.description: 'Chacun des trois sommets possède une position et une couleur. Le GPU détermine la forme du triangle à partir des positions et interpole les couleurs sur sa surface.' +tutorial.geometry.format.description: 'Ajoutez la déclaration de sommet {emphasis} :' tutorial.geometry.format.description.emphasis: à la fin de {programCs}, après les instructions de nettoyage -tutorial.geometry.format.details: "{file} limite le type au fichier {programCs}, tandis que {layoutKindSequential} conserve l’ordre de déclaration de ses champs. {position} contient trois nombres flottants de 32 bits à partir du décalage de 0 octet ; {color} en contient quatre à partir du décalage de 12 octets. Chaque sommet occupe donc 28 octets. La disposition d’entrée décrira cette organisation pour que le GPU lise correctement les champs." -tutorial.geometry.format.imports: "Ajoutez ces directives using au début de {programCs} pour les types vectoriels et l’attribut de disposition mémoire des structures :" -tutorial.geometry.format.title: "Représentation d’un sommet" -tutorial.geometry.title: "Données de sommets" -tutorial.geometry.upload.context: "{fixed} empêche le ramasse-miettes de déplacer le tableau pendant l’utilisation de son adresse. Pour ce tampon accessible en écriture au CPU, {upload} mappe la mémoire, copie les données, puis termine le mapping avant de retourner. Le tableau ne doit donc rester épinglé que pendant l’appel. Transférez les sommets une seule fois à l’initialisation et conservez le tampon jusqu’à la fin du rendu." -tutorial.geometry.upload.description: "Placez les sommets dans un {buffer} afin que le GPU puisse les lire pendant le dessin. Ajoutez l’allocation et le transfert immédiatement après le tableau :" -tutorial.geometry.upload.details: "{sizeofVertexVerticesLength} représente trois sommets de 28 octets, soit 84 octets. {bufferUsagesVertex} déclare l’accès en entrée de sommets, {cpuWriteOnly} autorise l’initialisation directe par le CPU. Le pas du descripteur indique la taille d’un élément ; la disposition d’entrée précise ensuite chaque attribut." -tutorial.geometry.upload.guidance: "L’allocation n’initialise pas le contenu. {upload} copie le tableau au décalage de destination 0 à partir du pointeur source et du nombre d’octets de la description." -tutorial.geometry.upload.imports: "Dans {programCs}, ajoutez {bufferAlias} aux directives using pour distinguer le type de tampon de Zenith.NET de {systemBuffer}." -tutorial.geometry.upload.notes: "Ajoutez {vertexBufferDispose} juste avant {swapChainDispose} à la fin de {programCs}. Le stockage réservé au GPU et les transferts pour de plus grandes géométries sont présentés dans {link}." +tutorial.geometry.format.details: '{file} limite le type au fichier {programCs}, tandis que {layoutKindSequential} conserve l’ordre de déclaration de ses champs. {position} contient trois nombres flottants de 32 bits à partir du décalage de 0 octet ; {color} en contient quatre à partir du décalage de 12 octets. Chaque sommet occupe donc 28 octets. La disposition d’entrée décrira cette organisation pour que le GPU lise correctement les champs.' +tutorial.geometry.format.imports: 'Ajoutez ces directives using au début de {programCs} pour les types vectoriels et l’attribut de disposition mémoire des structures :' +tutorial.geometry.format.title: 'Représentation d’un sommet' +tutorial.geometry.title: 'Données de sommets' +tutorial.geometry.upload.context: '{fixed} empêche le ramasse-miettes de déplacer le tableau pendant l’utilisation de son adresse. Pour ce tampon accessible en écriture au CPU, {upload} mappe la mémoire, copie les données, puis termine le mapping avant de retourner. Le tableau ne doit donc rester épinglé que pendant l’appel. Transférez les sommets une seule fois à l’initialisation et conservez le tampon jusqu’à la fin du rendu.' +tutorial.geometry.upload.description: 'Placez les sommets dans un {buffer} afin que le GPU puisse les lire pendant le dessin. Ajoutez l’allocation et le transfert immédiatement après le tableau :' +tutorial.geometry.upload.details: '{sizeofVertexVerticesLength} représente trois sommets de 28 octets, soit 84 octets. {bufferUsagesVertex} déclare l’accès en entrée de sommets, {cpuWriteOnly} autorise l’initialisation directe par le CPU. Le pas du descripteur indique la taille d’un élément ; la disposition d’entrée précise ensuite chaque attribut.' +tutorial.geometry.upload.guidance: 'L’allocation n’initialise pas le contenu. {upload} copie le tableau au décalage de destination 0 à partir du pointeur source et du nombre d’octets de la description.' +tutorial.geometry.upload.imports: 'Dans {programCs}, ajoutez {bufferAlias} aux directives using pour distinguer le type de tampon de Zenith.NET de {systemBuffer}.' +tutorial.geometry.upload.notes: 'Ajoutez {vertexBufferDispose} juste avant {swapChainDispose} à la fin de {programCs}. Le stockage réservé au GPU et les transferts pour de plus grandes géométries sont présentés dans {link}.' tutorial.geometry.upload.notes.link: Gestion des ressources -tutorial.geometry.upload.title: "Allocation et transfert du tampon" -tutorial.input.description: "Le GPU doit savoir où se trouvent les attributs de chaque sommet, comme la position et la couleur. La disposition d’entrée indique leur format et leur décalage, ainsi que le pas, la distance en octets entre deux sommets successifs. Ajoutez ce code après la création des shaders :" -tutorial.input.details: "{inputLayoutAdd} place chaque attribut immédiatement après le précédent et ajoute sa taille au pas entre sommets. Les décalages sont calculés à partir des formats fournis, sans examiner la structure C#. Pour ces deux champs, la disposition obtenue est la suivante :" -tutorial.input.guidance: "La valeur par défaut de {semanticIndex} est zéro, ce qui correspond à {pOSITION0} et {cOLOR0} dans le shader. La position et la couleur étant stockées ensemble dans un seul tampon de sommets, le pipeline utilise une disposition d’entrée à l’emplacement 0. Cette disposition doit être adaptée si l’ordre des champs ou le remplissage de la structure C# change." +tutorial.geometry.upload.title: 'Allocation et transfert du tampon' +tutorial.input.description: 'Le GPU doit savoir où se trouvent les attributs de chaque sommet, comme la position et la couleur. La disposition d’entrée indique leur format et leur décalage, ainsi que le pas, la distance en octets entre deux sommets successifs. Ajoutez ce code après la création des shaders :' +tutorial.input.details: '{inputLayoutAdd} place chaque attribut immédiatement après le précédent et ajoute sa taille au pas entre sommets. Les décalages sont calculés à partir des formats fournis, sans examiner la structure C#. Pour ces deux champs, la disposition obtenue est la suivante :' +tutorial.input.guidance: 'La valeur par défaut de {semanticIndex} est zéro, ce qui correspond à {pOSITION0} et {cOLOR0} dans le shader. La position et la couleur étant stockées ensemble dans un seul tampon de sommets, le pipeline utilise une disposition d’entrée à l’emplacement 0. Cette disposition doit être adaptée si l’ordre des champs ou le remplissage de la structure C# change.' tutorial.input.table.headings.byteOffset: Décalage d’octets -tutorial.input.table.headings.cField: "Champ C#" +tutorial.input.table.headings.cField: 'Champ C#' tutorial.input.table.headings.format: Format tutorial.input.table.headings.shaderInput: Entrée de shader tutorial.input.table.nextVertex.cField: Sommet suivant -tutorial.input.table.nextVertex.format: "Pas total : 28 octets" +tutorial.input.table.nextVertex.format: 'Pas total : 28 octets' tutorial.input.table.nextVertex.shaderInput: Enregistrement d’entrée suivant -tutorial.input.table.vertexColor.format: "{float4} (16 octets)" -tutorial.input.table.vertexPosition.format: "{float3} (12 octets)" -tutorial.input.title: "Disposition des sommets en entrée" -tutorial.lifecycle.description: "Chaque image suit cette séquence :" -tutorial.lifecycle.details: "À la fermeture de la fenêtre, {run} retourne et l’exécution se poursuit avec le nettoyage. Chaque image ayant déjà attendu la fin de ses commandes, les ressources utilisées par ces commandes peuvent être libérées. Le nettoyage complet après {windowRun} est le suivant :" -tutorial.lifecycle.guidance: "Libérez la chaîne d’échange avant sa fenêtre native, et le contexte après ses ressources. La file recycle les tampons de commandes soumis, tandis que la chaîne d’échange gère sa texture de sortie. Aucun de ces objets ne nécessite donc d’appel distinct à {dispose}." -tutorial.lifecycle.title: "Cycle d’image et libération" -tutorial.pipeline.behavior: "Après la disposition d’entrée, créez le pipeline :" -tutorial.pipeline.context: "{cullNone} désactive l’élimination des faces. Le triangle est donc dessiné que ses sommets apparaissent dans le sens horaire ou antihoraire." -tutorial.pipeline.description: "Un {graphicsPipeline} réunit la disposition des sommets, les deux shaders et les réglages d’assemblage des primitives et d’écriture dans les attachements." -tutorial.pipeline.details: "Les shaders traitent les sommets et les fragments. Les autres réglages du pipeline contrôlent l’assemblage des primitives, l’élimination des faces, le test de profondeur et le mélange des couleurs :" -tutorial.pipeline.guidance: "Le format du pipeline doit correspondre à l’attachement ; il provient donc de {swapChainDescFormat}. {count1} indique un échantillon par pixel." -tutorial.pipeline.item: "{triangleList} assemble chaque groupe de trois sommets consécutifs en un triangle." -tutorial.pipeline.notes: "{depthNone} désactive le test et l’écriture de profondeur, puisque la passe ne comporte pas d’attachement de profondeur." -tutorial.pipeline.reference: "{opaque} désactive le mélange. La couleur du fragment remplace ainsi le fond à l’intérieur du triangle." -tutorial.pipeline.title: "Pipeline graphique" -tutorial.pipeline.usage: "Les objets shader peuvent être libérés après la création du pipeline. Conservez le pipeline pendant le rendu et ajoutez {pipelineDispose} avant {vertexBufferDispose} dans le nettoyage." -tutorial.presentation.title: "Contexte graphique et présentation" -tutorial.project.context: "Activez {emphasis} ({allowUnsafeBlocks}) dans les paramètres de compilation. Les appels natifs du code de fenêtre et le transfert des sommets nécessitent du code unsafe." +tutorial.input.table.vertexColor.format: '{float4} (16 octets)' +tutorial.input.table.vertexPosition.format: '{float3} (12 octets)' +tutorial.input.title: 'Disposition des sommets en entrée' +tutorial.lifecycle.description: 'Chaque image suit cette séquence :' +tutorial.lifecycle.details: 'À la fermeture de la fenêtre, {run} retourne et l’exécution se poursuit avec le nettoyage. Chaque image ayant déjà attendu la fin de ses commandes, les ressources utilisées par ces commandes peuvent être libérées. Le nettoyage complet après {windowRun} est le suivant :' +tutorial.lifecycle.guidance: 'Libérez la chaîne d’échange avant sa fenêtre native, et le contexte après ses ressources. La file recycle les tampons de commandes soumis, tandis que la chaîne d’échange gère sa texture de sortie. Aucun de ces objets ne nécessite donc d’appel distinct à {dispose}.' +tutorial.lifecycle.title: 'Cycle d’image et libération' +tutorial.pipeline.behavior: 'Après la disposition d’entrée, créez le pipeline :' +tutorial.pipeline.context: '{cullNone} désactive l’élimination des faces. Le triangle est donc dessiné que ses sommets apparaissent dans le sens horaire ou antihoraire.' +tutorial.pipeline.description: 'Un {graphicsPipeline} réunit la disposition des sommets, les deux shaders et les réglages d’assemblage des primitives et d’écriture dans les attachements.' +tutorial.pipeline.details: 'Les shaders traitent les sommets et les fragments. Les autres réglages du pipeline contrôlent l’assemblage des primitives, l’élimination des faces, le test de profondeur et le mélange des couleurs :' +tutorial.pipeline.guidance: 'Le format du pipeline doit correspondre à l’attachement ; il provient donc de {swapChainDescFormat}. {count1} indique un échantillon par pixel.' +tutorial.pipeline.item: '{triangleList} assemble chaque groupe de trois sommets consécutifs en un triangle.' +tutorial.pipeline.notes: '{depthNone} désactive le test et l’écriture de profondeur, puisque la passe ne comporte pas d’attachement de profondeur.' +tutorial.pipeline.reference: '{opaque} désactive le mélange. La couleur du fragment remplace ainsi le fond à l’intérieur du triangle.' +tutorial.pipeline.title: 'Pipeline graphique' +tutorial.pipeline.usage: 'Les objets shader peuvent être libérés après la création du pipeline. Conservez le pipeline pendant le rendu et ajoutez {pipelineDispose} avant {vertexBufferDispose} dans le nettoyage.' +tutorial.presentation.title: 'Contexte graphique et présentation' +tutorial.project.context: 'Activez {emphasis} ({allowUnsafeBlocks}) dans les paramètres de compilation. Les appels natifs du code de fenêtre et le transfert des sommets nécessitent du code unsafe.' tutorial.project.context.emphasis: Autoriser le code non sécurisé -tutorial.project.description: "Créez un projet console C# nommé {firstTriangle} ciblant .NET 10." -tutorial.project.details: "Ajoutez les paquets NuGet suivants au projet :" -tutorial.project.guidance: "{zenithNET} fournit l’API de rendu commune, et les trois paquets de backend en fournissent les implémentations propres aux plateformes. {zenithNETCompiler} compile les shaders Slang présentés plus bas pour le backend choisi. Silk.NET assure la création de la fenêtre et le traitement des événements." -tutorial.project.title: "Configuration du projet" -tutorial.requirements.context: "L’{link} et son {detail} fournissent les implémentations de référence de ce tutoriel." +tutorial.project.description: 'Créez un projet console C# nommé {firstTriangle} ciblant .NET 10.' +tutorial.project.details: 'Ajoutez les paquets NuGet suivants au projet :' +tutorial.project.guidance: '{zenithNET} fournit l’API de rendu commune, et les trois paquets de backend en fournissent les implémentations propres aux plateformes. {zenithNETCompiler} compile les shaders Slang présentés plus bas pour le backend choisi. Silk.NET assure la création de la fenêtre et le traitement des événements.' +tutorial.project.title: 'Configuration du projet' +tutorial.requirements.context: 'L’{link} et son {detail} fournissent les implémentations de référence de ce tutoriel.' tutorial.requirements.context.detail: hôte partagé tutorial.requirements.context.link: exemple Bonjour triangle -tutorial.requirements.description: "Vous devez disposer du {emphasis} et connaître les bases de C#. L’application cible {net10}. Le GPU et son pilote doivent prendre en charge le backend choisi pour votre plateforme :" +tutorial.requirements.description: 'Vous devez disposer du {emphasis} et connaître les bases de C#. L’application cible {net10}. Le GPU et son pilote doivent prendre en charge le backend choisi pour votre plateforme :' tutorial.requirements.description.emphasis: SDK .NET 10 -tutorial.requirements.guidance: "Zenith.NET rend dans une surface native fournie par l’application. Silk.NET.Windowing crée la fenêtre et gère les événements. Sous macOS, une couche Metal représentée par {cAMetalLayerCs} reçoit la sortie ; le code auxiliaire la rattache à la fenêtre." +tutorial.requirements.guidance: 'Zenith.NET rend dans une surface native fournie par l’application. Silk.NET.Windowing crée la fenêtre et gère les événements. Sous macOS, une couche Metal représentée par {cAMetalLayerCs} reçoit la sortie ; le code auxiliaire la rattache à la fenêtre.' tutorial.requirements.table.headings.graphicsBackend: Backend graphique tutorial.requirements.table.headings.platform: Plateforme tutorial.requirements.table.linux.graphicsBackend: Vulkan 1.4 -tutorial.requirements.table.linux.platform: "Linux (X11 ou XWayland)" +tutorial.requirements.table.linux.platform: 'Linux (X11 ou XWayland)' tutorial.requirements.table.macOS.graphicsBackend: Metal 4 tutorial.requirements.table.macOS.platform: macOS tutorial.requirements.table.windows.graphicsBackend: DirectX 12 tutorial.requirements.table.windows.platform: Windows -tutorial.requirements.title: "Prérequis" -tutorial.resize.context: "Compilez et lancez de nouveau l’application. Le fond doit continuer à remplir la fenêtre lorsque vous la redimensionnez : chaque nouvelle passe ajuste son viewport et son rectangle de découpe aux dimensions de l’attachement. Conservez le rappel de rendu ; le triangle sera dessiné dans cette passe." -tutorial.resize.description: "La chaîne d’échange doit suivre les changements de dimensions du framebuffer. Ajoutez un gestionnaire de {framebufferResize} après le rappel de rendu et avant {windowRun} :" -tutorial.resize.details: "Réagissez aux {link}, exprimés en pixels, plutôt qu’aux changements de taille logique de la fenêtre. Si la réduction de la fenêtre met l’une des dimensions du framebuffer à zéro, le gestionnaire de redimensionnement laisse la chaîne d’échange inchangée. Le rappel de rendu retourne lui aussi immédiatement tant qu’une dimension est nulle. Le rendu reprend lorsque le framebuffer retrouve des dimensions utilisables." -tutorial.resize.details.link: "changements de taille du framebuffer" -tutorial.resize.guidance: "Le rappel de rendu attend la fin des commandes soumises pour chaque image avant d’appeler {present}. Le gestionnaire de redimensionnement peut donc remplacer les images de la chaîne d’échange sans interrompre le travail d’une image précédente. L’article {link} détaille ce lien entre achèvement du travail et durée de vie des ressources." +tutorial.requirements.title: 'Prérequis' +tutorial.resize.context: 'Compilez et lancez de nouveau l’application. Le fond doit continuer à remplir la fenêtre lorsque vous la redimensionnez : chaque nouvelle passe ajuste son viewport et son rectangle de découpe aux dimensions de l’attachement. Conservez le rappel de rendu ; le triangle sera dessiné dans cette passe.' +tutorial.resize.description: 'La chaîne d’échange doit suivre les changements de dimensions du framebuffer. Ajoutez un gestionnaire de {framebufferResize} après le rappel de rendu et avant {windowRun} :' +tutorial.resize.details: 'Réagissez aux {link}, exprimés en pixels, plutôt qu’aux changements de taille logique de la fenêtre. Si la réduction de la fenêtre met l’une des dimensions du framebuffer à zéro, le gestionnaire de redimensionnement laisse la chaîne d’échange inchangée. Le rappel de rendu retourne lui aussi immédiatement tant qu’une dimension est nulle. Le rendu reprend lorsque le framebuffer retrouve des dimensions utilisables.' +tutorial.resize.details.link: 'changements de taille du framebuffer' +tutorial.resize.guidance: 'Le rappel de rendu attend la fin des commandes soumises pour chaque image avant d’appeler {present}. Le gestionnaire de redimensionnement peut donc remplacer les images de la chaîne d’échange sans interrompre le travail d’une image précédente. L’article {link} détaille ce lien entre achèvement du travail et durée de vie des ressources.' tutorial.resize.guidance.link: Synchronisation -tutorial.resize.title: "Redimensionnement" -tutorial.shaders.compilation.context: "{appContextBaseDirectory} permet de charger la copie du shader depuis le répertoire de sortie de l’application. Le fichier reste ainsi localisable même si l’application est lancée depuis un autre répertoire de travail." -tutorial.shaders.compilation.description: "Pour {triangleSlang}, réglez la propriété {emphasis} sur {detail}. La compilation du projet copiera le shader près de l’exécutable." +tutorial.resize.title: 'Redimensionnement' +tutorial.shaders.compilation.context: '{appContextBaseDirectory} permet de charger la copie du shader depuis le répertoire de sortie de l’application. Le fichier reste ainsi localisable même si l’application est lancée depuis un autre répertoire de travail.' +tutorial.shaders.compilation.description: 'Pour {triangleSlang}, réglez la propriété {emphasis} sur {detail}. La compilation du projet copiera le shader près de l’exécutable.' tutorial.shaders.compilation.description.detail: Copier si plus récent tutorial.shaders.compilation.description.emphasis: Copier dans le répertoire de sortie -tutorial.shaders.compilation.details: "Dans {programCs}, ajoutez l’initialisation des shaders après le transfert des sommets et avant le rappel de rendu :" -tutorial.shaders.compilation.guidance: "{zenithCompiler} compile le code source pour {contextGraphicsApi}, puis {createShader} crée un objet shader à partir de la description compilée. Les noms de points d’entrée {vSMain} et {fSMain} sélectionnent les deux fonctions définies dans le fichier Slang." -tutorial.shaders.compilation.title: "Compilation des shaders" -tutorial.shaders.context: "{fSInput} relie les deux étapes de shader. Le shader de sommets écrit une position dans l’espace de clipping dans {sVPOSITION} ; le GPU s’en sert pour déterminer la partie visible du triangle. Le champ {cOLOR0} transmet la couleur du sommet, qui est interpolée sur le triangle avant de parvenir au shader de fragments. Son type et sa sémantique doivent correspondre entre les deux étapes." -tutorial.shaders.description: "Les shaders sont des programmes exécutés sur le GPU. Le shader de sommets détermine la position de chaque sommet ; le shader de fragments détermine la couleur aux emplacements de l’image couverts par le triangle. Les deux étapes seront écrites dans un même fichier Slang, chacune avec son point d’entrée, c’est-à-dire la fonction où commence son exécution." -tutorial.shaders.details: "Créez {triangleSlang} avec ces structures d’entrée et de sortie :" -tutorial.shaders.fragment.description: "Ajoutez le point d’entrée de fragments dans le même fichier :" -tutorial.shaders.fragment.details: "La rastérisation détermine les emplacements couverts par le triangle et y génère des fragments. Chaque fragment reçoit une couleur interpolée à partir des couleurs des trois sommets. {fSMain} renvoie cette couleur, et {sVTARGET} dirige le résultat vers le premier attachement de couleur." -tutorial.shaders.fragment.title: "Traitement des fragments" -tutorial.shaders.guidance: "{vSInput} définit l’entrée du shader de sommets. {pOSITION0} et {cOLOR0} identifient les attributs par leur sémantique ; les noms C# n’établissent pas cette correspondance." -tutorial.shaders.title: "Étapes des shaders" -tutorial.shaders.vertex.description: "Ajoutez le point d’entrée de sommets à {triangleSlang} :" -tutorial.shaders.vertex.details: "Le GPU appelle ce point d’entrée pour chaque sommet, ajoute la coordonnée homogène {w} et transmet la couleur. La position est ensuite divisée par w. Ici w vaut 1 : x, y et z restent inchangés et correspondent aux coordonnées normalisées du périphérique." -tutorial.shaders.vertex.title: "Traitement des sommets" -tutorial.surface.description: "Définissez la cible de présentation native {emphasis} :" +tutorial.shaders.compilation.details: 'Dans {programCs}, ajoutez l’initialisation des shaders après le transfert des sommets et avant le rappel de rendu :' +tutorial.shaders.compilation.guidance: '{zenithCompiler} compile le code source pour {contextGraphicsApi}, puis {createShader} crée un objet shader à partir de la description compilée. Les noms de points d’entrée {vSMain} et {fSMain} sélectionnent les deux fonctions définies dans le fichier Slang.' +tutorial.shaders.compilation.title: 'Compilation des shaders' +tutorial.shaders.context: '{fSInput} relie les deux étapes de shader. Le shader de sommets écrit une position dans l’espace de clipping dans {sVPOSITION} ; le GPU s’en sert pour déterminer la partie visible du triangle. Le champ {cOLOR0} transmet la couleur du sommet, qui est interpolée sur le triangle avant de parvenir au shader de fragments. Son type et sa sémantique doivent correspondre entre les deux étapes.' +tutorial.shaders.description: 'Les shaders sont des programmes exécutés sur le GPU. Le shader de sommets détermine la position de chaque sommet ; le shader de fragments détermine la couleur aux emplacements de l’image couverts par le triangle. Les deux étapes seront écrites dans un même fichier Slang, chacune avec son point d’entrée, c’est-à-dire la fonction où commence son exécution.' +tutorial.shaders.details: 'Créez {triangleSlang} avec ces structures d’entrée et de sortie :' +tutorial.shaders.fragment.description: 'Ajoutez le point d’entrée de fragments dans le même fichier :' +tutorial.shaders.fragment.details: 'La rastérisation détermine les emplacements couverts par le triangle et y génère des fragments. Chaque fragment reçoit une couleur interpolée à partir des couleurs des trois sommets. {fSMain} renvoie cette couleur, et {sVTARGET} dirige le résultat vers le premier attachement de couleur.' +tutorial.shaders.fragment.title: 'Traitement des fragments' +tutorial.shaders.guidance: '{vSInput} définit l’entrée du shader de sommets. {pOSITION0} et {cOLOR0} identifient les attributs par leur sémantique ; les noms C# n’établissent pas cette correspondance.' +tutorial.shaders.title: 'Étapes des shaders' +tutorial.shaders.vertex.description: 'Ajoutez le point d’entrée de sommets à {triangleSlang} :' +tutorial.shaders.vertex.details: 'Le GPU appelle ce point d’entrée pour chaque sommet, ajoute la coordonnée homogène {w} et transmet la couleur. La position est ensuite divisée par w. Ici w vaut 1 : x, y et z restent inchangés et correspondent aux coordonnées normalisées du périphérique.' +tutorial.shaders.vertex.title: 'Traitement des sommets' +tutorial.surface.description: 'Définissez la cible de présentation native {emphasis} :' tutorial.surface.description.emphasis: après {windowCenter} et avant {windowRun} -tutorial.surface.details: "Le framebuffer est l’image de la fenêtre en pixels. {surface} décrit la cible de présentation native et ses dimensions ; {framebufferSize} donne la taille en pixels. Avec la mise à l’échelle de l’affichage, cette taille peut différer de la taille logique de la fenêtre." -tutorial.surface.guidance: "La surface fournit les handles natifs du backend choisi : une fenêtre Win32 sous Windows, un affichage et une fenêtre X11 sous Linux, ou la couche Metal attachée sous macOS." -tutorial.surface.title: "Surface native" -tutorial.swapChain.context: "La chaîne dépend du contexte et de la fenêtre. Remplacez {windowDispose} à la fin de {programCs} par cet ordre de libération :" -tutorial.swapChain.description: "Créez la chaîne d’échange immédiatement après la surface :" -tutorial.swapChain.details: "La {swapChain} gère les images présentées. {drawable} fournit l’image courante sous forme de {texture}, la ressource image de l’API. Après le rendu, {present} demande son affichage et passe à la suivante." -tutorial.swapChain.guidance: "{b8G8R8A8UNorm} stocke quatre canaux de 8 bits dans l’ordre bleu, vert, rouge, alpha. {uNorm} fait correspondre les entiers de 0 à 255 aux valeurs de 0 à 1. Le shader produit des valeurs RGBA ; le format détermine leur stockage en mémoire. Le pipeline reprend le format de couleur {swapChainDescFormat} pour correspondre à l’attachement." -tutorial.swapChain.title: "Chaîne d’échange" +tutorial.surface.details: 'Le framebuffer est l’image de la fenêtre en pixels. {surface} décrit la cible de présentation native et ses dimensions ; {framebufferSize} donne la taille en pixels. Avec la mise à l’échelle de l’affichage, cette taille peut différer de la taille logique de la fenêtre.' +tutorial.surface.guidance: 'La surface fournit les handles natifs du backend choisi : une fenêtre Win32 sous Windows, un affichage et une fenêtre X11 sous Linux, ou la couche Metal attachée sous macOS.' +tutorial.surface.title: 'Surface native' +tutorial.swapChain.context: 'La chaîne dépend du contexte et de la fenêtre. Remplacez {windowDispose} à la fin de {programCs} par cet ordre de libération :' +tutorial.swapChain.description: 'Créez la chaîne d’échange immédiatement après la surface :' +tutorial.swapChain.details: 'La {swapChain} gère les images présentées. {drawable} fournit l’image courante sous forme de {texture}, la ressource image de l’API. Après le rendu, {present} demande son affichage et passe à la suivante.' +tutorial.swapChain.guidance: '{b8G8R8A8UNorm} stocke quatre canaux de 8 bits dans l’ordre bleu, vert, rouge, alpha. {uNorm} fait correspondre les entiers de 0 à 255 aux valeurs de 0 à 1. Le shader produit des valeurs RGBA ; le format détermine leur stockage en mémoire. Le pipeline reprend le format de couleur {swapChainDescFormat} pour correspondre à l’attachement.' +tutorial.swapChain.title: 'Chaîne d’échange' tutorial.title: Premier triangle -tutorial.troubleshooting.description: "Les diagnostics console et les trois points de contrôle permettent d’isoler l’étape en échec :" -tutorial.troubleshooting.details: "Le {link} et le {detail} servent de référence pour les données des sommets, la disposition d’entrée et les commandes de dessin. Dans cet exemple, la fenêtre et la soumission sont gérées par un hôte commun ; ce tutoriel conserve le déroulement de l’application dans {programCs}. L’exemple {context} introduit le dessin indexé, les transformations et le test de profondeur." +tutorial.troubleshooting.description: 'Les diagnostics console et les trois points de contrôle permettent d’isoler l’étape en échec :' +tutorial.troubleshooting.details: 'Le {link} et le {detail} servent de référence pour les données des sommets, la disposition d’entrée et les commandes de dessin. Dans cet exemple, la fenêtre et la soumission sont gérées par un hôte commun ; ce tutoriel conserve le déroulement de l’application dans {programCs}. L’exemple {context} introduit le dessin indexé, les transformations et le test de profondeur.' tutorial.troubleshooting.details.context: Cube en rotation tutorial.troubleshooting.details.detail: shader Slang tutorial.troubleshooting.details.link: moteur de rendu d’exemple @@ -496,18 +496,18 @@ tutorial.troubleshooting.table.drawing.check: Vérifiez la taille du transfert, tutorial.troubleshooting.table.drawing.symptom: L’arrière-plan apparaît mais pas le triangle tutorial.troubleshooting.table.headings.check: Vérification tutorial.troubleshooting.table.headings.symptom: Symptôme -tutorial.troubleshooting.table.input.check: "Vérifiez le pas de 28 octets et les décalages de la position et de la couleur : respectivement 0 et 12 octets." +tutorial.troubleshooting.table.input.check: 'Vérifiez le pas de 28 octets et les décalages de la position et de la couleur : respectivement 0 et 12 octets.' tutorial.troubleshooting.table.input.symptom: Les positions ou les couleurs des sommets sont corrompues tutorial.troubleshooting.table.shaders.check: Vérifiez le fichier {triangleSlang} copié, l’orthographe du point d’entrée et le diagnostic signalé par le compilateur. -tutorial.troubleshooting.table.shaders.symptom: "Le fond s’affiche, mais le chargement des shaders échoue" +tutorial.troubleshooting.table.shaders.symptom: 'Le fond s’affiche, mais le chargement des shaders échoue' tutorial.troubleshooting.table.window.check: Confirmez que le projet .NET se compile et que l’étape de fenêtre seule s’exécute dans une session de bureau. Sous Linux, vérifiez que X11 ou XWayland est disponible. tutorial.troubleshooting.table.window.symptom: Aucune fenêtre ne s’ouvre -tutorial.troubleshooting.title: "Diagnostic des erreurs" -tutorial.window.description: "Téléchargez {cocoaHelperCs} dans le projet. Cette classe auxiliaire attache la couche Metal à la fenêtre macOS." -tutorial.window.details: "Remplacez le contenu généré de {programCs} par le code suivant. Les instructions de niveau supérieur s’exécutent dans l’ordre, sans méthode {main} explicite. Les prochaines sections préciseront où ajouter chaque extrait :" -tutorial.window.guidance: "{graphicsAPINone} laisse à Zenith.NET la création du contexte graphique. {initialize} crée la fenêtre native et rend ses handles disponibles. {center} la place au centre de l’écran. {run} traite les événements jusqu’à sa fermeture, puis l’exécution passe à {dispose} pour la libérer." -tutorial.window.notes: "Compilez et lancez l’application. Vérifiez que la fenêtre s’ouvre et se ferme correctement, et que vous pouvez la déplacer et la redimensionner. Son contenu n’est pas encore défini, car aucune commande de rendu n’a été soumise. Fermez la fenêtre avant de poursuivre." -tutorial.window.title: "Création de la fenêtre" +tutorial.troubleshooting.title: 'Diagnostic des erreurs' +tutorial.window.description: 'Téléchargez {cocoaHelperCs} dans le projet. Cette classe auxiliaire attache la couche Metal à la fenêtre macOS.' +tutorial.window.details: 'Remplacez le contenu généré de {programCs} par le code suivant. Les instructions de niveau supérieur s’exécutent dans l’ordre, sans méthode {main} explicite. Les prochaines sections préciseront où ajouter chaque extrait :' +tutorial.window.guidance: '{graphicsAPINone} laisse à Zenith.NET la création du contexte graphique. {initialize} crée la fenêtre native et rend ses handles disponibles. {center} la place au centre de l’écran. {run} traite les événements jusqu’à sa fermeture, puis l’exécution passe à {dispose} pour la libérer.' +tutorial.window.notes: 'Compilez et lancez l’application. Vérifiez que la fenêtre s’ouvre et se ferme correctement, et que vous pouvez la déplacer et la redimensionner. Son contenu n’est pas encore défini, car aucune commande de rendu n’a été soumise. Fermez la fenêtre avant de poursuivre.' +tutorial.window.title: 'Création de la fenêtre' ui.action.copy: Copier ui.action.navigate: Naviguer ui.action.open: Ouvrir @@ -530,12 +530,12 @@ ui.content.tutorial: Tutoriel ui.contents.close: Fermer la table des matières ui.contents.open: Ouvrir la table des matières ui.contents.title: Table des matières -ui.footer.caption: "RHI moderne pour .NET" +ui.footer.caption: 'RHI moderne pour .NET' ui.footer.label: Pied de page ui.language.label: Langue ui.language.unavailable: Non traduit ui.members.clear: Effacer la recherche de membres -ui.members.close: "Fermer la recherche de membres" +ui.members.close: 'Fermer la recherche de membres' ui.members.empty: Aucun membre correspondant. ui.members.open: Aller au membre ui.members.placeholder: Nom ou signature… @@ -552,7 +552,7 @@ ui.outline.title: Sur cette page ui.reference.assembly: Assembly ui.reference.classes: Classes ui.reference.constructors: Constructeurs -ui.reference.declaration: "Déclaration de type C#" +ui.reference.declaration: 'Déclaration de type C#' ui.reference.delegates: Délégués ui.reference.derived: Types dérivés ui.reference.enums: Énumérations @@ -576,7 +576,7 @@ ui.reference.properties: Propriétés ui.reference.related: Voir aussi ui.reference.relationships: Héritage et métadonnées ui.reference.remarks: Remarques -ui.reference.returns: "Valeur de retour" +ui.reference.returns: 'Valeur de retour' ui.reference.structs: Structures ui.reference.typeParameters: Paramètres de type ui.reference.value: Valeur @@ -588,6 +588,6 @@ ui.search.loading: Chargement de la recherche… ui.search.more: Afficher plus de résultats ui.search.pending: Recherche en cours… ui.search.placeholder: Que recherchez-vous ? -ui.search.resultCount: "Résultats : {count}" +ui.search.resultCount: 'Résultats : {count}' ui.search.title: Rechercher dans la documentation ui.search.unavailable: La recherche est indisponible. Vous pouvez toujours ouvrir les pages ci-dessous. diff --git a/documents/locales/fr-FR/translation.md b/documents/locales/fr-FR/translation.md index 7321670a..fa9f17f4 100644 --- a/documents/locales/fr-FR/translation.md +++ b/documents/locales/fr-FR/translation.md @@ -2,7 +2,7 @@ ## Ressources et structure -Le [dictionnaire de ressources anglais](../en-US/strings.yml) est l’unique source du texte. Les règles du projet figurent dans le [guide de maintenance de la documentation](../../authoring.md). Pour commencer une traduction, copier l’intégralité du fichier anglais dans `strings.yml`, dans ce répertoire. Conserver la première ligne `### YamlMime:Resources` et l’encodage UTF-8. Pour les mises à jour, reporter les changements de l’original sans écraser les traductions existantes. Ce fichier `translation.md` est conservé durablement et n’est pas publié sur le site. +Le [dictionnaire de ressources anglais](../en-US/strings.yml) est l’unique source du texte. Les règles du projet figurent dans le [guide de maintenance de la documentation](../../maintenance.md). Pour commencer une traduction, copier l’intégralité du fichier anglais dans `strings.yml`, dans ce répertoire. Conserver la première ligne `### YamlMime:Resources` et l’encodage UTF-8. Pour les mises à jour, reporter les changements de l’original sans écraser les traductions existantes. Ce fichier `translation.md` est conservé durablement et n’est pas publié sur le site. La navigation, l’ordre des chapitres, les ancres, les liens, la mise en forme, le code et les images sont partagés et restent hors de `locales/`. Ne pas ajouter ici d’articles, de TOC, de modèles, de scripts ou de configuration. @@ -65,21 +65,21 @@ Avant livraison, vérifier les clés et les espaces réservés. Contrôler l’a ## Terminologie -| Terme anglais | Forme retenue | -| --- | --- | -| API / GPU / RHI | Conserver les sigles et les expliquer selon l’original | -| barrier | barrière | -| buffer | tampon ; conserver `Buffer` | -| command buffer | tampon de commandes | -| command queue | file de commandes | -| drawable | texture de sortie de l’image en cours de rendu ; conserver `Drawable`, sans supposer qu’elle appartient à une chaîne d’échange | -| graphics context | contexte graphique | -| pipeline | pipeline | -| readback | lecture de données depuis le GPU | -| render pass | passe de rendu | -| resource | ressource | -| shader | shader | -| swap chain | chaîne d’échange | -| texture | texture | -| timeline | ligne de temps | -| upload | transfert de données vers le GPU | +| Terme anglais | Forme retenue | +| ---------------- | ------------------------------------------------------------------------------------------------------------------------------ | +| API / GPU / RHI | Conserver les sigles et les expliquer selon l’original | +| barrier | barrière | +| buffer | tampon ; conserver `Buffer` | +| command buffer | tampon de commandes | +| command queue | file de commandes | +| drawable | texture de sortie de l’image en cours de rendu ; conserver `Drawable`, sans supposer qu’elle appartient à une chaîne d’échange | +| graphics context | contexte graphique | +| pipeline | pipeline | +| readback | lecture de données depuis le GPU | +| render pass | passe de rendu | +| resource | ressource | +| shader | shader | +| swap chain | chaîne d’échange | +| texture | texture | +| timeline | ligne de temps | +| upload | transfert de données vers le GPU | diff --git a/documents/locales/ja-JP/strings.yml b/documents/locales/ja-JP/strings.yml index d0325bb9..3ee356f9 100644 --- a/documents/locales/ja-JP/strings.yml +++ b/documents/locales/ja-JP/strings.yml @@ -1,593 +1,593 @@ ### YamlMime:Resources -concepts.execution.context.description: "{graphicsContext} は特定のバックエンドを介してアプリケーションを GPU デバイスに接続し、描画、計算、転送のキューを提供します。一緒に使うリソースは同じコンテキストに属している必要があります。バッファー、テクスチャ、シェーダー、パイプラインとそのハンドルを、コンテキストをまたいでバインドすることはできません。" -concepts.execution.context.details: "{capabilities} はデバイス名と対応機能を提供します。レイトレーシングやメッシュシェーディング用のリソースを作成する前に、{rayTracingSupported} と {meshShadingSupported} で対応を確認します。{link}と{detail}のサンプルでは、初期化時にこの確認を行っています。" -concepts.execution.context.details.detail: "メッシュシェーディング" -concepts.execution.context.details.link: "レイトレーシング" -concepts.execution.context.title: "グラフィックスコンテキスト" -concepts.execution.description: "GPU の処理は CPU 側で準備します。アプリケーションがリソースを作成し、それらを使うコマンドを記録して、キューに送信します。送信後は GPU がコマンドを実行する間も CPU が処理を続けられます。リソースは GPU の実行が終わるまで保持する必要があります。" -concepts.execution.ownership.description: "所有権は誰がオブジェクトを解放するかを、GPU の完了はいつ解放できるかを決めます。C# の参照が残っていても、{dispose} を呼ぶとネイティブリソースは解放されます。コマンドを送信しても、そのリソースの所有権はキューへ移りません。" -concepts.execution.ownership.details: "終了時は新しい送信を止め、関係するすべてのキューでリソースの最後の使用が終わるのを待ちます。その後、アプリケーションのリソースを解放し、最後にコンテキストを解放します。コンテキストは自身のキューと内部の補助オブジェクトを解放するため、この処理はアプリケーションの作業が終わってから行います。" -concepts.execution.ownership.guidance: "描画中にデータを上書きしたりリソースを置き換えたりする場合は、それを使う処理の完了を追跡します。その使用が終わるのを待ってから、データを変更するか記憶領域を解放します。ビューとその参照先リソースの寿命は、{link}で説明します。" -concepts.execution.ownership.guidance.link: "リソース管理" -concepts.execution.ownership.table.applicationResources.object: "アプリケーションが作成したリソース" -concepts.execution.ownership.table.applicationResources.ownership: "アプリケーションが最後の GPU 使用後に解放します。" -concepts.execution.ownership.table.commandBuffers.object: "借用したコマンドバッファー" -concepts.execution.ownership.table.commandBuffers.ownership: "キューが管理して再利用します。" -concepts.execution.ownership.table.headings.object: "オブジェクト" -concepts.execution.ownership.table.headings.ownership: "解放の責任" -concepts.execution.ownership.table.queues.object: "コンテキストキューとそのタイムライン" -concepts.execution.ownership.table.queues.ownership: "コンテキストとキューが管理します。" -concepts.execution.ownership.table.swapChainDrawable.ownership: "スワップチェーンが管理します。" -concepts.execution.ownership.title: "所有権と寿命" -concepts.execution.pipelines.description: "グラフィックスパイプラインは、シェーダー、頂点入力レイアウト、プリミティブの組み立て、アタッチメントのフォーマット、描画状態を定義します。頂点、インデックス、定数のデータをバインドする前に選択してください。アタッチメントのフォーマットとサンプル数は、レンダーパスと一致させる必要があります。" -concepts.execution.pipelines.details: "コンピュートパイプラインは、ディスパッチで実行するシェーダーのエントリーポイントを選びます。グラフィックスのレンダーパス外で、パイプラインと定数をバインドしてからディスパッチします。" -concepts.execution.pipelines.guidance: "{link}ではグラフィックスの手順を、{detail}では計算結果を表示するパスの前にディスパッチを加える手順を確認できます。" -concepts.execution.pipelines.guidance.detail: "コンピュートサンプル" -concepts.execution.pipelines.guidance.link: "三角形の描画コールバック" -concepts.execution.pipelines.title: "パイプラインの状態" -concepts.execution.queues.description: "描画、計算、コピーを含むフレームでは、通常は {graphicsQueue} から始めます。依存する操作を同じキューにまとめると、順序を扱いやすくなります。" -concepts.execution.queues.details: "独立した処理を別々のキューに送信できますが、各キューが独立したハードウェア実行ユニットに対応するとは限りません。処理を並行して実行する利点がある場合に、キューを追加します。一方のキューがもう一方の生成データを使う場合は、送信間に明示的な依存関係を設定します。" -concepts.execution.queues.guidance: "同じキュー内でも、依存する操作にはバリアやテクスチャ遷移が必要になる場合があります。後のアクセスで、それ以前の書き込み結果を読み取れるようにするためです。このメモリ依存関係は送信順序とは別の要件であり、指定方法は{link}で説明します。" -concepts.execution.queues.guidance.link: "同期" -concepts.execution.queues.table.computeQueue.workToRecord: "コンピュートディスパッチと対応する転送操作。グラフィックスのレンダーパスは含みません。" -concepts.execution.queues.table.graphicsQueue.workToRecord: "レンダーパス、描画、計算、転送の操作。" -concepts.execution.queues.table.headings.queue: "キュー" -concepts.execution.queues.table.headings.workToRecord: "対応する操作" -concepts.execution.queues.table.transferQueue.workToRecord: "アップロード、リードバック、コピー。描画とコンピュートディスパッチは含みません。" -concepts.execution.queues.title: "キューの選択" -concepts.execution.recording.context: "キューは完了したコマンドバッファーを回収して再利用します。記録ごとに {queueCommandBuffer} で取得し、同時に記録するスレッドを一つに限定して、一度だけ送信します。送信後はキューに管理を任せ、変更、再送信、解放を行わないでください。" -concepts.execution.recording.description: "{queueCommandBuffer} が返す {commandBuffer} は、既に記録を開始しています。操作と依存関係を記録した後、一度だけ {submit} を呼びます。記録が終了して送信され、そのキューの完了点を示す {timelineValue} が返ります。" -concepts.execution.recording.details: "三角形のチュートリアルでは、{commandBuffer} にフレームを記録した後、次のように送信して完了を待ちます。" -concepts.execution.recording.guidance: "記録によってコマンド列を構築し、{submit} でその実行をスケジュールします。続いて {wait} を呼ぶと、送信した処理が完了するまで CPU スレッドが待機します。チュートリアルでは次のフレームを始める前に現在のフレームが終わるため、処理の順序を追いやすくなります。" -concepts.execution.recording.title: "記録と送信" -concepts.execution.title: "実行モデル" -concepts.platforms.description: "画面への提示は、アプリケーションまたは UI コントロールが管理します。この選択によって、フレームの出力テクスチャを取得し、コマンドを記録・送信して結果を提示する担当が決まります。この出力テクスチャを drawable と呼びます。" -concepts.platforms.frame.context: "パス内でパイプラインのバインドと描画を記録し、ハンドラーから戻る前にパスを終了します。コントロールがコマンドを送信し、結果を提示します。ハンドラーでは送信を行わず、渡されたコマンドバッファーや drawable を解放しないでください。drawable のレイアウトを変更した場合は、コントロールが最後の遷移を行えるよう、戻る前に {colorAttachment} に戻します。" -concepts.platforms.frame.description: "コントロールは {iZenithView} を実装します。アプリケーションは {graphicsContext} を設定し、{updateRequested} でシーンを更新し、{renderRequested} で渡された {renderEventArgs} を使ってコマンドを記録します。" -concepts.platforms.frame.details: "各フレームで、コントロールは drawable とコマンドバッファーを取得し、drawable を {colorAttachment} に遷移させてから、更新と描画のハンドラーを呼びます。その後、記録した処理を送信し、フレームワークの提示方式に従って画像を表示します。" -concepts.platforms.frame.guidance: "ファイルに {usingZenithNET} を追加します。{view} という名前の {iZenithView} が初期化され、グラフィックスコンテキストも設定済みなら、次のハンドラーで drawable をクリアできます。" -concepts.platforms.frame.notes: "最初の遷移は {undefined} を使うため、以前の画像内容は破棄できます。毎フレーム、画像全体を描画するかクリアしてください。蓄積する描画結果やキャッシュはアプリケーション所有のテクスチャに保存し、そのテクスチャをコントロールの drawable に描画します。" -concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat} は、これらの統合で使う既定のカラーフォーマットを提供します。" -concepts.platforms.frame.title: "UI コントロールでの描画" -concepts.platforms.integration.context: "WinForms、WPF、Windows 向け WinUI の統合は Windows 上で動作します。MAUI では対象プラットフォームのワークロードをインストールし、{extensionsCs} のように {useZenithView} でコントロールハンドラーを登録します。" -concepts.platforms.integration.description: "イベントのインターフェースは共通ですが、提示方式はフレームワークごとに異なります。" -concepts.platforms.integration.details: "GPU の画像を UI に届ける方法は、実装によって異なります。ビットマップへのリードバックでは、表示前にピクセルを CPU メモリへコピーします。共有テクスチャの相互運用では、この CPU コピーを省けますが、GPU コピーや同期が必要な場合があります。統合を選ぶ際は、共通の {renderRequested} イベントだけでなく、提示方法も検討してください。" -concepts.platforms.integration.guidance: "使用する UI フレームワークの統合パッケージを NuGet から追加します。Avalonia では {avaloniaPackage} を使います。" -concepts.platforms.integration.table.avalonia.integration: "Avalonia" -concepts.platforms.integration.table.avalonia.presentation: "テクスチャにレンダリングし、ピクセルを {writeableBitmap} にリードバックします。{zenithViewCs} および {surfaceCs} を参照してください。" -concepts.platforms.integration.table.headings.integration: "統合" -concepts.platforms.integration.table.headings.presentation: "提示方式" -concepts.platforms.integration.table.maui.integration: ".NET MAUI" -concepts.platforms.integration.table.maui.presentation: "Android、iOS、Mac Catalyst ではネイティブサーフェスを使用し、Windows では共有テクスチャコンポジションを使用します。{link} を参照してください。" -concepts.platforms.integration.table.maui.presentation.link: "プラットフォーム実装" -concepts.platforms.integration.table.uno.integration: "Uno パス" -concepts.platforms.integration.table.uno.presentation: "ピクセルを {writeableBitmap} にリードバックします。{zenithViewUnoCs} を参照してください。" -concepts.platforms.integration.table.winForms.integration: "WinForms" -concepts.platforms.integration.table.winForms.presentation: "コントロールの {hWND} 用に Zenith.NET スワップチェーンを作成します。{zenithViewCs} を参照してください。" -concepts.platforms.integration.table.winUI.integration: "Windows 上の WinUI" -concepts.platforms.integration.table.winUI.presentation: "インポートされた共有 Direct3D 11 テクスチャにレンダリングし、{swapChainPanel} に接続されたコンポジションスワップチェーンにコピーします。{zenithViewWinUICs} を参照してください。" -concepts.platforms.integration.table.wpf.integration: "WPF" -concepts.platforms.integration.table.wpf.presentation: "共有 Direct3D 11 テクスチャをインポートし、Direct3D 相互運用を介して {d3DImage} によって表示されるサーフェスにコピーします。{surfaceCs} を参照してください。" -concepts.platforms.integration.title: "フレームワークと提示方式" -concepts.platforms.lifecycle.context: "対応するアタッチメントを作るときは、描画イベントから渡された drawable の {descWidth}、{descHeight}、{descFormat}、{descSampleCount} を使います。このテクスチャの寸法が、実際の描画先の寸法です。コントロールのレイアウト上のサイズや表示倍率から推測しないでください。" -concepts.platforms.lifecycle.description: "スワップチェーンのサイズには、フレームバッファーの幅と高さをピクセル単位で使います。表示倍率によっては、ウィンドウの論理寸法とは異なります。どちらかの寸法がゼロの間は、描画もスワップチェーンのリサイズも行いません。{swapChainDrawable} は毎フレーム取得します。このテクスチャはスワップチェーンが所有し、提示やリサイズの後に置き換わることがあります。" -concepts.platforms.lifecycle.details: "フレームバッファーの寸法が変わったら、古い画像への GPU アクセスが終わるのを待ってから {swapChainResize} を呼びます。ネイティブの提示先を置き換える場合も、アクセスの完了後に、新しいサーフェス記述とハンドルを {swapChainRefresh} に渡します。終了時は、ネイティブの提示先を破棄する前にスワップチェーンを解放します。" -concepts.platforms.lifecycle.guidance: "アプリケーションの深度テクスチャやオフスクリーンテクスチャがウィンドウと同じ寸法を使う場合は、リサイズ時に再作成し、それらのハンドルを含む定数も更新します。アタッチメントのフォーマットとサンプル数が合っていれば、パイプラインは再利用できます。{link}では、テクスチャをリサイズしながらパイプラインを保持する構成を確認できます。" -concepts.platforms.lifecycle.guidance.link: "回転する立方体のレンダラー" -concepts.platforms.lifecycle.title: "スワップチェーンの寸法と寿命" -concepts.platforms.ownership.description: "設定したコンテキストと描画リソースはアプリケーションが、提示用リソースはコントロールが所有します。ビューの {graphicsContext} を変えると、スケジューラーは新しいコンテキストでコントロールのリソースを再作成します。アプリケーションのパイプライン、バッファー、テクスチャも、同じコンテキストで作り直してください。" -concepts.platforms.ownership.details: "描画リソースを置き換える前にビューのフレーム処理を止め、そのリソースを使う GPU 処理の完了を待ちます。その後、古いリソースやコンテキストを解放します。ビューを削除した場合も、設定したコンテキストの解放はアプリケーションが担当します。" -concepts.platforms.ownership.guidance: "共通の {frameSchedulerCs} は、ビューの UI ディスパッチャーを通してフレームハンドラーを実行します。ハンドラーはシーンデータの更新とコマンドの記録に集中させてください。そこで長い CPU 処理を行うと、UI の応答も遅れます。" -concepts.platforms.ownership.title: "アプリケーションとコントロールの所有権" -concepts.platforms.surface.description: "{link}では、Silk.NET がウィンドウを作成してイベントを処理します。Zenith.NET は {surface} 記述を通じてネイティブウィンドウのハンドルと寸法を受け取り、それを使って {swapChain} を作成します。OS のウィンドウは引き続きアプリケーションが管理します。" -concepts.platforms.surface.description.link: "三角形のチュートリアル" -concepts.platforms.surface.details: "サーフェスのハンドルはバックエンドと対応させます。" -concepts.platforms.surface.guidance: "{appCs} のサンプルホストは Windows、macOS、X11 に対応しています。Linux のウィンドウは Xlib ハンドルを渡すため、Wayland セッションで実行するには XWayland が必要です。ネイティブ Wayland アプリケーションでは、{surfaceWayland} にディスプレイとサーフェスのハンドルを渡します。" -concepts.platforms.surface.table.android.backend: "Android 上の Vulkan。" -concepts.platforms.surface.table.apple.backend: "Apple プラットフォーム上の Metal。" -concepts.platforms.surface.table.headings.backend: "バックエンドとプラットフォーム" -concepts.platforms.surface.table.headings.factory: "サーフェスファクトリ" -concepts.platforms.surface.table.headings.handles: "ホストから提供されるハンドル" -concepts.platforms.surface.table.wayland.backend: "ネイティブ Wayland ホストを使用した Vulkan。" -concepts.platforms.surface.table.wayland.handles: "Wayland ディスプレイおよびサーフェス" -concepts.platforms.surface.table.win32.backend: "Windows 上の DirectX 12 または Vulkan。" -concepts.platforms.surface.table.xlib.backend: "X11 または XWayland を使用した Linux 上の Vulkan。" -concepts.platforms.surface.table.xlib.handles: "X11 ディスプレイおよびウィンドウ" -concepts.platforms.surface.title: "ネイティブの提示サーフェス" -concepts.platforms.title: "プラットフォーム統合" -concepts.resources.allocation.context: "ヒープに配置したリソースは、その寿命全体にわたってヒープの記憶領域を使います。最後の GPU 使用が終わったら、リソースを先に解放し、その後ヒープを解放します。" -concepts.resources.allocation.description: "アプリケーションでメモリ割り当てを管理する場合は、{heap} を使います。ヒープは、指定したバイトオフセットにリソースを配置する記憶領域です。オフセットの選択と使用領域の管理はアプリケーションが行います。" -concepts.resources.allocation.details: "各リソースの作成に使うバッファーまたはテクスチャ記述を渡して、{contextGetSizeAndAlignment} を呼びます。返されたアラインメントの倍数となるオフセットに、返されたサイズ分の領域を確保します。領域はヒープ内に収め、使用中の別の割り当てと重ねてはいけません。テクスチャにはバックエンド固有のパディングが含まれる場合があるため、ピクセル数とピクセル当たりのバイト数だけでは割り当てサイズを算出できません。" -concepts.resources.allocation.guidance: "ヒープに配置するバッファーは、そのヒープと同じ常駐区分を指定します。テクスチャの格納には GPU 専用ヒープを使います。" -concepts.resources.allocation.title: "ヒープへの配置" -concepts.resources.bufferUsages.table.constant.role: "定数バッファーバインドを介して読み取られるシェーダーパラメーター。" -concepts.resources.bufferUsages.table.headings.role: "役割" -concepts.resources.bufferUsages.table.headings.usage: "用途" -concepts.resources.bufferUsages.table.index.role: "インデックス描画で使用されるインデックス。" -concepts.resources.bufferUsages.table.indirect.role: "間接描画または間接ディスパッチのコマンドが読み取る引数。" -concepts.resources.bufferUsages.table.none.role: "バッファーの用途フラグは宣言されていません。" -concepts.resources.bufferUsages.table.storageReadOnly.role: "読み取り専用のシェーダーバインドを介してアクセスするバッファーデータ。" -concepts.resources.bufferUsages.table.storageReadWrite.role: "読み書き可能なシェーダーバインドを介してアクセスするバッファーデータ。" -concepts.resources.bufferUsages.table.transferDst.role: "GPU コピーの転送先ストレージ。" -concepts.resources.bufferUsages.table.transferSrc.role: "GPU コピーの転送元データ。" -concepts.resources.bufferUsages.table.vertex.role: "描画のためにフェッチされる頂点属性。" -concepts.resources.bufferUsages.title: "バッファーの用途" -concepts.resources.description: "リソース記述は、アプリケーションが記憶領域をどう使えるかを定めます。例えば、描画先にし、シェーダーでサンプリングし、CPU に読み戻すテクスチャには、三つの操作に対応する用途フラグが必要です。メモリ配置は CPU のアクセス方法を決めます。データにアクセスできる時点や記憶領域を解放できる時点は、同期と寿命の管理によって決まります。" -concepts.resources.memory.context: "CPU からアクセスできるバッファーでは、{map} がデータを読み書きするためのアドレスを提供します。マッピングも {unmap} も、GPU の処理を待機しません。GPU が書いた結果を CPU で読む前にはその書き込みを待ち、同じバイトを書き換える前には、その領域への GPU アクセスが終わるのを待ちます。" -concepts.resources.memory.description: "{bufferDesc} の {residency} は、想定する CPU アクセスを指定します。" -concepts.resources.memory.details: "常駐区分は CPU アクセスの要件を表します。CPU と GPU が物理メモリを共有するシステムでも、この区分を使います。三角形では {cpuWriteOnly} を使い、小さな頂点バッファーを直接初期化します。大きな静的ジオメトリでは、GPU 専用の記憶領域へアップロードする方が適している場合があります。" -concepts.resources.memory.guidance: "コンテキストから直接作成したテクスチャは GPU の記憶領域を使うため、{textureDesc} に常駐区分のフィールドはありません。CPU メモリとのデータ交換には、アップロードとリードバックを使います。" -concepts.resources.memory.table.cpuReadOnly.cPUAccess: "読み取りのみ" -concepts.resources.memory.table.cpuReadOnly.typicalRole: "CPU へ読み戻すために GPU が生成したデータ" -concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "書き込みのみ" -concepts.resources.memory.table.cpuWriteOnly.typicalRole: "CPU が供給または更新するデータ" -concepts.resources.memory.table.gpuOnly.cPUAccess: "なし" -concepts.resources.memory.table.gpuOnly.typicalRole: "静的ジオメトリと GPU の作業用データ" -concepts.resources.memory.table.headings.cPUAccess: "想定する CPU アクセス" -concepts.resources.memory.table.headings.residency: "常駐区分" -concepts.resources.memory.table.headings.typicalRole: "典型的な役割" -concepts.resources.memory.title: "CPU アクセスとメモリ配置" -concepts.resources.textureUsages.description: "転送フラグは、リソースを GPU コピーの転送元または転送先として使うことを宣言します。CPU から直接アクセスできるかどうかは、メモリ配置によって別途決まります。" -concepts.resources.textureUsages.details: "用途フラグは、テクスチャを何に使えるかを宣言します。用途を切り替える際は、それに応じた{link}が必要です。また、使用するデバイスが、指定したテクスチャフォーマットでその用途をサポートしている必要があります。" -concepts.resources.textureUsages.details.link: "レイアウトと同期" -concepts.resources.textureUsages.table.colorAttachment.role: "レンダーパスのカラーアタッチメント。" -concepts.resources.textureUsages.table.depthStencilAttachment.role: "レンダーパスの深度/ステンシルアタッチメント。" -concepts.resources.textureUsages.table.headings.role: "役割" -concepts.resources.textureUsages.table.headings.usage: "用途" -concepts.resources.textureUsages.table.none.role: "テクスチャの用途フラグは宣言されていません。" -concepts.resources.textureUsages.table.sampled.role: "サンプリング用テクスチャのバインドを介して読み取るテクスチャデータ。" -concepts.resources.textureUsages.table.storage.role: "ストレージテクスチャのバインドを介してシェーダーが読み書きするテクスチャデータ。" -concepts.resources.textureUsages.table.transferDst.role: "GPU コピーの転送先画像ストレージ。" -concepts.resources.textureUsages.table.transferSrc.role: "GPU コピーの転送元画像データ。" -concepts.resources.textureUsages.title: "テクスチャの用途" -concepts.resources.title: "リソース管理" -concepts.resources.transfers.context: "リードバックでは、まず GPU データを内部の読み戻し領域へコピーします。ライブラリは完了したコマンドバッファーを回収するときに、そのデータを指定した CPU の宛先へコピーします。リードバックの送信値に対して {wait} を呼ぶと、両方の処理が完了します。戻るまで宛先を確保したままにし、管理対象メモリは固定してください。" -concepts.resources.transfers.description: "アップロードは CPU データを GPU リソースへコピーし、リードバックはリソースのデータを CPU メモリへコピーします。バッファーとテクスチャの次のメソッドは、転送を完了してから戻ります。" -concepts.resources.transfers.details: "呼び出す前に、他のキューとの競合するアクセスを解消します。メソッド内の待機は自身の転送だけを対象とし、他のキューとの依存関係を設定するものではありません。マッピングしたメモリを直接コピーする場合は、競合する GPU アクセスの完了を呼び出し側で待つ必要があります。" -concepts.resources.transfers.guidance: "他の GPU 処理とまとめて転送を送信するには、{commandBufferUpload} または {commandBufferDownload} で記録します。アップロードの転送元とリードバックの転送先では、メモリを有効に保つ必要のある期間が異なります。" -concepts.resources.transfers.item: "アップロードの呼び出し中に、ライブラリは元データをステージングメモリと呼ばれる内部の一時領域へコピーします。GPU は後でこの領域を読むため、アプリケーションの元ポインターが必要なのは、呼び出しが戻るまでです。" -concepts.resources.transfers.notes: "テクスチャ転送の行ストライドは、CPU データの隣り合う行の間隔をバイトで表します。スライスストライドは、深さ方向に隣り合うスライスの間隔です。転送処理はこれらの値を使い、CPU データとテクスチャの GPU 記憶領域との間でコピーします。GPU の完了と宛先へのコピーが別の段階になる理由は、{link}で説明します。" -concepts.resources.transfers.notes.link: "同期" -concepts.resources.transfers.table.bufferDownload.transfer: "{cpuReadOnly} では、マッピングしたメモリから直接コピーします。それ以外は転送キューにリードバックを送信し、完了を待ちます。" -concepts.resources.transfers.table.bufferUpload.transfer: "{cpuWriteOnly} では、マッピングしたメモリへ直接コピーします。それ以外は転送キューにアップロードを送信し、完了を待ちます。" -concepts.resources.transfers.table.headings.method: "方法" -concepts.resources.transfers.table.headings.transfer: "転送の動作" -concepts.resources.transfers.table.textureTransfers.method: "{textureUpload} / {textureDownload}" -concepts.resources.transfers.table.textureTransfers.transfer: "コピーとテクスチャ遷移をグラフィックスキューに送信し、完了を待ちます。終了時には、選択したサブリソースが指定した最終レイアウトになります。" -concepts.resources.transfers.title: "即時転送とコマンドへの記録" -concepts.resources.usages.description: "{bufferUsages} と {textureUsages} は、リソースの用途を宣言するフラグ列挙型です。それぞれ {bufferDescUsages} と {textureDescUsages} に設定します。複数の用途には、必要なメンバーを {value} で組み合わせます。" -concepts.resources.usages.title: "リソースの用途" -concepts.resources.views.description: "{bufferView} はバッファーの範囲とデータの解釈方法を記述します。{textureView} はサブリソース範囲と、互換性のあるテクスチャ種別やフォーマットを選択します。どちらも既存の記憶領域を参照し、その作成時に宣言した用途に従います。ビューの範囲はアクセス範囲を示すものであり、シェーダーの境界検査が全バックエンドで同じように働くことを保証するものではありません。" -concepts.resources.views.details: "リソース自身のハンドルは既定のビューを提供します。別の範囲や互換性のある解釈方法を選ぶ場合は、独立したビューを作成します。ビューと元リソースはどちらも、GPU が使い終わるまで保持してください。ハンドルだけでは、どちらのオブジェクトも保持されません。いずれかを置き換えたら、古い{link}を含む定数も更新します。" -concepts.resources.views.details.link: "リソースハンドル" -concepts.resources.views.title: "ビューと参照先リソース" -concepts.shaders.binding.context: "コンピュートのサンプルでは、{input} に {inputTextureSampledHandle}、{output} に {outputTextureStorageHandle} を設定します。Slang の {descriptorHandle} の型引数が、各リソースへのアクセス方法を定めます。" -concepts.shaders.binding.description: "{setConstantBuffer} は、現在のパイプラインが定数を読み取るバッファーとバイトオフセットを選択します。シェーダーが使う前に、パラメーターのデータをその領域へアップロードします。以前の GPU 処理が同じ領域をまだ読んでいる場合は、完了を待ってから更新してください。" -concepts.shaders.binding.details: "コマンドバッファー、コンピュートパイプライン、データを設定した定数バッファー、スレッドグループ数が用意できたら、次の順にディスパッチを記録します。定数バッファーは選択中のパイプラインにバインドされるため、先にパイプラインを選択します。" -concepts.shaders.binding.guidance: "ここでは {commandBuffer} に、{computePipeline} と {constantBuffer} のパラメーターを使うディスパッチを記録しています。定数バッファーには {bufferUsagesConstant} の用途が必要で、オフセット 0 はその先頭を指定します。一つのバッファーを複数の定数レコードで共有する場合、各開始オフセットはバックエンドのバインド時アラインメント要件にも従います。これは、レコード内部のフィールド配置とは別の要件です。" -concepts.shaders.binding.notes: "{resourceHandle} は二つの 32 ビットフィールドを持ち、解釈はバックエンドに依存します。値はリソースを作成したコンテキスト内でのみ有効です。" -concepts.shaders.binding.reference: "ハンドルの取得元リソースとビューは、シェーダーの最後のアクセスが完了するまで保持します。テクスチャやビューの置換後は、古いハンドルを含む定数を更新してください。所有権の規則は{link}で説明します。" -concepts.shaders.binding.reference.link: "リソース管理" -concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: "シェーダー型 {t} の構造化要素の読み取り" -concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: "シェーダー型 {t} の構造化要素の読み書き" -concepts.shaders.binding.table.headings.access: "想定されるアクセス" -concepts.shaders.binding.table.headings.cHandle: "C# ハンドル" -concepts.shaders.binding.table.headings.slangFieldType: "Slang フィールド型" -concepts.shaders.binding.table.samplerHandle.access: "テクスチャのサンプリング状態" -concepts.shaders.binding.table.textureSampledHandle.access: "テクスチャの読み取り" -concepts.shaders.binding.table.textureStorageHandle.access: "ストレージテクスチャの読み書き" -concepts.shaders.binding.title: "定数バッファーとリソースハンドル" -concepts.shaders.compilation.description: "{zenithCompiler} は Slang の指定エントリーポイントを {shaderDesc} にコンパイルします。コンテキストの {graphicsApi} に応じ、DirectX 12 には DXIL、Metal には Metal ライブラリ、Vulkan には SPIR-V を生成します。" -concepts.shaders.compilation.details: "{context} という名前のグラフィックスコンテキストを作成してから、実行ファイルと同じディレクトリにコピーした三角形のシェーダーをコンパイルします。" -concepts.shaders.compilation.guidance: "エントリーポイント名 {vSMain} は、シェーダーファイル内の宣言と一致させます。シェーダーのコンパイルとパイプラインの作成は初期化時に行い、描画中はパイプラインを再利用します。作成が終われば、{link}で示すようにシェーダーオブジェクトを解放できます。" -concepts.shaders.compilation.guidance.link: "最初の三角形" -concepts.shaders.compilation.title: "シェーダーのコンパイル" -concepts.shaders.description: "C# と Slang の宣言では、各値をどこに格納し、シェーダーがどうアクセスするかを一致させます。頂点入力レイアウトは頂点属性を、シェーダーバッファーの宣言はパラメーターや配列を記述します。リソースハンドルは、シェーダーが使うリソースを識別します。" -concepts.shaders.dispatch.description: "{dispatch} は、実行するスレッドグループ数を指定します。コンピュートサンプルでは {numthreads} を宣言しているため、一グループは 16 × 16 スレッドです。画像の幅と高さをそれぞれ 16 で割って切り上げると、画像全体を覆えます。17 × 19 の画像には 2 × 2 グループが必要です。シェーダーで各スレッドの座標を調べ、画像の外側なら処理を省きます。" -concepts.shaders.dispatch.details: "宣言したグループサイズは {shaderDescThreadGroupSize} から取得でき、{dispatch} に渡すグループ数の計算に使えます。計算の全体は {computeShaderRendererCs} で確認できます。ディスパッチ後の画像へのアクセスは、{link}の要件に従います。" -concepts.shaders.dispatch.details.link: "同期" -concepts.shaders.dispatch.title: "スレッドグループ" -concepts.shaders.layout.context: "{link}では、画像の寸法と二つのテクスチャハンドルを使ってこの配置を示しています。各フィールドの開始位置はオフセットで明示します。次の宣言では {systemRuntimeInteropServices} と {zenithNET} の名前空間を使用します。" -concepts.shaders.layout.context.link: "コンピュートサンプルの C# 定数" -concepts.shaders.layout.description: "頂点入力の {inputLayout} は、各属性のフォーマット、オフセット、セマンティクスと、頂点間のストライドを記述します。三角形では {float3} の位置の後に {float4} の色を置きます。色のバイトオフセットは 12、頂点一つのサイズは 28 バイトです。{inputLayoutAdd} は属性のフォーマットからこの密な配置を計算します。C# の構造体にパディングがある場合は、それを含めたオフセットとストライドを指定してください。" -concepts.shaders.layout.details: "定数バッファーはシェーダーのパラメーターを、構造化バッファーは型付き要素の配列を格納します。これらの配置は {inputLayout} ではなく、Slang の宣言に従います。C# のフィールドオフセット、要素サイズ、パディングを、コンパイル済みシェーダーの配置に合わせてください。C# のアンマネージ型はバイト列としてコピーできますが、そのメモリ配置がシェーダーの配置と一致するとは限りません。頂点内で密に格納した {float3} も、シェーダーバッファーでは別のアラインメントが必要になる場合があります。" -concepts.shaders.layout.guidance: "シェーダーのパラメーターには、数値とともにリソースハンドルを含められます。ハンドルは既存の記憶領域を指すため、定数バッファーにコピーしてもリソースの内容はコピーされません。" -concepts.shaders.layout.notes: "{computeShaderSlang} の対応する宣言は次のとおりです。" -concepts.shaders.layout.reference: "二つの寸法値が先頭の 8 バイトを占め、その後に二つの 8 バイトのハンドルが続きます。C# サンプルはレコード全体に 256 バイトを確保します。別のレコードでは、フィールドの内容と必要な配置、アラインメントからサイズを決めます。" -concepts.shaders.layout.title: "データ配置" -concepts.shaders.matrices.description: "コンパイラーは行ごとに連続する行優先の行列配置を選択します。{link}では三つの {matrix4x4} をオフセット 0、64、128 に格納します。対応する{detail}では、{mulVectorMatrix} をモデル、ビュー、投影の順に適用します。" -concepts.shaders.matrices.description.detail: "シェーダー" -concepts.shaders.matrices.description.link: "回転する立方体のレンダラー" -concepts.shaders.matrices.details: "格納順序はメモリ内の行列要素の配置を、乗算順序は変換を定めます。C# と Slang で対応する規約を使います。" -concepts.shaders.matrices.title: "行列の規約" -concepts.shaders.title: "シェーダーデータとバインド" -concepts.synchronization.backends.description: "DirectX 12 と Vulkan は、テクスチャ遷移をレイアウトとアクセスの変更として記録します。Zenith.NET の Metal バックエンドでは、{transition} に相当する GPU 操作はありません。代わりにコマンドを描画・計算エンコーダーにまとめ、エンコーダー終了時に可視性バリアを挿入します。連続するコンピュートディスパッチなど、同じエンコーダー内の依存には明示的な {barrier} 呼び出しを使います。" -concepts.synchronization.backends.details: "{link}では、グラフィックスのレンダーパスを開始すると計算エンコーダーが終了し、計算結果を描画処理から読み取れるようになります。連続する二つのコンピュートディスパッチは同じエンコーダー内にとどまるため、間にテクスチャ遷移を記録しても、依存を指定するバリアが必要です。このため、複数のバックエンドで使うコマンド列では、レイアウトとアクセス依存の両方を扱います。" -concepts.synchronization.backends.details.link: "コンピュートサンプル" -concepts.synchronization.backends.title: "バックエンドごとの動作" -concepts.synchronization.barriers.context: "関係するアクセスを含み、キューが対応しているステージを選びます。{barrierStagesAll} は対応するすべてのステージを含みます。依存関係が一部のステージだけに関わる場合は、その範囲に限定できます。" -concepts.synchronization.barriers.description: "同じコマンドバッファーに記録した二つのコンピュートディスパッチで、最初がシミュレーションデータを書き、次がそれを読む場合を考えます。その間にバリアを置くと、後のディスパッチが完了済みの書き込み結果を読み取れます。ストレージバッファーでは、テクスチャレイアウトを遷移させずにアクセスを順序付けられます。" -concepts.synchronization.barriers.details: "最初の引数はデータを生成したステージ、二つ目はそれを使用するステージを指定します。この二つで、ディスパッチ間に必要な実行順序とメモリの可視性を表します。" -concepts.synchronization.barriers.guidance: "{link}では、シミュレーションの各段階の間にこの形のバリアを置きます。どのバリアも、データを生成するディスパッチの後、使用するディスパッチの前に記録します。" -concepts.synchronization.barriers.guidance.link: "FluidTank シミュレーション" -concepts.synchronization.barriers.title: "パイプラインバリア" -concepts.synchronization.dependencies.description: "各リソースで、同じデータに触れるアクセスを確認します。一方でも書き込みを行う場合は、必要な順序を保ちます。二つの読み取りは競合しませんが、テクスチャレイアウトや提示の要件は満たす必要があります。CPU からの更新やリソースの解放も、対象領域を GPU が使い終わるまで待ちます。" -concepts.synchronization.dependencies.details: "操作の実行場所に応じて、使う仕組みを選びます。" -concepts.synchronization.dependencies.guidance: "一つの処理に複数の同期手段が必要な場合もあります。例えば、別のキューで生成したテクスチャには、送信間の依存関係と、次の用途に適したレイアウトの両方が必要です。どちらも、それ自体は CPU の待機を必要としません。CPU がデータにアクセスしたり解放したりする場合に、CPU 側で待機します。" -concepts.synchronization.dependencies.table.cpuAccess.mechanism: "該当する完了値に対して {wait} を呼び出します。" -concepts.synchronization.dependencies.table.cpuAccess.situation: "CPU のアクセスやリソース解放に GPU の完了が必要な場合" -concepts.synchronization.dependencies.table.crossQueue.mechanism: "生成側の {timelineValue} を使用側の {submit} に渡します。" -concepts.synchronization.dependencies.table.crossQueue.situation: "別のキューで生成したデータを使用する場合" -concepts.synchronization.dependencies.table.headings.mechanism: "メカニズム" -concepts.synchronization.dependencies.table.headings.situation: "状況" -concepts.synchronization.dependencies.table.layoutChange.mechanism: "以前のレイアウトと次のレイアウトを指定した {commandBufferTransition}。" -concepts.synchronization.dependencies.table.layoutChange.situation: "テクスチャサブリソースの使用方法の変更" -concepts.synchronization.dependencies.table.pipelineStages.mechanism: "生成側ステージと使用側ステージを指定した {commandBufferBarrier}。" -concepts.synchronization.dependencies.table.pipelineStages.situation: "コマンドストリーム内の依存する GPU ステージ" -concepts.synchronization.dependencies.title: "アクセス間の依存" -concepts.synchronization.description: "同期は、共有データへのアクセス順序を定め、後の操作が必要な結果を読み取れるようにします。書き込みから読み取りへの依存では、書き込む側を生成側、読む側を使用側と呼びます。バリアとテクスチャ遷移は GPU のアクセスを調整し、タイムラインは送信間の依存を設定したり、CPU で GPU の完了を待ったりするために使います。" -concepts.synchronization.layouts.context: "以前の内容を破棄できる場合は、遷移前のレイアウトに {undefined} を指定できます。例えば、新しい画像や全体をクリアするアタッチメントが該当します。ロード、サンプリング、蓄積のために内容を保持する場合は、直前のアクセスのレイアウトを使います。" -concepts.synchronization.layouts.description: "用途フラグは、テクスチャの許可された用途を宣言します。{textureLayout} は、コマンド列のある時点で、mip レベルと配列レイヤーで特定したサブリソースにどうアクセスするかを表します。アクセス方法が変わるときに遷移を記録します。例えばコンピュートサンプルでは、{storage} レイアウトで出力テクスチャへ書き込んだ後、グラフィックスパスでサンプリングする準備をします。" -concepts.synchronization.layouts.details: "ここでは {outputTexture} を {sampledStorage} 用途で作成し、対象サブリソースは {storage} です。{default} は mip レベル 0 と配列レイヤー 0 を選びます。他のレベルとレイヤーには影響しません。" -concepts.synchronization.layouts.guidance: "{transition} には、サブリソースを前回使用したときのレイアウトを渡します。アプリケーションはコマンドを記録し、テクスチャを描画ステージ間で渡す際に、この状態を追跡します。" -concepts.synchronization.layouts.title: "テクスチャレイアウト" -concepts.synchronization.readback.description: "{isCompleted} は GPU の完了を報告します。記録したリードバックには、その後にもう一つの処理があります。内部の読み戻し領域からアプリケーションの宛先メモリへ結果をコピーする処理です。" -concepts.synchronization.readback.details: "{commandBufferDownload} は、この内部領域への GPU コピーを記録します。送信完了後、ライブラリはコマンドバッファーの回収時に CPU コピーを行います。リードバックの送信値に対して {wait} を呼ぶと、GPU を待機した後、そのキューの完了済みバッファーを処理し、両方のコピーが完了します。戻るまで宛先を確保し、管理対象メモリは固定したままにしてください。" -concepts.synchronization.readback.guidance: "{isCompleted} の確認だけでは、最後の CPU コピーは行われません。別のキューで待機しても、リードバックを管理するキューのバッファーは回収されません。アップロードとリードバックが直接アクセスや一時領域を使う条件は、{link}で説明します。" -concepts.synchronization.readback.guidance.link: "リソース管理" -concepts.synchronization.readback.title: "リードバックの完了" -concepts.synchronization.reuse.description: "三角形では、各フレームの完了を待ってからデータを再利用します。フレームの処理を並行して進める場合は、処理中の各フレームに個別の変更可能な記憶領域を用意し、再び使える時点を追跡します。データを変更する前にはその領域への GPU アクセスを、リソースを解放する前にはそのすべての使用を待ちます。" -concepts.synchronization.reuse.details: "リサイズと終了も、同じ順序で処理します。新しい使用を止め、既存の使用が終わるのを待ってから、リソースを置き換えるか解放します。{swapChainResize} やリソース、コンテキストの解放を呼ぶ前に、この順序を確保してください。三角形では毎フレーム待機しているため、コールバックの間でリサイズできます。" -concepts.synchronization.reuse.guidance: "{swapChainPresent} は提示後にグラフィックスキューへシグナルを送り、完了を待ちます。そのため、明示的な送信待ちを除いても、三角形は提示時に待機します。別キューへ独立して送信した処理は、完了を個別に追跡する必要があります。" -concepts.synchronization.reuse.title: "リソースの再利用" -concepts.synchronization.timelines.context: "使用側の処理後に CPU で結果を読んだり、共有データを上書きしたり、リソースを解放したりする場合は、その送信を待ちます。" -concepts.synchronization.timelines.description: "タイムラインは増加する値でキューの完了を表します。{submit} が返す {timelineValue} はタイムラインと送信の値を含みます。異なるタイムラインの数値 {value} は直接比較できません。" -concepts.synchronization.timelines.details: "同じコンテキストの二つのキューで記録した {producer} と {consumer} があり、後者が前者の書いたデータを使うとします。次の依存関係で送信します。" -concepts.synchronization.timelines.guidance: "使用側のキューは、渡された完了値に到達するのを待ってからコマンドを実行します。CPU は {producedWait} を呼ばずに処理を続けられます。共有リソースは {consumed} が完了するまで保持し、使用側のアクセスに必要なテクスチャ遷移も記録します。" -concepts.synchronization.timelines.notes: "{queueTimelineSignal} の戻り値も、{wait} で待機したり、別キューの依存関係に使ったりできます。{signal} は、それまでに送信した処理の後に完了点を置きます。GPU がその処理を終えると、完了点に到達します。" -concepts.synchronization.timelines.title: "タイムラインとキュー間の依存" -concepts.synchronization.title: "同期" -home.actions.reference: "API を参照" -home.actions.tutorial: "三角形から始める" -home.entries.description: "チュートリアル、サンプル、API リファレンス" -home.entries.label: "ドキュメントの構成" -home.entries.reference.action: "API を探索" -home.entries.reference.category: "リファレンス" -home.entries.reference.description: "API の型、メンバー、宣言を調べる" -home.entries.reference.title: "API リファレンス" -home.entries.samples.action: "サンプルを参照" -home.entries.samples.category: "サンプル" -home.entries.samples.description: "描画と計算の手法を実行できるサンプルで学ぶ" -home.entries.samples.title: "サンプル" -home.entries.title: "ドキュメント" -home.entries.tutorial.action: "チュートリアルを開始" -home.entries.tutorial.category: "チュートリアル" -home.entries.tutorial.description: "空のプロジェクトから、最初の三角形を描くまで" -home.entries.tutorial.title: "最初の三角形" -home.introduction.accent: "クロスプラットフォームのグラフィックス" -home.introduction.description: "Zenith.NET は、共通の API で DirectX、Metal、Vulkan の描画と計算を扱うライブラリです" -home.introduction.title: ".NET でつくる{lineBreak}{accent}" -home.meta.description: "DirectX、Metal、Vulkan に共通の API を使い、.NET でクロスプラットフォームの描画・計算アプリケーションを開発" -home.scene.description: "回転する図形を操作できます。ドラッグまたは矢印キーで視点を調整してください。" -home.scene.label: "ジオメトリ表示" -home.scene.surface: "サーフェス" -home.scene.wireframe: "ワイヤーフレーム" -home.title: ".NET 向けのモダンな RHI" -learning.concepts.description: "リソース用途の選択、シェーダーデータの記述、GPU 実行の調整" -learning.concepts.execution.description: "コマンドの記録と送信、リソースの寿命" -learning.concepts.platforms.description: "ネイティブの提示と UI 描画コントロール" -learning.concepts.resources.description: "リソースの用途、メモリ配置、ビュー" -learning.concepts.shaders.description: "C# と Slang のデータ配置とバインドの規約" -learning.concepts.synchronization.description: "依存関係、可視性、完了" -learning.concepts.title: "基本概念" -learning.description: "まずは三角形のチュートリアルで、最初のアプリケーションを作成します。その後は必要に応じて、リソース管理、シェーダーデータ、同期の解説を読むか、実装したい手法のサンプルを選んでください。" -learning.entries.samples.action: "サンプルを参照" -learning.entries.samples.description: "ジオメトリ、計算、レイクエリ、メッシュシェーディングの C# と Slang による実装" -learning.entries.tutorial.action: "チュートリアルを開く" -learning.entries.tutorial.description: "ウィンドウを開き、三角形を描くコンソールアプリケーション" -learning.meta.description: "Zenith.NET のプログラミングモデルを学ぶチュートリアルと概念解説" -learning.title: "学習" -reference.description: "リソース、コマンド、プラットフォーム統合のリファレンス" -reference.entries.commands.description: "描画、計算、転送のコマンド" -reference.entries.commands.label: "コマンドを記録" -reference.entries.context.description: "選択したバックエンドの GPU リソース作成" -reference.entries.context.label: "ここから開始" -reference.meta.description: "Zenith.NET の名前空間、型、メンバー" -reference.navigation.core: "コア API リファレンス" -reference.title: "API リファレンス" -samples.computeShader.description: "サンプルは {assetsTexturesShokoPng} を読み込み、コンピュートディスパッチでグレースケールに変換して、出力テクスチャを表示します。変換は一度だけ行い、以降のフレームでは同じ結果を表示します。レンダラーでは、サンプリング用と書き込み用テクスチャのバインド、画像全体を覆うためのグループ数の切り上げ、シェーダー内の境界検査を確認できます。" -samples.computeShader.details: "{computeShaderRendererCs} · {computeShaderSlang}" -samples.computeShader.title: "コンピュートシェーダー" -samples.cube.description: "立方体では、インデックス付き描画、定数バッファー内のモデル・ビュー・投影行列、深度テストを加えます。{d32FloatS8UInt} の深度ステンシルテクスチャはリサイズ時に再作成します。" -samples.cube.details: "{spinningCubeRendererCs} · {spinningCubeSlang}" -samples.cube.title: "回転する立方体" -samples.description: "各サンプルは C# のレンダラーと Slang シェーダーを組み合わせ、一つの手法を扱います。アプリケーションの準備から描画までの手順は、{link}で説明します。" -samples.description.link: "最初の三角形" -samples.execution.description: "{link} プロジェクトを実行し、コンソールメニューからサンプルを選びます。" -samples.execution.description.link: "ZenithTutorials" -samples.execution.title: "サンプルの実行" -samples.host.description: "{appCs} はコンテキスト、ウィンドウ、スワップチェーンを初期化します。各フレームではコマンドバッファーを取得し、選択したレンダラーを呼び、送信と提示を行います。{iRendererCs} は更新、描画、リサイズ、解放の操作を定義します。" -samples.host.details: "コンピュートとレイトレーシングのレンダラーは、オフスクリーンテクスチャを生成します。{texturePresenterCs} と {presentTextureSlang} がその内容を現在の drawable に描画し、共通ホストがコマンドを送信してフレームを提示します。" -samples.host.title: "ホストと提示" -samples.indirectDrawing.description: "間接描画では、インデックス付き描画の引数バッファーとインスタンスごとの構造化データを使い、複数の立方体を描きます。CPU が引数を設定し、変換を更新します。" -samples.indirectDrawing.details: "{indirectDrawingRendererCs} · {indirectDrawingSlang}" -samples.indirectDrawing.title: "間接描画" -samples.meshShading.description: "タスクシェーダーが球のインスタンスをカリングし、残ったインデックスを、ジオメトリを生成するメッシュシェーダーへ渡します。パイプライン作成前に {contextCapabilitiesMeshShadingSupported} を確認します。" -samples.meshShading.details: "{meshShadingRendererCs} · {meshShadingSlang}" -samples.meshShading.title: "メッシュシェーディング" -samples.rayTracing.description: "床と手続き的な球の下位・上位アクセラレーション構造を構築し、コンピュートシェーダー内でインラインレイクエリを実行します。初期化前に {contextCapabilitiesRayTracingSupported} を確認します。" -samples.rayTracing.details: "{rayTracingRendererCs} · {rayTracingSlang}" -samples.rayTracing.title: "レイトレーシング" -samples.title: "サンプル" -samples.triangle.description: "頂点バッファーと対応する入力レイアウトを関連付け、グラフィックスパイプラインで三つの頂点から三角形を描きます。" -samples.triangle.details: "{helloTriangleRendererCs} · {helloTriangleSlang} · {link}" -samples.triangle.details.link: "完全なチュートリアル" -samples.triangle.title: "Hello Triangle" -samples.workloads.description: "メインリポジトリの {link} にある応用例は、ライブラリのソースを直接参照しています。" -samples.workloads.description.link: "Experiments ディレクトリ" -samples.workloads.details: "ウィンドウ付きの実験は同じ Windows、macOS、Linux/X11 の提示経路を使います。Avalonia、WinForms、WPF、WinUI/Uno、MAUI のコントロールは、フレーム処理と実装ソースを含めて{link}で紹介します。" -samples.workloads.details.link: "プラットフォーム統合" -samples.workloads.table.cornellBox.example: "{link}" -samples.workloads.table.cornellBox.example.link: "CornellBox" -samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: "パストレーシング、ノイズ除去、トーンマッピング、アップスケーリング、ImGui による操作を扱います。レイトレーシング対応が必要です。" -samples.workloads.table.fluidTank.example: "{link}" -samples.workloads.table.fluidTank.example.link: "FluidTank" -samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: "計算による流体シミュレーション、段階間の依存、複数パスの表面描画を扱います。" -samples.workloads.table.headings.example: "例" -samples.workloads.table.headings.whatItDemonstratesAndRequires: "手法と要件" -samples.workloads.table.inkCanvas.example: "{link}" -samples.workloads.table.inkCanvas.example.link: "InkCanvas" -samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: "ネイティブウィンドウで Skia の描画と入力処理を行います。対象プラットフォームのバックエンドと Skia ネイティブライブラリが必要です。" -samples.workloads.table.platformDetection.example: "{link}" -samples.workloads.table.platformDetection.example.link: "PlatformDetection" -samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: "各バックエンドのコンテキスト作成を試み、デバイスの機能を報告します。作成に失敗した場合は非対応と表示しますが、原因にはデバイス、ドライバー、実行時依存の不足が考えられます。" -samples.workloads.title: "より大きなアプリケーション" -tutorial.context.description: "{graphicsContext} はバックエンドを介してアプリケーションを GPU に接続し、描画リソースを作成するためのメソッドを提供します。" -tutorial.context.details: "コンテキストの初期化を{emphasis}に追加します。" -tutorial.context.details.emphasis: "using ディレクティブの後、{iWindowWindow} の前" -tutorial.context.guidance: "各分岐でプラットフォームに応じたバックエンドを選び、検証を要求します。{validationMessage} のメッセージはコンソールに出力します。" -tutorial.context.imports: "{programCs} の先頭に、次の using ディレクティブを追加します。" -tutorial.context.title: "グラフィックスコンテキスト" -tutorial.description: "このチュートリアルでは、空の .NET コンソールプロジェクトから始め、ウィンドウを開いて色付きの三角形を描くアプリケーションを作成します。" -tutorial.details: "このチュートリアルでは、空のウィンドウ、単色の背景、色付きの三角形の三段階で結果を確認します。各段階でアプリケーションを実行し、表示を確かめてから次へ進んでください。" -tutorial.draw.context: "{draw} の引数は次のとおりです。" -tutorial.draw.description: "{windowRender} コールバックの {addTheTriangleDrawCommandsHereLater} を、次のコマンドで置き換えます。位置は {beginRenderPass} と {endRenderPass} の間です。" -tutorial.draw.details: "{setPipeline} はシェーダーと描画状態を選択します。頂点のバインドはパイプラインの入力レイアウトに従って解釈されるため、その前に呼びます。" -tutorial.draw.guidance: "{setVertexBufferVertexBuffer} は、転送済みの頂点データをバイトオフセット 0 から入力スロット 0 にバインドします。これは {inputLayouts} の唯一の要素に対応します。" -tutorial.draw.notes: "これらの呼び出しは描画コマンドを記録します。既存の {submitWait} がコマンドを送信して GPU の完了を待ち、その後 {present} が完成した画像の表示を要求します。三角形の外側にも決まった背景色を表示するため、パスの先頭のクリア処理は残します。" -tutorial.draw.table.firstInstance.meaning: "インスタンスの番号付けをゼロから開始します。" -tutorial.draw.table.firstVertex.meaning: "バッファー内の最初の頂点から開始します。" -tutorial.draw.table.headings.argument: "引数" -tutorial.draw.table.headings.description: "値" -tutorial.draw.table.headings.meaning: "意味" -tutorial.draw.table.instanceCount.meaning: "三角形を一つ描きます。" -tutorial.draw.table.vertexCount.meaning: "3 つの頂点を読み取ります。" -tutorial.draw.title: "描画コマンド" -tutorial.execution.description: "{firstTriangle} プロジェクトをビルドして実行します。" -tutorial.execution.details: "暗い背景の上に、上が赤、右下が緑、左下が青の三角形が表示されます。内部の色は頂点色を補間したもので、滑らかなグラデーションになります。" -tutorial.execution.guidance: "リサイズすると画像のピクセル寸法が変わりますが、頂点座標は変わりません。ビューポートは同じ座標を新しい幅と高さに対応付けるため、ウィンドウの縦横比を変えると三角形が伸縮します。" -tutorial.execution.title: "アプリケーションの実行" -tutorial.frame.commands.context: "{endRenderPass} の後、二回目の遷移で出力テクスチャを提示可能な状態にします。{submit} は記録を終えてコマンドを送信し、{wait} はその完了まで待機します。続く {present} が描画済み画像の表示を要求します。" -tutorial.frame.commands.description: "レンダーパスは、同じアタッチメントに書き込む描画操作をまとめます。このパスではスワップチェーンの drawable が色の出力先です。{colorAttachmentClear} は、アタッチメントを RGBA 色で初期化し、パス終了時に内容を保持するよう指定します。{beginRenderPass} は、この設定でパスを開始するコマンドを記録します。" -tutorial.frame.commands.details: "コレクションにはカラーアタッチメントを一つ入れます。{null} は深度ステンシルアタッチメントを使わない指定です。" -tutorial.frame.commands.guidance: "{beginRenderPass} は、アタッチメント全体を覆うビューポートとシザーを設定します。ビューポートは描画座標をピクセル位置に変換し、シザーは書き込める範囲を制限します。" -tutorial.frame.commands.title: "クリア、送信、提示" -tutorial.frame.description: "まず、ウィンドウを単色の背景で埋めます。この操作をクリアと呼びます。背景が表示されれば、サーフェス、コマンド送信、提示の流れが動いています。ここに三角形の頂点とシェーダーを加えていきます。" -tutorial.frame.details: "Silk.NET は描画のタイミングでコールバックを呼びます。この例では経過時間の引数を使わないため、パラメーター名を {value} にしています。コールバックを{emphasis}に登録します。" -tutorial.frame.details.emphasis: "{windowRun} の前" -tutorial.frame.target.description: "{graphicsQueueCommandBuffer} は記録可能なコマンドバッファーを返します。記録は GPU の処理を定義する段階であり、実行は送信後に始まります。" -tutorial.frame.target.details: "テクスチャレイアウトは、操作がテクスチャにどうアクセスするかを表します。最初の {transition} で、出力テクスチャをカラーアタッチメントとして使える状態にします。ここでの {default} は mip レベル 0 と配列レイヤー 0、つまり出力テクスチャの基本画像を選びます。このパスでは画像全体をクリアするため、{undefined} を指定して以前の内容を破棄できます。" -tutorial.frame.target.guidance: "提示すると別の画像に切り替わることがあるため、毎フレーム、現在の drawable を取得します。" -tutorial.frame.target.title: "drawable の準備" -tutorial.frame.title: "最初のフレーム" -tutorial.geometry.data.description: "頂点配列を{emphasis}に追加します。以後のリソース初期化も、説明する順序でこのコールバックの前に置きます。" -tutorial.geometry.data.description.emphasis: "{windowRender} の前" -tutorial.geometry.data.details: "各要素は {vertex} を作り、内側の二つの {new} が {vector3} の位置と {vector4} の色を渡します。位置は上、右下、左下の頂点です。頂点シェーダーで第四成分 {w} を加えます。w が 1 なので x と y は正規化デバイス座標でもあり、-1 と +1 が画像の端、0 が中央を表します。この意味はピクセル寸法に依存しません。" -tutorial.geometry.data.guidance: "各色は赤、緑、青、アルファの成分を持ち、アルファは 1 です。三つの頂点はすべて z = 0 で、同じ平面上にあります。" -tutorial.geometry.data.title: "頂点の位置と色" -tutorial.geometry.description: "三角形の各頂点には位置と色があります。GPU は三つの位置から形を決め、頂点色を補間して内部の色を求めます。" -tutorial.geometry.format.description: "頂点の宣言を{emphasis}に追加します。" -tutorial.geometry.format.description.emphasis: "{programCs} の末尾、解放処理の後" -tutorial.geometry.format.details: "{file} は型の使用範囲を {programCs} に限定し、{layoutKindSequential} はフィールドの宣言順を保ちます。{position} は三つの 32 ビット浮動小数点数を含み、バイトオフセット 0 から始まります。{color} は四つを含み、バイトオフセット 12 から始まります。したがって、頂点一つの大きさは 28 バイトです。後で入力レイアウトにこの配置を指定し、GPU が各フィールドを正しく読めるようにします。" -tutorial.geometry.format.imports: "ベクトル型と構造体のレイアウト属性を使うため、{programCs} の先頭に次の using ディレクティブを追加します。" -tutorial.geometry.format.title: "頂点の表現" -tutorial.geometry.title: "頂点データ" -tutorial.geometry.upload.context: "{fixed} は、配列のアドレスを使用している間、ガベージコレクターが配列を移動しないようにします。この CPU 書き込み可能なバッファーでは、{upload} がメモリをマッピングし、データをコピーして、マッピングを解除してから戻ります。そのため、配列の固定が必要なのは呼び出し中だけです。頂点は初期化時に一度アップロードし、バッファーは描画が終わるまで保持します。" -tutorial.geometry.upload.description: "描画時に GPU が読み取れるよう、頂点を {buffer} に格納します。配列の直後に、バッファーの確保とアップロードを追加します。" -tutorial.geometry.upload.details: "サイズは {sizeofVertexVerticesLength}、つまり 28 バイトの頂点三つで 84 バイトです。{bufferUsagesVertex} は頂点入力用途、{cpuWriteOnly} は CPU による直接初期化を許可します。記述のストライドは要素サイズを表します。各属性の読み方は、後で作る入力レイアウトが定めます。" -tutorial.geometry.upload.guidance: "確保しただけではデータは入りません。{upload} が、データ記述に渡した元ポインターとバイト数を使い、配列をバッファーのオフセット 0 にコピーします。" -tutorial.geometry.upload.imports: "Zenith.NET のバッファー型を {systemBuffer} と区別するため、{programCs} の using ディレクティブに {bufferAlias} を追加します。" -tutorial.geometry.upload.notes: "{programCs} 末尾の解放処理で、{swapChainDispose} の直前に {vertexBufferDispose} を加えます。大きな静的ジオメトリ向けの GPU 専用メモリと転送は{link}で説明します。" -tutorial.geometry.upload.notes.link: "リソース管理" -tutorial.geometry.upload.title: "バッファーの確保と転送" -tutorial.input.description: "GPU は位置や色などの頂点属性がどこにあるかを知る必要があります。入力レイアウトで各属性のフォーマットとバイトオフセットを指定し、ストライドで次の頂点までのバイト数を示します。シェーダー作成後に次のコードを加えます。" -tutorial.input.details: "{inputLayoutAdd} は属性を順番に並べ、各属性のサイズをストライドに加算します。オフセットは C# の構造体を調べて得るのではなく、ここで指定したフォーマットから計算されます。この二つのフィールドでは、次の配置になります。" -tutorial.input.guidance: "{semanticIndex} の既定値は 0 で、シェーダーの {pOSITION0} と {cOLOR0} に対応します。位置と色は一つの頂点バッファーに格納するため、パイプラインにはスロット 0 の入力レイアウトを一つ指定します。C# のフィールド順やパディングを変えた場合は、入力レイアウトも合わせて変更してください。" -tutorial.input.table.headings.byteOffset: "バイトオフセット" -tutorial.input.table.headings.cField: "C# フィールド" -tutorial.input.table.headings.format: "フォーマット" -tutorial.input.table.headings.shaderInput: "シェーダー入力" -tutorial.input.table.nextVertex.cField: "次の頂点" -tutorial.input.table.nextVertex.format: "合計ストライド:28 バイト" -tutorial.input.table.nextVertex.shaderInput: "次の入力レコード" -tutorial.input.table.vertexColor.format: "{float4} (16 バイト)" -tutorial.input.table.vertexPosition.format: "{float3} (12 バイト)" -tutorial.input.title: "頂点入力レイアウト" -tutorial.lifecycle.description: "各フレームは次の順で進みます。" -tutorial.lifecycle.details: "ウィンドウを閉じると {run} が戻り、解放処理へ進みます。各フレームで送信した処理の完了を待っているため、その処理で使用したリソースは解放できます。{windowRun} の後に置く解放処理の全体は次のとおりです。" -tutorial.lifecycle.guidance: "スワップチェーンはネイティブウィンドウを破棄する前に、コンテキストはそのリソースを解放した後に解放します。送信済みコマンドバッファーはキューが回収し、drawable はスワップチェーンが管理するため、どちらにも個別の {dispose} 呼び出しは不要です。" -tutorial.lifecycle.title: "フレームの流れと終了処理" -tutorial.pipeline.behavior: "入力レイアウトの後にパイプラインを作成します。" -tutorial.pipeline.context: "{cullNone} は面のカリングを無効にします。頂点が画面上で時計回りに並んでいても、反時計回りに並んでいても、三角形を描画します。" -tutorial.pipeline.description: "{graphicsPipeline} は、頂点レイアウト、二つのシェーダー、プリミティブの組み立てとアタッチメントへの出力設定をまとめます。" -tutorial.pipeline.details: "頂点とフラグメントの処理はシェーダーが担当します。パイプラインの残りの設定では、プリミティブの組み立て、面のカリング、深度テスト、ブレンドを指定します。" -tutorial.pipeline.guidance: "パイプラインのカラーフォーマットはパスのアタッチメントに合わせ、{swapChainDescFormat} から取得します。{count1} は一ピクセル一サンプルです。" -tutorial.pipeline.item: "{triangleList} は連続する三つの頂点を一組として、三角形を組み立てます。" -tutorial.pipeline.notes: "{depthNone} は深度テストと深度書き込みを無効にします。深度アタッチメントを使わないパスと対応します。" -tutorial.pipeline.reference: "{opaque} はブレンドを無効にします。三角形の内部では、フラグメントシェーダーの色が背景を置き換えます。" -tutorial.pipeline.title: "グラフィックスパイプライン" -tutorial.pipeline.usage: "シェーダーオブジェクトはパイプライン作成後に解放できます。パイプラインは描画中保持し、終了処理で {vertexBufferDispose} の前に {pipelineDispose} を加えます。" -tutorial.presentation.title: "グラフィックスコンテキストと提示" -tutorial.project.context: "プロジェクトのビルド設定で {emphasis}({allowUnsafeBlocks})を有効にします。ウィンドウ補助コードのネイティブ呼び出しと頂点の転送に unsafe コードが必要です。" -tutorial.project.context.emphasis: "アンセーフコードの許可" -tutorial.project.description: ".NET 10 を対象とする、{firstTriangle} という名前の C# コンソールプロジェクトを作成します。" -tutorial.project.details: "プロジェクトに次の NuGet パッケージを追加します。" -tutorial.project.guidance: "{zenithNET} が共通の描画 API を、三つのバックエンドパッケージが各実装を提供します。{zenithNETCompiler} は後で作る Slang シェーダーを対象バックエンド向けにコンパイルします。Silk.NET はウィンドウの作成とイベント処理を担当します。" -tutorial.project.title: "プロジェクトの準備" -tutorial.requirements.context: "{link}とその{detail}が、このチュートリアルの参照実装です。" -tutorial.requirements.context.detail: "共有ホスト" -tutorial.requirements.context.link: "Hello Triangle サンプル" -tutorial.requirements.description: "{emphasis} と C# の基礎知識が必要です。アプリケーションの対象フレームワークは {net10} です。GPU とドライバーは、プラットフォームごとに選ぶ次のバックエンドに対応している必要があります。" -tutorial.requirements.description.emphasis: ".NET 10 SDK" -tutorial.requirements.guidance: "Zenith.NET はアプリケーションから渡されたネイティブサーフェスへ描画します。Silk.NET.Windowing がウィンドウとイベントを管理します。macOS の提示には {cAMetalLayerCs} で表される Metal レイヤーを使い、補助コードがウィンドウへ取り付けます。" -tutorial.requirements.table.headings.graphicsBackend: "グラフィックスバックエンド" -tutorial.requirements.table.headings.platform: "プラットフォーム" -tutorial.requirements.table.linux.graphicsBackend: "Vulkan 1.4" -tutorial.requirements.table.linux.platform: "Linux(X11 または XWayland)" -tutorial.requirements.table.macOS.graphicsBackend: "Metal 4" -tutorial.requirements.table.macOS.platform: "macOS" -tutorial.requirements.table.windows.graphicsBackend: "DirectX 12" -tutorial.requirements.table.windows.platform: "Windows" -tutorial.requirements.title: "前提条件" -tutorial.resize.context: "アプリケーションをもう一度ビルドして実行します。リサイズしても背景がウィンドウ全体を覆うことを確認してください。新しいレンダーパスでは、変更後のアタッチメントの寸法からビューポートとシザーが設定されます。描画コールバックはそのまま残し、後でこのパスに三角形の描画を加えます。" -tutorial.resize.description: "フレームバッファーの寸法が変わったら、スワップチェーンも合わせて変更します。描画コールバックの後、{windowRun} の前に {framebufferResize} のコールバックを登録します。" -tutorial.resize.details: "ウィンドウの論理寸法ではなく、ピクセル単位の{link}を受け取ります。最小化によって幅か高さがゼロになった場合、リサイズコールバックはスワップチェーンを変更しません。描画コールバックも、どちらかの寸法がゼロの間はそのまま戻ります。有効な寸法に戻るまで描画を中断するためです。" -tutorial.resize.details.link: "フレームバッファーサイズの変化" -tutorial.resize.guidance: "描画コールバックは、送信したフレームの完了を待ってから {present} を呼びます。そのため、リサイズコールバックがスワップチェーンの画像を置き換える時点では、以前のフレームによる処理は終わっています。完了とリソースの寿命に関する条件は、{link}で詳しく説明します。" -tutorial.resize.guidance.link: "同期" -tutorial.resize.title: "リサイズ" -tutorial.shaders.compilation.context: "{appContextBaseDirectory} を使うと、コピーしたシェーダーをアプリケーションの出力ディレクトリから読み込みます。別の作業ディレクトリから起動しても、ファイルを探す場所は変わりません。" -tutorial.shaders.compilation.description: "{triangleSlang} のファイルプロパティで {emphasis} を {detail} に設定します。ビルド時にシェーダーが実行ファイルの隣へコピーされます。" -tutorial.shaders.compilation.description.detail: "新しい場合はコピーする" -tutorial.shaders.compilation.description.emphasis: "出力ディレクトリにコピー" -tutorial.shaders.compilation.details: "{programCs} に戻り、頂点のアップロード後、描画コールバック前にシェーダーの初期化を追加します。" -tutorial.shaders.compilation.guidance: "{zenithCompiler} は {contextGraphicsApi} のバックエンド向けにソースをコンパイルします。{createShader} は、コンパイル済みの記述からシェーダーオブジェクトを作成します。エントリーポイント名 {vSMain} と {fSMain} は、Slang ファイルに定義した二つの関数を選択します。" -tutorial.shaders.compilation.title: "シェーダーのコンパイル" -tutorial.shaders.context: "{fSInput} は二つのシェーダーステージをつなぎます。頂点シェーダーはクリップ空間の位置を {sVPOSITION} に書き込み、GPU はその位置から三角形の見える範囲を判断します。{cOLOR0} は頂点色を渡すフィールドです。色は三角形の内部で補間されてから、フラグメントシェーダーに届きます。両ステージで色の型とセマンティクスを一致させる必要があります。" -tutorial.shaders.description: "シェーダーは GPU 上で実行するプログラムです。頂点シェーダーは各頂点の位置を決め、フラグメントシェーダーは画像の覆われた位置の色を決めます。両ステージを一つの Slang ファイルに書き、それぞれにエントリーポイントを定義します。エントリーポイントは、そのステージの実行が始まる関数です。" -tutorial.shaders.details: "{triangleSlang} を作成し、次の入出力構造体を書きます。" -tutorial.shaders.fragment.description: "同じファイルにフラグメントのエントリーポイントを追加します。" -tutorial.shaders.fragment.details: "ラスタライズは三角形が画像を覆う範囲を調べ、その位置にフラグメントを生成します。各フラグメントの色は、三つの頂点色を補間して求めます。{fSMain} がその色を返し、{sVTARGET} が最初のカラーアタッチメントへの出力を指定します。" -tutorial.shaders.fragment.title: "フラグメントシェーダー" -tutorial.shaders.guidance: "{vSInput} は頂点シェーダーの入力です。{pOSITION0} と {cOLOR0} はセマンティクスによって属性を対応付けます。C# のフィールド名だけでは、この対応は決まりません。" -tutorial.shaders.title: "シェーダーステージ" -tutorial.shaders.vertex.description: "{triangleSlang} に頂点のエントリーポイントを追加します。" -tutorial.shaders.vertex.details: "GPU は入力頂点ごとにこの関数を呼びます。同次座標 {w} を追加し、色をそのまま渡します。頂点処理後に位置を w で割りますが、ここでは 1 なので x、y、z は変わらず、正規化デバイス座標として直接解釈できます。" -tutorial.shaders.vertex.title: "頂点シェーダー" -tutorial.surface.description: "ネイティブの提示先を{emphasis}に指定します。" -tutorial.surface.description.emphasis: "{windowCenter} の後、{windowRun} の前" -tutorial.surface.details: "フレームバッファーは、ウィンドウが表示するピクセル画像です。{surface} はネイティブの提示先と寸法を記述し、{framebufferSize} はピクセル単位のサイズを返します。表示倍率によっては、ウィンドウの論理サイズと異なります。" -tutorial.surface.guidance: "サーフェスにはバックエンドが必要とするネイティブハンドルを渡します。Windows は Win32 ウィンドウ、Linux は X11 のディスプレイとウィンドウ、macOS は取り付けた Metal レイヤーを使います。" -tutorial.surface.title: "ネイティブサーフェス" -tutorial.swapChain.context: "スワップチェーンはコンテキストとウィンドウの両方に依存します。{programCs} 末尾の {windowDispose} を次の解放順序に置き換えます。" -tutorial.swapChain.description: "サーフェス記述の直後にスワップチェーンを作成します。" -tutorial.swapChain.details: "{swapChain} はウィンドウが提示する画像を管理します。{drawable} は現在の画像を、API の画像リソースである {texture} として返します。描画後に {present} が表示を要求し、次の drawable へ進みます。" -tutorial.swapChain.guidance: "{b8G8R8A8UNorm} は青、緑、赤、アルファの順に各 8 ビットを格納します。{uNorm} は整数 0~255 を 0~1 に対応付けます。シェーダー出力は論理的な RGBA のままで、フォーマットは保存表現を定めます。パイプラインは {swapChainDescFormat} でこのアタッチメントに合わせます。" -tutorial.swapChain.title: "スワップチェーン" -tutorial.title: "最初の三角形" -tutorial.troubleshooting.description: "コンソールの診断と三段階の結果を使い、問題のある箇所を特定します。" -tutorial.troubleshooting.details: "{link}と{detail}で頂点データ、入力レイアウト、描画操作を照合できます。サンプルはウィンドウと送信を共通ホストへ分離していますが、このチュートリアルの処理は {programCs} にまとめています。{context}ではインデックス付き描画、変換、深度テストへ進みます。" -tutorial.troubleshooting.details.context: "回転する立方体" -tutorial.troubleshooting.details.detail: "Slang シェーダー" -tutorial.troubleshooting.details.link: "サンプルレンダラー" -tutorial.troubleshooting.table.backend.check: "選択したバックエンドがデバイスおよびインストールされているグラフィックスドライバーでサポートされていることを確認してください。" -tutorial.troubleshooting.table.backend.symptom: "バックエンドの作成に失敗する" -tutorial.troubleshooting.table.drawing.check: "アップロードサイズ、入力レイアウト、パイプラインの選択、およびレンダーパス内の描画コマンドの配置を確認してください。" -tutorial.troubleshooting.table.drawing.symptom: "背景は表示されるが三角形が表示されない" -tutorial.troubleshooting.table.headings.check: "確認事項" -tutorial.troubleshooting.table.headings.symptom: "症状" -tutorial.troubleshooting.table.input.check: "ストライドが 28 バイト、位置と色のオフセットがそれぞれ 0 と 12 バイトであることを確認します。" -tutorial.troubleshooting.table.input.symptom: "頂点の位置や色が破損している" -tutorial.troubleshooting.table.shaders.check: "コピーされた {triangleSlang}、エントリーポイントのスペル、およびコンパイラーが報告した診断情報を確認してください。" -tutorial.troubleshooting.table.shaders.symptom: "背景色は表示されるがシェーダーを読み込めない" -tutorial.troubleshooting.table.window.check: ".NET プロジェクトがビルドされ、ウィンドウ単体のステップがデスクトップセッションで実行されることを確認してください。Linux では、X11 または XWayland が利用可能であることを確認してください。" -tutorial.troubleshooting.table.window.symptom: "ウィンドウが開かない" -tutorial.troubleshooting.title: "問題の切り分け" -tutorial.window.description: "{cocoaHelperCs} をダウンロードしてプロジェクトに追加します。この補助クラスが macOS のウィンドウに Metal レイヤーを取り付けます。" -tutorial.window.details: "自動生成された {programCs} の内容を、次のコードに置き換えます。トップレベルステートメントを使うため、明示的な {main} メソッドを書かずに、上から順に実行できます。続く各節でコードを追加する位置を示します。" -tutorial.window.guidance: "{graphicsAPINone} で、グラフィックスコンテキストの作成を Zenith.NET に任せます。{initialize} はネイティブウィンドウを作り、ウィンドウシステムのハンドルを利用可能にします。{center} で画面中央に置き、{run} で閉じるまでイベントを処理します。その後、{dispose} でウィンドウを解放します。" -tutorial.window.notes: "アプリケーションをビルドして実行し、ウィンドウを開く、移動する、リサイズする、閉じるという操作を確認します。描画コマンドはまだ送信していないため、表示内容は未定義です。次へ進む前にウィンドウを閉じてください。" -tutorial.window.title: "ウィンドウの作成" -ui.action.copy: "コピー" -ui.action.navigate: "移動" -ui.action.open: "開く" -ui.action.source: "ソースを表示" -ui.api.browse: "名前空間と型を参照します。" -ui.api.clearTypeSearch: "型の検索をクリア" -ui.api.findType: "型を検索" -ui.api.loadError: "型を読み込めませんでした。このページを再読み込みしてやり直してください。" -ui.api.loadingNamespaces: "名前空間を読み込み中…" -ui.api.loadingTypes: "型を読み込み中…" -ui.api.matchingTypes: "一致する型" -ui.api.namespace: "名前空間" -ui.api.namespaces: "名前空間" -ui.api.noNamespaceTypes: "この名前空間には型がありません。" -ui.api.noTypes: "一致する型はありません。" -ui.api.types: "型" -ui.content.reference: "リファレンス" -ui.content.source: "ソースコード" -ui.content.tutorial: "チュートリアル" -ui.contents.close: "目次を閉じる" -ui.contents.open: "目次を開く" -ui.contents.title: "目次" -ui.footer.caption: ".NET 向けのモダンな RHI" -ui.footer.label: "フッター" -ui.language.label: "言語" -ui.language.unavailable: "未翻訳" -ui.members.clear: "メンバー検索をクリア" -ui.members.close: "メンバー検索を閉じる" -ui.members.empty: "一致するメンバーはありません。" -ui.members.open: "メンバーへ移動" -ui.members.placeholder: "名前またはシグネチャ…" -ui.members.search: "メンバーを検索" -ui.members.title: "メンバーを検索" -ui.members.undeclared: "この型には宣言されたメンバーがありません。" -ui.navigation.api: "API" -ui.navigation.concepts: "概念" -ui.navigation.home: "ホーム" -ui.navigation.label: "メインナビゲーション" +concepts.execution.context.description: '{graphicsContext} は特定のバックエンドを介してアプリケーションを GPU デバイスに接続し、描画、計算、転送のキューを提供します。一緒に使うリソースは同じコンテキストに属している必要があります。バッファー、テクスチャ、シェーダー、パイプラインとそのハンドルを、コンテキストをまたいでバインドすることはできません。' +concepts.execution.context.details: '{capabilities} はデバイス名と対応機能を提供します。レイトレーシングやメッシュシェーディング用のリソースを作成する前に、{rayTracingSupported} と {meshShadingSupported} で対応を確認します。{link}と{detail}のサンプルでは、初期化時にこの確認を行っています。' +concepts.execution.context.details.detail: 'メッシュシェーディング' +concepts.execution.context.details.link: 'レイトレーシング' +concepts.execution.context.title: 'グラフィックスコンテキスト' +concepts.execution.description: 'GPU の処理は CPU 側で準備します。アプリケーションがリソースを作成し、それらを使うコマンドを記録して、キューに送信します。送信後は GPU がコマンドを実行する間も CPU が処理を続けられます。リソースは GPU の実行が終わるまで保持する必要があります。' +concepts.execution.ownership.description: '所有権は誰がオブジェクトを解放するかを、GPU の完了はいつ解放できるかを決めます。C# の参照が残っていても、{dispose} を呼ぶとネイティブリソースは解放されます。コマンドを送信しても、そのリソースの所有権はキューへ移りません。' +concepts.execution.ownership.details: '終了時は新しい送信を止め、関係するすべてのキューでリソースの最後の使用が終わるのを待ちます。その後、アプリケーションのリソースを解放し、最後にコンテキストを解放します。コンテキストは自身のキューと内部の補助オブジェクトを解放するため、この処理はアプリケーションの作業が終わってから行います。' +concepts.execution.ownership.guidance: '描画中にデータを上書きしたりリソースを置き換えたりする場合は、それを使う処理の完了を追跡します。その使用が終わるのを待ってから、データを変更するか記憶領域を解放します。ビューとその参照先リソースの寿命は、{link}で説明します。' +concepts.execution.ownership.guidance.link: 'リソース管理' +concepts.execution.ownership.table.applicationResources.object: 'アプリケーションが作成したリソース' +concepts.execution.ownership.table.applicationResources.ownership: 'アプリケーションが最後の GPU 使用後に解放します。' +concepts.execution.ownership.table.commandBuffers.object: '借用したコマンドバッファー' +concepts.execution.ownership.table.commandBuffers.ownership: 'キューが管理して再利用します。' +concepts.execution.ownership.table.headings.object: 'オブジェクト' +concepts.execution.ownership.table.headings.ownership: '解放の責任' +concepts.execution.ownership.table.queues.object: 'コンテキストキューとそのタイムライン' +concepts.execution.ownership.table.queues.ownership: 'コンテキストとキューが管理します。' +concepts.execution.ownership.table.swapChainDrawable.ownership: 'スワップチェーンが管理します。' +concepts.execution.ownership.title: '所有権と寿命' +concepts.execution.pipelines.description: 'グラフィックスパイプラインは、シェーダー、頂点入力レイアウト、プリミティブの組み立て、アタッチメントのフォーマット、描画状態を定義します。頂点、インデックス、定数のデータをバインドする前に選択してください。アタッチメントのフォーマットとサンプル数は、レンダーパスと一致させる必要があります。' +concepts.execution.pipelines.details: 'コンピュートパイプラインは、ディスパッチで実行するシェーダーのエントリーポイントを選びます。グラフィックスのレンダーパス外で、パイプラインと定数をバインドしてからディスパッチします。' +concepts.execution.pipelines.guidance: '{link}ではグラフィックスの手順を、{detail}では計算結果を表示するパスの前にディスパッチを加える手順を確認できます。' +concepts.execution.pipelines.guidance.detail: 'コンピュートサンプル' +concepts.execution.pipelines.guidance.link: '三角形の描画コールバック' +concepts.execution.pipelines.title: 'パイプラインの状態' +concepts.execution.queues.description: '描画、計算、コピーを含むフレームでは、通常は {graphicsQueue} から始めます。依存する操作を同じキューにまとめると、順序を扱いやすくなります。' +concepts.execution.queues.details: '独立した処理を別々のキューに送信できますが、各キューが独立したハードウェア実行ユニットに対応するとは限りません。処理を並行して実行する利点がある場合に、キューを追加します。一方のキューがもう一方の生成データを使う場合は、送信間に明示的な依存関係を設定します。' +concepts.execution.queues.guidance: '同じキュー内でも、依存する操作にはバリアやテクスチャ遷移が必要になる場合があります。後のアクセスで、それ以前の書き込み結果を読み取れるようにするためです。このメモリ依存関係は送信順序とは別の要件であり、指定方法は{link}で説明します。' +concepts.execution.queues.guidance.link: '同期' +concepts.execution.queues.table.computeQueue.workToRecord: 'コンピュートディスパッチと対応する転送操作。グラフィックスのレンダーパスは含みません。' +concepts.execution.queues.table.graphicsQueue.workToRecord: 'レンダーパス、描画、計算、転送の操作。' +concepts.execution.queues.table.headings.queue: 'キュー' +concepts.execution.queues.table.headings.workToRecord: '対応する操作' +concepts.execution.queues.table.transferQueue.workToRecord: 'アップロード、リードバック、コピー。描画とコンピュートディスパッチは含みません。' +concepts.execution.queues.title: 'キューの選択' +concepts.execution.recording.context: 'キューは完了したコマンドバッファーを回収して再利用します。記録ごとに {queueCommandBuffer} で取得し、同時に記録するスレッドを一つに限定して、一度だけ送信します。送信後はキューに管理を任せ、変更、再送信、解放を行わないでください。' +concepts.execution.recording.description: '{queueCommandBuffer} が返す {commandBuffer} は、既に記録を開始しています。操作と依存関係を記録した後、一度だけ {submit} を呼びます。記録が終了して送信され、そのキューの完了点を示す {timelineValue} が返ります。' +concepts.execution.recording.details: '三角形のチュートリアルでは、{commandBuffer} にフレームを記録した後、次のように送信して完了を待ちます。' +concepts.execution.recording.guidance: '記録によってコマンド列を構築し、{submit} でその実行をスケジュールします。続いて {wait} を呼ぶと、送信した処理が完了するまで CPU スレッドが待機します。チュートリアルでは次のフレームを始める前に現在のフレームが終わるため、処理の順序を追いやすくなります。' +concepts.execution.recording.title: '記録と送信' +concepts.execution.title: '実行モデル' +concepts.platforms.description: '画面への提示は、アプリケーションまたは UI コントロールが管理します。この選択によって、フレームの出力テクスチャを取得し、コマンドを記録・送信して結果を提示する担当が決まります。この出力テクスチャを drawable と呼びます。' +concepts.platforms.frame.context: 'パス内でパイプラインのバインドと描画を記録し、ハンドラーから戻る前にパスを終了します。コントロールがコマンドを送信し、結果を提示します。ハンドラーでは送信を行わず、渡されたコマンドバッファーや drawable を解放しないでください。drawable のレイアウトを変更した場合は、コントロールが最後の遷移を行えるよう、戻る前に {colorAttachment} に戻します。' +concepts.platforms.frame.description: 'コントロールは {iZenithView} を実装します。アプリケーションは {graphicsContext} を設定し、{updateRequested} でシーンを更新し、{renderRequested} で渡された {renderEventArgs} を使ってコマンドを記録します。' +concepts.platforms.frame.details: '各フレームで、コントロールは drawable とコマンドバッファーを取得し、drawable を {colorAttachment} に遷移させてから、更新と描画のハンドラーを呼びます。その後、記録した処理を送信し、フレームワークの提示方式に従って画像を表示します。' +concepts.platforms.frame.guidance: 'ファイルに {usingZenithNET} を追加します。{view} という名前の {iZenithView} が初期化され、グラフィックスコンテキストも設定済みなら、次のハンドラーで drawable をクリアできます。' +concepts.platforms.frame.notes: '最初の遷移は {undefined} を使うため、以前の画像内容は破棄できます。毎フレーム、画像全体を描画するかクリアしてください。蓄積する描画結果やキャッシュはアプリケーション所有のテクスチャに保存し、そのテクスチャをコントロールの drawable に描画します。' +concepts.platforms.frame.reference: '{zenithViewHelperDrawableFormat} は、これらの統合で使う既定のカラーフォーマットを提供します。' +concepts.platforms.frame.title: 'UI コントロールでの描画' +concepts.platforms.integration.context: 'WinForms、WPF、Windows 向け WinUI の統合は Windows 上で動作します。MAUI では対象プラットフォームのワークロードをインストールし、{extensionsCs} のように {useZenithView} でコントロールハンドラーを登録します。' +concepts.platforms.integration.description: 'イベントのインターフェースは共通ですが、提示方式はフレームワークごとに異なります。' +concepts.platforms.integration.details: 'GPU の画像を UI に届ける方法は、実装によって異なります。ビットマップへのリードバックでは、表示前にピクセルを CPU メモリへコピーします。共有テクスチャの相互運用では、この CPU コピーを省けますが、GPU コピーや同期が必要な場合があります。統合を選ぶ際は、共通の {renderRequested} イベントだけでなく、提示方法も検討してください。' +concepts.platforms.integration.guidance: '使用する UI フレームワークの統合パッケージを NuGet から追加します。Avalonia では {avaloniaPackage} を使います。' +concepts.platforms.integration.table.avalonia.integration: 'Avalonia' +concepts.platforms.integration.table.avalonia.presentation: 'テクスチャにレンダリングし、ピクセルを {writeableBitmap} にリードバックします。{zenithViewCs} および {surfaceCs} を参照してください。' +concepts.platforms.integration.table.headings.integration: '統合' +concepts.platforms.integration.table.headings.presentation: '提示方式' +concepts.platforms.integration.table.maui.integration: '.NET MAUI' +concepts.platforms.integration.table.maui.presentation: 'Android、iOS、Mac Catalyst ではネイティブサーフェスを使用し、Windows では共有テクスチャコンポジションを使用します。{link} を参照してください。' +concepts.platforms.integration.table.maui.presentation.link: 'プラットフォーム実装' +concepts.platforms.integration.table.uno.integration: 'Uno パス' +concepts.platforms.integration.table.uno.presentation: 'ピクセルを {writeableBitmap} にリードバックします。{zenithViewUnoCs} を参照してください。' +concepts.platforms.integration.table.winForms.integration: 'WinForms' +concepts.platforms.integration.table.winForms.presentation: 'コントロールの {hWND} 用に Zenith.NET スワップチェーンを作成します。{zenithViewCs} を参照してください。' +concepts.platforms.integration.table.winUI.integration: 'Windows 上の WinUI' +concepts.platforms.integration.table.winUI.presentation: 'インポートされた共有 Direct3D 11 テクスチャにレンダリングし、{swapChainPanel} に接続されたコンポジションスワップチェーンにコピーします。{zenithViewWinUICs} を参照してください。' +concepts.platforms.integration.table.wpf.integration: 'WPF' +concepts.platforms.integration.table.wpf.presentation: '共有 Direct3D 11 テクスチャをインポートし、Direct3D 相互運用を介して {d3DImage} によって表示されるサーフェスにコピーします。{surfaceCs} を参照してください。' +concepts.platforms.integration.title: 'フレームワークと提示方式' +concepts.platforms.lifecycle.context: '対応するアタッチメントを作るときは、描画イベントから渡された drawable の {descWidth}、{descHeight}、{descFormat}、{descSampleCount} を使います。このテクスチャの寸法が、実際の描画先の寸法です。コントロールのレイアウト上のサイズや表示倍率から推測しないでください。' +concepts.platforms.lifecycle.description: 'スワップチェーンのサイズには、フレームバッファーの幅と高さをピクセル単位で使います。表示倍率によっては、ウィンドウの論理寸法とは異なります。どちらかの寸法がゼロの間は、描画もスワップチェーンのリサイズも行いません。{swapChainDrawable} は毎フレーム取得します。このテクスチャはスワップチェーンが所有し、提示やリサイズの後に置き換わることがあります。' +concepts.platforms.lifecycle.details: 'フレームバッファーの寸法が変わったら、古い画像への GPU アクセスが終わるのを待ってから {swapChainResize} を呼びます。ネイティブの提示先を置き換える場合も、アクセスの完了後に、新しいサーフェス記述とハンドルを {swapChainRefresh} に渡します。終了時は、ネイティブの提示先を破棄する前にスワップチェーンを解放します。' +concepts.platforms.lifecycle.guidance: 'アプリケーションの深度テクスチャやオフスクリーンテクスチャがウィンドウと同じ寸法を使う場合は、リサイズ時に再作成し、それらのハンドルを含む定数も更新します。アタッチメントのフォーマットとサンプル数が合っていれば、パイプラインは再利用できます。{link}では、テクスチャをリサイズしながらパイプラインを保持する構成を確認できます。' +concepts.platforms.lifecycle.guidance.link: '回転する立方体のレンダラー' +concepts.platforms.lifecycle.title: 'スワップチェーンの寸法と寿命' +concepts.platforms.ownership.description: '設定したコンテキストと描画リソースはアプリケーションが、提示用リソースはコントロールが所有します。ビューの {graphicsContext} を変えると、スケジューラーは新しいコンテキストでコントロールのリソースを再作成します。アプリケーションのパイプライン、バッファー、テクスチャも、同じコンテキストで作り直してください。' +concepts.platforms.ownership.details: '描画リソースを置き換える前にビューのフレーム処理を止め、そのリソースを使う GPU 処理の完了を待ちます。その後、古いリソースやコンテキストを解放します。ビューを削除した場合も、設定したコンテキストの解放はアプリケーションが担当します。' +concepts.platforms.ownership.guidance: '共通の {frameSchedulerCs} は、ビューの UI ディスパッチャーを通してフレームハンドラーを実行します。ハンドラーはシーンデータの更新とコマンドの記録に集中させてください。そこで長い CPU 処理を行うと、UI の応答も遅れます。' +concepts.platforms.ownership.title: 'アプリケーションとコントロールの所有権' +concepts.platforms.surface.description: '{link}では、Silk.NET がウィンドウを作成してイベントを処理します。Zenith.NET は {surface} 記述を通じてネイティブウィンドウのハンドルと寸法を受け取り、それを使って {swapChain} を作成します。OS のウィンドウは引き続きアプリケーションが管理します。' +concepts.platforms.surface.description.link: '三角形のチュートリアル' +concepts.platforms.surface.details: 'サーフェスのハンドルはバックエンドと対応させます。' +concepts.platforms.surface.guidance: '{appCs} のサンプルホストは Windows、macOS、X11 に対応しています。Linux のウィンドウは Xlib ハンドルを渡すため、Wayland セッションで実行するには XWayland が必要です。ネイティブ Wayland アプリケーションでは、{surfaceWayland} にディスプレイとサーフェスのハンドルを渡します。' +concepts.platforms.surface.table.android.backend: 'Android 上の Vulkan。' +concepts.platforms.surface.table.apple.backend: 'Apple プラットフォーム上の Metal。' +concepts.platforms.surface.table.headings.backend: 'バックエンドとプラットフォーム' +concepts.platforms.surface.table.headings.factory: 'サーフェスファクトリ' +concepts.platforms.surface.table.headings.handles: 'ホストから提供されるハンドル' +concepts.platforms.surface.table.wayland.backend: 'ネイティブ Wayland ホストを使用した Vulkan。' +concepts.platforms.surface.table.wayland.handles: 'Wayland ディスプレイおよびサーフェス' +concepts.platforms.surface.table.win32.backend: 'Windows 上の DirectX 12 または Vulkan。' +concepts.platforms.surface.table.xlib.backend: 'X11 または XWayland を使用した Linux 上の Vulkan。' +concepts.platforms.surface.table.xlib.handles: 'X11 ディスプレイおよびウィンドウ' +concepts.platforms.surface.title: 'ネイティブの提示サーフェス' +concepts.platforms.title: 'プラットフォーム統合' +concepts.resources.allocation.context: 'ヒープに配置したリソースは、その寿命全体にわたってヒープの記憶領域を使います。最後の GPU 使用が終わったら、リソースを先に解放し、その後ヒープを解放します。' +concepts.resources.allocation.description: 'アプリケーションでメモリ割り当てを管理する場合は、{heap} を使います。ヒープは、指定したバイトオフセットにリソースを配置する記憶領域です。オフセットの選択と使用領域の管理はアプリケーションが行います。' +concepts.resources.allocation.details: '各リソースの作成に使うバッファーまたはテクスチャ記述を渡して、{contextGetSizeAndAlignment} を呼びます。返されたアラインメントの倍数となるオフセットに、返されたサイズ分の領域を確保します。領域はヒープ内に収め、使用中の別の割り当てと重ねてはいけません。テクスチャにはバックエンド固有のパディングが含まれる場合があるため、ピクセル数とピクセル当たりのバイト数だけでは割り当てサイズを算出できません。' +concepts.resources.allocation.guidance: 'ヒープに配置するバッファーは、そのヒープと同じ常駐区分を指定します。テクスチャの格納には GPU 専用ヒープを使います。' +concepts.resources.allocation.title: 'ヒープへの配置' +concepts.resources.bufferUsages.table.constant.role: '定数バッファーバインドを介して読み取られるシェーダーパラメーター。' +concepts.resources.bufferUsages.table.headings.role: '役割' +concepts.resources.bufferUsages.table.headings.usage: '用途' +concepts.resources.bufferUsages.table.index.role: 'インデックス描画で使用されるインデックス。' +concepts.resources.bufferUsages.table.indirect.role: '間接描画または間接ディスパッチのコマンドが読み取る引数。' +concepts.resources.bufferUsages.table.none.role: 'バッファーの用途フラグは宣言されていません。' +concepts.resources.bufferUsages.table.storageReadOnly.role: '読み取り専用のシェーダーバインドを介してアクセスするバッファーデータ。' +concepts.resources.bufferUsages.table.storageReadWrite.role: '読み書き可能なシェーダーバインドを介してアクセスするバッファーデータ。' +concepts.resources.bufferUsages.table.transferDst.role: 'GPU コピーの転送先ストレージ。' +concepts.resources.bufferUsages.table.transferSrc.role: 'GPU コピーの転送元データ。' +concepts.resources.bufferUsages.table.vertex.role: '描画のためにフェッチされる頂点属性。' +concepts.resources.bufferUsages.title: 'バッファーの用途' +concepts.resources.description: 'リソース記述は、アプリケーションが記憶領域をどう使えるかを定めます。例えば、描画先にし、シェーダーでサンプリングし、CPU に読み戻すテクスチャには、三つの操作に対応する用途フラグが必要です。メモリ配置は CPU のアクセス方法を決めます。データにアクセスできる時点や記憶領域を解放できる時点は、同期と寿命の管理によって決まります。' +concepts.resources.memory.context: 'CPU からアクセスできるバッファーでは、{map} がデータを読み書きするためのアドレスを提供します。マッピングも {unmap} も、GPU の処理を待機しません。GPU が書いた結果を CPU で読む前にはその書き込みを待ち、同じバイトを書き換える前には、その領域への GPU アクセスが終わるのを待ちます。' +concepts.resources.memory.description: '{bufferDesc} の {residency} は、想定する CPU アクセスを指定します。' +concepts.resources.memory.details: '常駐区分は CPU アクセスの要件を表します。CPU と GPU が物理メモリを共有するシステムでも、この区分を使います。三角形では {cpuWriteOnly} を使い、小さな頂点バッファーを直接初期化します。大きな静的ジオメトリでは、GPU 専用の記憶領域へアップロードする方が適している場合があります。' +concepts.resources.memory.guidance: 'コンテキストから直接作成したテクスチャは GPU の記憶領域を使うため、{textureDesc} に常駐区分のフィールドはありません。CPU メモリとのデータ交換には、アップロードとリードバックを使います。' +concepts.resources.memory.table.cpuReadOnly.cPUAccess: '読み取りのみ' +concepts.resources.memory.table.cpuReadOnly.typicalRole: 'CPU へ読み戻すために GPU が生成したデータ' +concepts.resources.memory.table.cpuWriteOnly.cPUAccess: '書き込みのみ' +concepts.resources.memory.table.cpuWriteOnly.typicalRole: 'CPU が供給または更新するデータ' +concepts.resources.memory.table.gpuOnly.cPUAccess: 'なし' +concepts.resources.memory.table.gpuOnly.typicalRole: '静的ジオメトリと GPU の作業用データ' +concepts.resources.memory.table.headings.cPUAccess: '想定する CPU アクセス' +concepts.resources.memory.table.headings.residency: '常駐区分' +concepts.resources.memory.table.headings.typicalRole: '典型的な役割' +concepts.resources.memory.title: 'CPU アクセスとメモリ配置' +concepts.resources.textureUsages.description: '転送フラグは、リソースを GPU コピーの転送元または転送先として使うことを宣言します。CPU から直接アクセスできるかどうかは、メモリ配置によって別途決まります。' +concepts.resources.textureUsages.details: '用途フラグは、テクスチャを何に使えるかを宣言します。用途を切り替える際は、それに応じた{link}が必要です。また、使用するデバイスが、指定したテクスチャフォーマットでその用途をサポートしている必要があります。' +concepts.resources.textureUsages.details.link: 'レイアウトと同期' +concepts.resources.textureUsages.table.colorAttachment.role: 'レンダーパスのカラーアタッチメント。' +concepts.resources.textureUsages.table.depthStencilAttachment.role: 'レンダーパスの深度/ステンシルアタッチメント。' +concepts.resources.textureUsages.table.headings.role: '役割' +concepts.resources.textureUsages.table.headings.usage: '用途' +concepts.resources.textureUsages.table.none.role: 'テクスチャの用途フラグは宣言されていません。' +concepts.resources.textureUsages.table.sampled.role: 'サンプリング用テクスチャのバインドを介して読み取るテクスチャデータ。' +concepts.resources.textureUsages.table.storage.role: 'ストレージテクスチャのバインドを介してシェーダーが読み書きするテクスチャデータ。' +concepts.resources.textureUsages.table.transferDst.role: 'GPU コピーの転送先画像ストレージ。' +concepts.resources.textureUsages.table.transferSrc.role: 'GPU コピーの転送元画像データ。' +concepts.resources.textureUsages.title: 'テクスチャの用途' +concepts.resources.title: 'リソース管理' +concepts.resources.transfers.context: 'リードバックでは、まず GPU データを内部の読み戻し領域へコピーします。ライブラリは完了したコマンドバッファーを回収するときに、そのデータを指定した CPU の宛先へコピーします。リードバックの送信値に対して {wait} を呼ぶと、両方の処理が完了します。戻るまで宛先を確保したままにし、管理対象メモリは固定してください。' +concepts.resources.transfers.description: 'アップロードは CPU データを GPU リソースへコピーし、リードバックはリソースのデータを CPU メモリへコピーします。バッファーとテクスチャの次のメソッドは、転送を完了してから戻ります。' +concepts.resources.transfers.details: '呼び出す前に、他のキューとの競合するアクセスを解消します。メソッド内の待機は自身の転送だけを対象とし、他のキューとの依存関係を設定するものではありません。マッピングしたメモリを直接コピーする場合は、競合する GPU アクセスの完了を呼び出し側で待つ必要があります。' +concepts.resources.transfers.guidance: '他の GPU 処理とまとめて転送を送信するには、{commandBufferUpload} または {commandBufferDownload} で記録します。アップロードの転送元とリードバックの転送先では、メモリを有効に保つ必要のある期間が異なります。' +concepts.resources.transfers.item: 'アップロードの呼び出し中に、ライブラリは元データをステージングメモリと呼ばれる内部の一時領域へコピーします。GPU は後でこの領域を読むため、アプリケーションの元ポインターが必要なのは、呼び出しが戻るまでです。' +concepts.resources.transfers.notes: 'テクスチャ転送の行ストライドは、CPU データの隣り合う行の間隔をバイトで表します。スライスストライドは、深さ方向に隣り合うスライスの間隔です。転送処理はこれらの値を使い、CPU データとテクスチャの GPU 記憶領域との間でコピーします。GPU の完了と宛先へのコピーが別の段階になる理由は、{link}で説明します。' +concepts.resources.transfers.notes.link: '同期' +concepts.resources.transfers.table.bufferDownload.transfer: '{cpuReadOnly} では、マッピングしたメモリから直接コピーします。それ以外は転送キューにリードバックを送信し、完了を待ちます。' +concepts.resources.transfers.table.bufferUpload.transfer: '{cpuWriteOnly} では、マッピングしたメモリへ直接コピーします。それ以外は転送キューにアップロードを送信し、完了を待ちます。' +concepts.resources.transfers.table.headings.method: '方法' +concepts.resources.transfers.table.headings.transfer: '転送の動作' +concepts.resources.transfers.table.textureTransfers.method: '{textureUpload} / {textureDownload}' +concepts.resources.transfers.table.textureTransfers.transfer: 'コピーとテクスチャ遷移をグラフィックスキューに送信し、完了を待ちます。終了時には、選択したサブリソースが指定した最終レイアウトになります。' +concepts.resources.transfers.title: '即時転送とコマンドへの記録' +concepts.resources.usages.description: '{bufferUsages} と {textureUsages} は、リソースの用途を宣言するフラグ列挙型です。それぞれ {bufferDescUsages} と {textureDescUsages} に設定します。複数の用途には、必要なメンバーを {value} で組み合わせます。' +concepts.resources.usages.title: 'リソースの用途' +concepts.resources.views.description: '{bufferView} はバッファーの範囲とデータの解釈方法を記述します。{textureView} はサブリソース範囲と、互換性のあるテクスチャ種別やフォーマットを選択します。どちらも既存の記憶領域を参照し、その作成時に宣言した用途に従います。ビューの範囲はアクセス範囲を示すものであり、シェーダーの境界検査が全バックエンドで同じように働くことを保証するものではありません。' +concepts.resources.views.details: 'リソース自身のハンドルは既定のビューを提供します。別の範囲や互換性のある解釈方法を選ぶ場合は、独立したビューを作成します。ビューと元リソースはどちらも、GPU が使い終わるまで保持してください。ハンドルだけでは、どちらのオブジェクトも保持されません。いずれかを置き換えたら、古い{link}を含む定数も更新します。' +concepts.resources.views.details.link: 'リソースハンドル' +concepts.resources.views.title: 'ビューと参照先リソース' +concepts.shaders.binding.context: 'コンピュートのサンプルでは、{input} に {inputTextureSampledHandle}、{output} に {outputTextureStorageHandle} を設定します。Slang の {descriptorHandle} の型引数が、各リソースへのアクセス方法を定めます。' +concepts.shaders.binding.description: '{setConstantBuffer} は、現在のパイプラインが定数を読み取るバッファーとバイトオフセットを選択します。シェーダーが使う前に、パラメーターのデータをその領域へアップロードします。以前の GPU 処理が同じ領域をまだ読んでいる場合は、完了を待ってから更新してください。' +concepts.shaders.binding.details: 'コマンドバッファー、コンピュートパイプライン、データを設定した定数バッファー、スレッドグループ数が用意できたら、次の順にディスパッチを記録します。定数バッファーは選択中のパイプラインにバインドされるため、先にパイプラインを選択します。' +concepts.shaders.binding.guidance: 'ここでは {commandBuffer} に、{computePipeline} と {constantBuffer} のパラメーターを使うディスパッチを記録しています。定数バッファーには {bufferUsagesConstant} の用途が必要で、オフセット 0 はその先頭を指定します。一つのバッファーを複数の定数レコードで共有する場合、各開始オフセットはバックエンドのバインド時アラインメント要件にも従います。これは、レコード内部のフィールド配置とは別の要件です。' +concepts.shaders.binding.notes: '{resourceHandle} は二つの 32 ビットフィールドを持ち、解釈はバックエンドに依存します。値はリソースを作成したコンテキスト内でのみ有効です。' +concepts.shaders.binding.reference: 'ハンドルの取得元リソースとビューは、シェーダーの最後のアクセスが完了するまで保持します。テクスチャやビューの置換後は、古いハンドルを含む定数を更新してください。所有権の規則は{link}で説明します。' +concepts.shaders.binding.reference.link: 'リソース管理' +concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: 'シェーダー型 {t} の構造化要素の読み取り' +concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: 'シェーダー型 {t} の構造化要素の読み書き' +concepts.shaders.binding.table.headings.access: '想定されるアクセス' +concepts.shaders.binding.table.headings.cHandle: 'C# ハンドル' +concepts.shaders.binding.table.headings.slangFieldType: 'Slang フィールド型' +concepts.shaders.binding.table.samplerHandle.access: 'テクスチャのサンプリング状態' +concepts.shaders.binding.table.textureSampledHandle.access: 'テクスチャの読み取り' +concepts.shaders.binding.table.textureStorageHandle.access: 'ストレージテクスチャの読み書き' +concepts.shaders.binding.title: '定数バッファーとリソースハンドル' +concepts.shaders.compilation.description: '{zenithCompiler} は Slang の指定エントリーポイントを {shaderDesc} にコンパイルします。コンテキストの {graphicsApi} に応じ、DirectX 12 には DXIL、Metal には Metal ライブラリ、Vulkan には SPIR-V を生成します。' +concepts.shaders.compilation.details: '{context} という名前のグラフィックスコンテキストを作成してから、実行ファイルと同じディレクトリにコピーした三角形のシェーダーをコンパイルします。' +concepts.shaders.compilation.guidance: 'エントリーポイント名 {vSMain} は、シェーダーファイル内の宣言と一致させます。シェーダーのコンパイルとパイプラインの作成は初期化時に行い、描画中はパイプラインを再利用します。作成が終われば、{link}で示すようにシェーダーオブジェクトを解放できます。' +concepts.shaders.compilation.guidance.link: '最初の三角形' +concepts.shaders.compilation.title: 'シェーダーのコンパイル' +concepts.shaders.description: 'C# と Slang の宣言では、各値をどこに格納し、シェーダーがどうアクセスするかを一致させます。頂点入力レイアウトは頂点属性を、シェーダーバッファーの宣言はパラメーターや配列を記述します。リソースハンドルは、シェーダーが使うリソースを識別します。' +concepts.shaders.dispatch.description: '{dispatch} は、実行するスレッドグループ数を指定します。コンピュートサンプルでは {numthreads} を宣言しているため、一グループは 16 × 16 スレッドです。画像の幅と高さをそれぞれ 16 で割って切り上げると、画像全体を覆えます。17 × 19 の画像には 2 × 2 グループが必要です。シェーダーで各スレッドの座標を調べ、画像の外側なら処理を省きます。' +concepts.shaders.dispatch.details: '宣言したグループサイズは {shaderDescThreadGroupSize} から取得でき、{dispatch} に渡すグループ数の計算に使えます。計算の全体は {computeShaderRendererCs} で確認できます。ディスパッチ後の画像へのアクセスは、{link}の要件に従います。' +concepts.shaders.dispatch.details.link: '同期' +concepts.shaders.dispatch.title: 'スレッドグループ' +concepts.shaders.layout.context: '{link}では、画像の寸法と二つのテクスチャハンドルを使ってこの配置を示しています。各フィールドの開始位置はオフセットで明示します。次の宣言では {systemRuntimeInteropServices} と {zenithNET} の名前空間を使用します。' +concepts.shaders.layout.context.link: 'コンピュートサンプルの C# 定数' +concepts.shaders.layout.description: '頂点入力の {inputLayout} は、各属性のフォーマット、オフセット、セマンティクスと、頂点間のストライドを記述します。三角形では {float3} の位置の後に {float4} の色を置きます。色のバイトオフセットは 12、頂点一つのサイズは 28 バイトです。{inputLayoutAdd} は属性のフォーマットからこの密な配置を計算します。C# の構造体にパディングがある場合は、それを含めたオフセットとストライドを指定してください。' +concepts.shaders.layout.details: '定数バッファーはシェーダーのパラメーターを、構造化バッファーは型付き要素の配列を格納します。これらの配置は {inputLayout} ではなく、Slang の宣言に従います。C# のフィールドオフセット、要素サイズ、パディングを、コンパイル済みシェーダーの配置に合わせてください。C# のアンマネージ型はバイト列としてコピーできますが、そのメモリ配置がシェーダーの配置と一致するとは限りません。頂点内で密に格納した {float3} も、シェーダーバッファーでは別のアラインメントが必要になる場合があります。' +concepts.shaders.layout.guidance: 'シェーダーのパラメーターには、数値とともにリソースハンドルを含められます。ハンドルは既存の記憶領域を指すため、定数バッファーにコピーしてもリソースの内容はコピーされません。' +concepts.shaders.layout.notes: '{computeShaderSlang} の対応する宣言は次のとおりです。' +concepts.shaders.layout.reference: '二つの寸法値が先頭の 8 バイトを占め、その後に二つの 8 バイトのハンドルが続きます。C# サンプルはレコード全体に 256 バイトを確保します。別のレコードでは、フィールドの内容と必要な配置、アラインメントからサイズを決めます。' +concepts.shaders.layout.title: 'データ配置' +concepts.shaders.matrices.description: 'コンパイラーは行ごとに連続する行優先の行列配置を選択します。{link}では三つの {matrix4x4} をオフセット 0、64、128 に格納します。対応する{detail}では、{mulVectorMatrix} をモデル、ビュー、投影の順に適用します。' +concepts.shaders.matrices.description.detail: 'シェーダー' +concepts.shaders.matrices.description.link: '回転する立方体のレンダラー' +concepts.shaders.matrices.details: '格納順序はメモリ内の行列要素の配置を、乗算順序は変換を定めます。C# と Slang で対応する規約を使います。' +concepts.shaders.matrices.title: '行列の規約' +concepts.shaders.title: 'シェーダーデータとバインド' +concepts.synchronization.backends.description: 'DirectX 12 と Vulkan は、テクスチャ遷移をレイアウトとアクセスの変更として記録します。Zenith.NET の Metal バックエンドでは、{transition} に相当する GPU 操作はありません。代わりにコマンドを描画・計算エンコーダーにまとめ、エンコーダー終了時に可視性バリアを挿入します。連続するコンピュートディスパッチなど、同じエンコーダー内の依存には明示的な {barrier} 呼び出しを使います。' +concepts.synchronization.backends.details: '{link}では、グラフィックスのレンダーパスを開始すると計算エンコーダーが終了し、計算結果を描画処理から読み取れるようになります。連続する二つのコンピュートディスパッチは同じエンコーダー内にとどまるため、間にテクスチャ遷移を記録しても、依存を指定するバリアが必要です。このため、複数のバックエンドで使うコマンド列では、レイアウトとアクセス依存の両方を扱います。' +concepts.synchronization.backends.details.link: 'コンピュートサンプル' +concepts.synchronization.backends.title: 'バックエンドごとの動作' +concepts.synchronization.barriers.context: '関係するアクセスを含み、キューが対応しているステージを選びます。{barrierStagesAll} は対応するすべてのステージを含みます。依存関係が一部のステージだけに関わる場合は、その範囲に限定できます。' +concepts.synchronization.barriers.description: '同じコマンドバッファーに記録した二つのコンピュートディスパッチで、最初がシミュレーションデータを書き、次がそれを読む場合を考えます。その間にバリアを置くと、後のディスパッチが完了済みの書き込み結果を読み取れます。ストレージバッファーでは、テクスチャレイアウトを遷移させずにアクセスを順序付けられます。' +concepts.synchronization.barriers.details: '最初の引数はデータを生成したステージ、二つ目はそれを使用するステージを指定します。この二つで、ディスパッチ間に必要な実行順序とメモリの可視性を表します。' +concepts.synchronization.barriers.guidance: '{link}では、シミュレーションの各段階の間にこの形のバリアを置きます。どのバリアも、データを生成するディスパッチの後、使用するディスパッチの前に記録します。' +concepts.synchronization.barriers.guidance.link: 'FluidTank シミュレーション' +concepts.synchronization.barriers.title: 'パイプラインバリア' +concepts.synchronization.dependencies.description: '各リソースで、同じデータに触れるアクセスを確認します。一方でも書き込みを行う場合は、必要な順序を保ちます。二つの読み取りは競合しませんが、テクスチャレイアウトや提示の要件は満たす必要があります。CPU からの更新やリソースの解放も、対象領域を GPU が使い終わるまで待ちます。' +concepts.synchronization.dependencies.details: '操作の実行場所に応じて、使う仕組みを選びます。' +concepts.synchronization.dependencies.guidance: '一つの処理に複数の同期手段が必要な場合もあります。例えば、別のキューで生成したテクスチャには、送信間の依存関係と、次の用途に適したレイアウトの両方が必要です。どちらも、それ自体は CPU の待機を必要としません。CPU がデータにアクセスしたり解放したりする場合に、CPU 側で待機します。' +concepts.synchronization.dependencies.table.cpuAccess.mechanism: '該当する完了値に対して {wait} を呼び出します。' +concepts.synchronization.dependencies.table.cpuAccess.situation: 'CPU のアクセスやリソース解放に GPU の完了が必要な場合' +concepts.synchronization.dependencies.table.crossQueue.mechanism: '生成側の {timelineValue} を使用側の {submit} に渡します。' +concepts.synchronization.dependencies.table.crossQueue.situation: '別のキューで生成したデータを使用する場合' +concepts.synchronization.dependencies.table.headings.mechanism: 'メカニズム' +concepts.synchronization.dependencies.table.headings.situation: '状況' +concepts.synchronization.dependencies.table.layoutChange.mechanism: '以前のレイアウトと次のレイアウトを指定した {commandBufferTransition}。' +concepts.synchronization.dependencies.table.layoutChange.situation: 'テクスチャサブリソースの使用方法の変更' +concepts.synchronization.dependencies.table.pipelineStages.mechanism: '生成側ステージと使用側ステージを指定した {commandBufferBarrier}。' +concepts.synchronization.dependencies.table.pipelineStages.situation: 'コマンドストリーム内の依存する GPU ステージ' +concepts.synchronization.dependencies.title: 'アクセス間の依存' +concepts.synchronization.description: '同期は、共有データへのアクセス順序を定め、後の操作が必要な結果を読み取れるようにします。書き込みから読み取りへの依存では、書き込む側を生成側、読む側を使用側と呼びます。バリアとテクスチャ遷移は GPU のアクセスを調整し、タイムラインは送信間の依存を設定したり、CPU で GPU の完了を待ったりするために使います。' +concepts.synchronization.layouts.context: '以前の内容を破棄できる場合は、遷移前のレイアウトに {undefined} を指定できます。例えば、新しい画像や全体をクリアするアタッチメントが該当します。ロード、サンプリング、蓄積のために内容を保持する場合は、直前のアクセスのレイアウトを使います。' +concepts.synchronization.layouts.description: '用途フラグは、テクスチャの許可された用途を宣言します。{textureLayout} は、コマンド列のある時点で、mip レベルと配列レイヤーで特定したサブリソースにどうアクセスするかを表します。アクセス方法が変わるときに遷移を記録します。例えばコンピュートサンプルでは、{storage} レイアウトで出力テクスチャへ書き込んだ後、グラフィックスパスでサンプリングする準備をします。' +concepts.synchronization.layouts.details: 'ここでは {outputTexture} を {sampledStorage} 用途で作成し、対象サブリソースは {storage} です。{default} は mip レベル 0 と配列レイヤー 0 を選びます。他のレベルとレイヤーには影響しません。' +concepts.synchronization.layouts.guidance: '{transition} には、サブリソースを前回使用したときのレイアウトを渡します。アプリケーションはコマンドを記録し、テクスチャを描画ステージ間で渡す際に、この状態を追跡します。' +concepts.synchronization.layouts.title: 'テクスチャレイアウト' +concepts.synchronization.readback.description: '{isCompleted} は GPU の完了を報告します。記録したリードバックには、その後にもう一つの処理があります。内部の読み戻し領域からアプリケーションの宛先メモリへ結果をコピーする処理です。' +concepts.synchronization.readback.details: '{commandBufferDownload} は、この内部領域への GPU コピーを記録します。送信完了後、ライブラリはコマンドバッファーの回収時に CPU コピーを行います。リードバックの送信値に対して {wait} を呼ぶと、GPU を待機した後、そのキューの完了済みバッファーを処理し、両方のコピーが完了します。戻るまで宛先を確保し、管理対象メモリは固定したままにしてください。' +concepts.synchronization.readback.guidance: '{isCompleted} の確認だけでは、最後の CPU コピーは行われません。別のキューで待機しても、リードバックを管理するキューのバッファーは回収されません。アップロードとリードバックが直接アクセスや一時領域を使う条件は、{link}で説明します。' +concepts.synchronization.readback.guidance.link: 'リソース管理' +concepts.synchronization.readback.title: 'リードバックの完了' +concepts.synchronization.reuse.description: '三角形では、各フレームの完了を待ってからデータを再利用します。フレームの処理を並行して進める場合は、処理中の各フレームに個別の変更可能な記憶領域を用意し、再び使える時点を追跡します。データを変更する前にはその領域への GPU アクセスを、リソースを解放する前にはそのすべての使用を待ちます。' +concepts.synchronization.reuse.details: 'リサイズと終了も、同じ順序で処理します。新しい使用を止め、既存の使用が終わるのを待ってから、リソースを置き換えるか解放します。{swapChainResize} やリソース、コンテキストの解放を呼ぶ前に、この順序を確保してください。三角形では毎フレーム待機しているため、コールバックの間でリサイズできます。' +concepts.synchronization.reuse.guidance: '{swapChainPresent} は提示後にグラフィックスキューへシグナルを送り、完了を待ちます。そのため、明示的な送信待ちを除いても、三角形は提示時に待機します。別キューへ独立して送信した処理は、完了を個別に追跡する必要があります。' +concepts.synchronization.reuse.title: 'リソースの再利用' +concepts.synchronization.timelines.context: '使用側の処理後に CPU で結果を読んだり、共有データを上書きしたり、リソースを解放したりする場合は、その送信を待ちます。' +concepts.synchronization.timelines.description: 'タイムラインは増加する値でキューの完了を表します。{submit} が返す {timelineValue} はタイムラインと送信の値を含みます。異なるタイムラインの数値 {value} は直接比較できません。' +concepts.synchronization.timelines.details: '同じコンテキストの二つのキューで記録した {producer} と {consumer} があり、後者が前者の書いたデータを使うとします。次の依存関係で送信します。' +concepts.synchronization.timelines.guidance: '使用側のキューは、渡された完了値に到達するのを待ってからコマンドを実行します。CPU は {producedWait} を呼ばずに処理を続けられます。共有リソースは {consumed} が完了するまで保持し、使用側のアクセスに必要なテクスチャ遷移も記録します。' +concepts.synchronization.timelines.notes: '{queueTimelineSignal} の戻り値も、{wait} で待機したり、別キューの依存関係に使ったりできます。{signal} は、それまでに送信した処理の後に完了点を置きます。GPU がその処理を終えると、完了点に到達します。' +concepts.synchronization.timelines.title: 'タイムラインとキュー間の依存' +concepts.synchronization.title: '同期' +home.actions.reference: 'API を参照' +home.actions.tutorial: '三角形から始める' +home.entries.description: 'チュートリアル、サンプル、API リファレンス' +home.entries.label: 'ドキュメントの構成' +home.entries.reference.action: 'API を探索' +home.entries.reference.category: 'リファレンス' +home.entries.reference.description: 'API の型、メンバー、宣言を調べる' +home.entries.reference.title: 'API リファレンス' +home.entries.samples.action: 'サンプルを参照' +home.entries.samples.category: 'サンプル' +home.entries.samples.description: '描画と計算の手法を実行できるサンプルで学ぶ' +home.entries.samples.title: 'サンプル' +home.entries.title: 'ドキュメント' +home.entries.tutorial.action: 'チュートリアルを開始' +home.entries.tutorial.category: 'チュートリアル' +home.entries.tutorial.description: '空のプロジェクトから、最初の三角形を描くまで' +home.entries.tutorial.title: '最初の三角形' +home.introduction.accent: 'クロスプラットフォームのグラフィックス' +home.introduction.description: 'Zenith.NET は、共通の API で DirectX、Metal、Vulkan の描画と計算を扱うライブラリです' +home.introduction.title: '.NET でつくる{lineBreak}{accent}' +home.meta.description: 'DirectX、Metal、Vulkan に共通の API を使い、.NET でクロスプラットフォームの描画・計算アプリケーションを開発' +home.scene.description: '回転する図形を操作できます。ドラッグまたは矢印キーで視点を調整してください。' +home.scene.label: 'ジオメトリ表示' +home.scene.surface: 'サーフェス' +home.scene.wireframe: 'ワイヤーフレーム' +home.title: '.NET 向けのモダンな RHI' +learning.concepts.description: 'リソース用途の選択、シェーダーデータの記述、GPU 実行の調整' +learning.concepts.execution.description: 'コマンドの記録と送信、リソースの寿命' +learning.concepts.platforms.description: 'ネイティブの提示と UI 描画コントロール' +learning.concepts.resources.description: 'リソースの用途、メモリ配置、ビュー' +learning.concepts.shaders.description: 'C# と Slang のデータ配置とバインドの規約' +learning.concepts.synchronization.description: '依存関係、可視性、完了' +learning.concepts.title: '基本概念' +learning.description: 'まずは三角形のチュートリアルで、最初のアプリケーションを作成します。その後は必要に応じて、リソース管理、シェーダーデータ、同期の解説を読むか、実装したい手法のサンプルを選んでください。' +learning.entries.samples.action: 'サンプルを参照' +learning.entries.samples.description: 'ジオメトリ、計算、レイクエリ、メッシュシェーディングの C# と Slang による実装' +learning.entries.tutorial.action: 'チュートリアルを開く' +learning.entries.tutorial.description: 'ウィンドウを開き、三角形を描くコンソールアプリケーション' +learning.meta.description: 'Zenith.NET のプログラミングモデルを学ぶチュートリアルと概念解説' +learning.title: '学習' +reference.description: 'リソース、コマンド、プラットフォーム統合のリファレンス' +reference.entries.commands.description: '描画、計算、転送のコマンド' +reference.entries.commands.label: 'コマンドを記録' +reference.entries.context.description: '選択したバックエンドの GPU リソース作成' +reference.entries.context.label: 'ここから開始' +reference.meta.description: 'Zenith.NET の名前空間、型、メンバー' +reference.navigation.core: 'コア API リファレンス' +reference.title: 'API リファレンス' +samples.computeShader.description: 'サンプルは {assetsTexturesShokoPng} を読み込み、コンピュートディスパッチでグレースケールに変換して、出力テクスチャを表示します。変換は一度だけ行い、以降のフレームでは同じ結果を表示します。レンダラーでは、サンプリング用と書き込み用テクスチャのバインド、画像全体を覆うためのグループ数の切り上げ、シェーダー内の境界検査を確認できます。' +samples.computeShader.details: '{computeShaderRendererCs} · {computeShaderSlang}' +samples.computeShader.title: 'コンピュートシェーダー' +samples.cube.description: '立方体では、インデックス付き描画、定数バッファー内のモデル・ビュー・投影行列、深度テストを加えます。{d32FloatS8UInt} の深度ステンシルテクスチャはリサイズ時に再作成します。' +samples.cube.details: '{spinningCubeRendererCs} · {spinningCubeSlang}' +samples.cube.title: '回転する立方体' +samples.description: '各サンプルは C# のレンダラーと Slang シェーダーを組み合わせ、一つの手法を扱います。アプリケーションの準備から描画までの手順は、{link}で説明します。' +samples.description.link: '最初の三角形' +samples.execution.description: '{link} プロジェクトを実行し、コンソールメニューからサンプルを選びます。' +samples.execution.description.link: 'ZenithTutorials' +samples.execution.title: 'サンプルの実行' +samples.host.description: '{appCs} はコンテキスト、ウィンドウ、スワップチェーンを初期化します。各フレームではコマンドバッファーを取得し、選択したレンダラーを呼び、送信と提示を行います。{iRendererCs} は更新、描画、リサイズ、解放の操作を定義します。' +samples.host.details: 'コンピュートとレイトレーシングのレンダラーは、オフスクリーンテクスチャを生成します。{texturePresenterCs} と {presentTextureSlang} がその内容を現在の drawable に描画し、共通ホストがコマンドを送信してフレームを提示します。' +samples.host.title: 'ホストと提示' +samples.indirectDrawing.description: '間接描画では、インデックス付き描画の引数バッファーとインスタンスごとの構造化データを使い、複数の立方体を描きます。CPU が引数を設定し、変換を更新します。' +samples.indirectDrawing.details: '{indirectDrawingRendererCs} · {indirectDrawingSlang}' +samples.indirectDrawing.title: '間接描画' +samples.meshShading.description: 'タスクシェーダーが球のインスタンスをカリングし、残ったインデックスを、ジオメトリを生成するメッシュシェーダーへ渡します。パイプライン作成前に {contextCapabilitiesMeshShadingSupported} を確認します。' +samples.meshShading.details: '{meshShadingRendererCs} · {meshShadingSlang}' +samples.meshShading.title: 'メッシュシェーディング' +samples.rayTracing.description: '床と手続き的な球の下位・上位アクセラレーション構造を構築し、コンピュートシェーダー内でインラインレイクエリを実行します。初期化前に {contextCapabilitiesRayTracingSupported} を確認します。' +samples.rayTracing.details: '{rayTracingRendererCs} · {rayTracingSlang}' +samples.rayTracing.title: 'レイトレーシング' +samples.title: 'サンプル' +samples.triangle.description: '頂点バッファーと対応する入力レイアウトを関連付け、グラフィックスパイプラインで三つの頂点から三角形を描きます。' +samples.triangle.details: '{helloTriangleRendererCs} · {helloTriangleSlang} · {link}' +samples.triangle.details.link: '完全なチュートリアル' +samples.triangle.title: 'Hello Triangle' +samples.workloads.description: 'メインリポジトリの {link} にある応用例は、ライブラリのソースを直接参照しています。' +samples.workloads.description.link: 'Experiments ディレクトリ' +samples.workloads.details: 'ウィンドウ付きの実験は同じ Windows、macOS、Linux/X11 の提示経路を使います。Avalonia、WinForms、WPF、WinUI/Uno、MAUI のコントロールは、フレーム処理と実装ソースを含めて{link}で紹介します。' +samples.workloads.details.link: 'プラットフォーム統合' +samples.workloads.table.cornellBox.example: '{link}' +samples.workloads.table.cornellBox.example.link: 'CornellBox' +samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: 'パストレーシング、ノイズ除去、トーンマッピング、アップスケーリング、ImGui による操作を扱います。レイトレーシング対応が必要です。' +samples.workloads.table.fluidTank.example: '{link}' +samples.workloads.table.fluidTank.example.link: 'FluidTank' +samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: '計算による流体シミュレーション、段階間の依存、複数パスの表面描画を扱います。' +samples.workloads.table.headings.example: '例' +samples.workloads.table.headings.whatItDemonstratesAndRequires: '手法と要件' +samples.workloads.table.inkCanvas.example: '{link}' +samples.workloads.table.inkCanvas.example.link: 'InkCanvas' +samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: 'ネイティブウィンドウで Skia の描画と入力処理を行います。対象プラットフォームのバックエンドと Skia ネイティブライブラリが必要です。' +samples.workloads.table.platformDetection.example: '{link}' +samples.workloads.table.platformDetection.example.link: 'PlatformDetection' +samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: '各バックエンドのコンテキスト作成を試み、デバイスの機能を報告します。作成に失敗した場合は非対応と表示しますが、原因にはデバイス、ドライバー、実行時依存の不足が考えられます。' +samples.workloads.title: 'より大きなアプリケーション' +tutorial.context.description: '{graphicsContext} はバックエンドを介してアプリケーションを GPU に接続し、描画リソースを作成するためのメソッドを提供します。' +tutorial.context.details: 'コンテキストの初期化を{emphasis}に追加します。' +tutorial.context.details.emphasis: 'using ディレクティブの後、{iWindowWindow} の前' +tutorial.context.guidance: '各分岐でプラットフォームに応じたバックエンドを選び、検証を要求します。{validationMessage} のメッセージはコンソールに出力します。' +tutorial.context.imports: '{programCs} の先頭に、次の using ディレクティブを追加します。' +tutorial.context.title: 'グラフィックスコンテキスト' +tutorial.description: 'このチュートリアルでは、空の .NET コンソールプロジェクトから始め、ウィンドウを開いて色付きの三角形を描くアプリケーションを作成します。' +tutorial.details: 'このチュートリアルでは、空のウィンドウ、単色の背景、色付きの三角形の三段階で結果を確認します。各段階でアプリケーションを実行し、表示を確かめてから次へ進んでください。' +tutorial.draw.context: '{draw} の引数は次のとおりです。' +tutorial.draw.description: '{windowRender} コールバックの {addTheTriangleDrawCommandsHereLater} を、次のコマンドで置き換えます。位置は {beginRenderPass} と {endRenderPass} の間です。' +tutorial.draw.details: '{setPipeline} はシェーダーと描画状態を選択します。頂点のバインドはパイプラインの入力レイアウトに従って解釈されるため、その前に呼びます。' +tutorial.draw.guidance: '{setVertexBufferVertexBuffer} は、転送済みの頂点データをバイトオフセット 0 から入力スロット 0 にバインドします。これは {inputLayouts} の唯一の要素に対応します。' +tutorial.draw.notes: 'これらの呼び出しは描画コマンドを記録します。既存の {submitWait} がコマンドを送信して GPU の完了を待ち、その後 {present} が完成した画像の表示を要求します。三角形の外側にも決まった背景色を表示するため、パスの先頭のクリア処理は残します。' +tutorial.draw.table.firstInstance.meaning: 'インスタンスの番号付けをゼロから開始します。' +tutorial.draw.table.firstVertex.meaning: 'バッファー内の最初の頂点から開始します。' +tutorial.draw.table.headings.argument: '引数' +tutorial.draw.table.headings.description: '値' +tutorial.draw.table.headings.meaning: '意味' +tutorial.draw.table.instanceCount.meaning: '三角形を一つ描きます。' +tutorial.draw.table.vertexCount.meaning: '3 つの頂点を読み取ります。' +tutorial.draw.title: '描画コマンド' +tutorial.execution.description: '{firstTriangle} プロジェクトをビルドして実行します。' +tutorial.execution.details: '暗い背景の上に、上が赤、右下が緑、左下が青の三角形が表示されます。内部の色は頂点色を補間したもので、滑らかなグラデーションになります。' +tutorial.execution.guidance: 'リサイズすると画像のピクセル寸法が変わりますが、頂点座標は変わりません。ビューポートは同じ座標を新しい幅と高さに対応付けるため、ウィンドウの縦横比を変えると三角形が伸縮します。' +tutorial.execution.title: 'アプリケーションの実行' +tutorial.frame.commands.context: '{endRenderPass} の後、二回目の遷移で出力テクスチャを提示可能な状態にします。{submit} は記録を終えてコマンドを送信し、{wait} はその完了まで待機します。続く {present} が描画済み画像の表示を要求します。' +tutorial.frame.commands.description: 'レンダーパスは、同じアタッチメントに書き込む描画操作をまとめます。このパスではスワップチェーンの drawable が色の出力先です。{colorAttachmentClear} は、アタッチメントを RGBA 色で初期化し、パス終了時に内容を保持するよう指定します。{beginRenderPass} は、この設定でパスを開始するコマンドを記録します。' +tutorial.frame.commands.details: 'コレクションにはカラーアタッチメントを一つ入れます。{null} は深度ステンシルアタッチメントを使わない指定です。' +tutorial.frame.commands.guidance: '{beginRenderPass} は、アタッチメント全体を覆うビューポートとシザーを設定します。ビューポートは描画座標をピクセル位置に変換し、シザーは書き込める範囲を制限します。' +tutorial.frame.commands.title: 'クリア、送信、提示' +tutorial.frame.description: 'まず、ウィンドウを単色の背景で埋めます。この操作をクリアと呼びます。背景が表示されれば、サーフェス、コマンド送信、提示の流れが動いています。ここに三角形の頂点とシェーダーを加えていきます。' +tutorial.frame.details: 'Silk.NET は描画のタイミングでコールバックを呼びます。この例では経過時間の引数を使わないため、パラメーター名を {value} にしています。コールバックを{emphasis}に登録します。' +tutorial.frame.details.emphasis: '{windowRun} の前' +tutorial.frame.target.description: '{graphicsQueueCommandBuffer} は記録可能なコマンドバッファーを返します。記録は GPU の処理を定義する段階であり、実行は送信後に始まります。' +tutorial.frame.target.details: 'テクスチャレイアウトは、操作がテクスチャにどうアクセスするかを表します。最初の {transition} で、出力テクスチャをカラーアタッチメントとして使える状態にします。ここでの {default} は mip レベル 0 と配列レイヤー 0、つまり出力テクスチャの基本画像を選びます。このパスでは画像全体をクリアするため、{undefined} を指定して以前の内容を破棄できます。' +tutorial.frame.target.guidance: '提示すると別の画像に切り替わることがあるため、毎フレーム、現在の drawable を取得します。' +tutorial.frame.target.title: 'drawable の準備' +tutorial.frame.title: '最初のフレーム' +tutorial.geometry.data.description: '頂点配列を{emphasis}に追加します。以後のリソース初期化も、説明する順序でこのコールバックの前に置きます。' +tutorial.geometry.data.description.emphasis: '{windowRender} の前' +tutorial.geometry.data.details: '各要素は {vertex} を作り、内側の二つの {new} が {vector3} の位置と {vector4} の色を渡します。位置は上、右下、左下の頂点です。頂点シェーダーで第四成分 {w} を加えます。w が 1 なので x と y は正規化デバイス座標でもあり、-1 と +1 が画像の端、0 が中央を表します。この意味はピクセル寸法に依存しません。' +tutorial.geometry.data.guidance: '各色は赤、緑、青、アルファの成分を持ち、アルファは 1 です。三つの頂点はすべて z = 0 で、同じ平面上にあります。' +tutorial.geometry.data.title: '頂点の位置と色' +tutorial.geometry.description: '三角形の各頂点には位置と色があります。GPU は三つの位置から形を決め、頂点色を補間して内部の色を求めます。' +tutorial.geometry.format.description: '頂点の宣言を{emphasis}に追加します。' +tutorial.geometry.format.description.emphasis: '{programCs} の末尾、解放処理の後' +tutorial.geometry.format.details: '{file} は型の使用範囲を {programCs} に限定し、{layoutKindSequential} はフィールドの宣言順を保ちます。{position} は三つの 32 ビット浮動小数点数を含み、バイトオフセット 0 から始まります。{color} は四つを含み、バイトオフセット 12 から始まります。したがって、頂点一つの大きさは 28 バイトです。後で入力レイアウトにこの配置を指定し、GPU が各フィールドを正しく読めるようにします。' +tutorial.geometry.format.imports: 'ベクトル型と構造体のレイアウト属性を使うため、{programCs} の先頭に次の using ディレクティブを追加します。' +tutorial.geometry.format.title: '頂点の表現' +tutorial.geometry.title: '頂点データ' +tutorial.geometry.upload.context: '{fixed} は、配列のアドレスを使用している間、ガベージコレクターが配列を移動しないようにします。この CPU 書き込み可能なバッファーでは、{upload} がメモリをマッピングし、データをコピーして、マッピングを解除してから戻ります。そのため、配列の固定が必要なのは呼び出し中だけです。頂点は初期化時に一度アップロードし、バッファーは描画が終わるまで保持します。' +tutorial.geometry.upload.description: '描画時に GPU が読み取れるよう、頂点を {buffer} に格納します。配列の直後に、バッファーの確保とアップロードを追加します。' +tutorial.geometry.upload.details: 'サイズは {sizeofVertexVerticesLength}、つまり 28 バイトの頂点三つで 84 バイトです。{bufferUsagesVertex} は頂点入力用途、{cpuWriteOnly} は CPU による直接初期化を許可します。記述のストライドは要素サイズを表します。各属性の読み方は、後で作る入力レイアウトが定めます。' +tutorial.geometry.upload.guidance: '確保しただけではデータは入りません。{upload} が、データ記述に渡した元ポインターとバイト数を使い、配列をバッファーのオフセット 0 にコピーします。' +tutorial.geometry.upload.imports: 'Zenith.NET のバッファー型を {systemBuffer} と区別するため、{programCs} の using ディレクティブに {bufferAlias} を追加します。' +tutorial.geometry.upload.notes: '{programCs} 末尾の解放処理で、{swapChainDispose} の直前に {vertexBufferDispose} を加えます。大きな静的ジオメトリ向けの GPU 専用メモリと転送は{link}で説明します。' +tutorial.geometry.upload.notes.link: 'リソース管理' +tutorial.geometry.upload.title: 'バッファーの確保と転送' +tutorial.input.description: 'GPU は位置や色などの頂点属性がどこにあるかを知る必要があります。入力レイアウトで各属性のフォーマットとバイトオフセットを指定し、ストライドで次の頂点までのバイト数を示します。シェーダー作成後に次のコードを加えます。' +tutorial.input.details: '{inputLayoutAdd} は属性を順番に並べ、各属性のサイズをストライドに加算します。オフセットは C# の構造体を調べて得るのではなく、ここで指定したフォーマットから計算されます。この二つのフィールドでは、次の配置になります。' +tutorial.input.guidance: '{semanticIndex} の既定値は 0 で、シェーダーの {pOSITION0} と {cOLOR0} に対応します。位置と色は一つの頂点バッファーに格納するため、パイプラインにはスロット 0 の入力レイアウトを一つ指定します。C# のフィールド順やパディングを変えた場合は、入力レイアウトも合わせて変更してください。' +tutorial.input.table.headings.byteOffset: 'バイトオフセット' +tutorial.input.table.headings.cField: 'C# フィールド' +tutorial.input.table.headings.format: 'フォーマット' +tutorial.input.table.headings.shaderInput: 'シェーダー入力' +tutorial.input.table.nextVertex.cField: '次の頂点' +tutorial.input.table.nextVertex.format: '合計ストライド:28 バイト' +tutorial.input.table.nextVertex.shaderInput: '次の入力レコード' +tutorial.input.table.vertexColor.format: '{float4} (16 バイト)' +tutorial.input.table.vertexPosition.format: '{float3} (12 バイト)' +tutorial.input.title: '頂点入力レイアウト' +tutorial.lifecycle.description: '各フレームは次の順で進みます。' +tutorial.lifecycle.details: 'ウィンドウを閉じると {run} が戻り、解放処理へ進みます。各フレームで送信した処理の完了を待っているため、その処理で使用したリソースは解放できます。{windowRun} の後に置く解放処理の全体は次のとおりです。' +tutorial.lifecycle.guidance: 'スワップチェーンはネイティブウィンドウを破棄する前に、コンテキストはそのリソースを解放した後に解放します。送信済みコマンドバッファーはキューが回収し、drawable はスワップチェーンが管理するため、どちらにも個別の {dispose} 呼び出しは不要です。' +tutorial.lifecycle.title: 'フレームの流れと終了処理' +tutorial.pipeline.behavior: '入力レイアウトの後にパイプラインを作成します。' +tutorial.pipeline.context: '{cullNone} は面のカリングを無効にします。頂点が画面上で時計回りに並んでいても、反時計回りに並んでいても、三角形を描画します。' +tutorial.pipeline.description: '{graphicsPipeline} は、頂点レイアウト、二つのシェーダー、プリミティブの組み立てとアタッチメントへの出力設定をまとめます。' +tutorial.pipeline.details: '頂点とフラグメントの処理はシェーダーが担当します。パイプラインの残りの設定では、プリミティブの組み立て、面のカリング、深度テスト、ブレンドを指定します。' +tutorial.pipeline.guidance: 'パイプラインのカラーフォーマットはパスのアタッチメントに合わせ、{swapChainDescFormat} から取得します。{count1} は一ピクセル一サンプルです。' +tutorial.pipeline.item: '{triangleList} は連続する三つの頂点を一組として、三角形を組み立てます。' +tutorial.pipeline.notes: '{depthNone} は深度テストと深度書き込みを無効にします。深度アタッチメントを使わないパスと対応します。' +tutorial.pipeline.reference: '{opaque} はブレンドを無効にします。三角形の内部では、フラグメントシェーダーの色が背景を置き換えます。' +tutorial.pipeline.title: 'グラフィックスパイプライン' +tutorial.pipeline.usage: 'シェーダーオブジェクトはパイプライン作成後に解放できます。パイプラインは描画中保持し、終了処理で {vertexBufferDispose} の前に {pipelineDispose} を加えます。' +tutorial.presentation.title: 'グラフィックスコンテキストと提示' +tutorial.project.context: 'プロジェクトのビルド設定で {emphasis}({allowUnsafeBlocks})を有効にします。ウィンドウ補助コードのネイティブ呼び出しと頂点の転送に unsafe コードが必要です。' +tutorial.project.context.emphasis: 'アンセーフコードの許可' +tutorial.project.description: '.NET 10 を対象とする、{firstTriangle} という名前の C# コンソールプロジェクトを作成します。' +tutorial.project.details: 'プロジェクトに次の NuGet パッケージを追加します。' +tutorial.project.guidance: '{zenithNET} が共通の描画 API を、三つのバックエンドパッケージが各実装を提供します。{zenithNETCompiler} は後で作る Slang シェーダーを対象バックエンド向けにコンパイルします。Silk.NET はウィンドウの作成とイベント処理を担当します。' +tutorial.project.title: 'プロジェクトの準備' +tutorial.requirements.context: '{link}とその{detail}が、このチュートリアルの参照実装です。' +tutorial.requirements.context.detail: '共有ホスト' +tutorial.requirements.context.link: 'Hello Triangle サンプル' +tutorial.requirements.description: '{emphasis} と C# の基礎知識が必要です。アプリケーションの対象フレームワークは {net10} です。GPU とドライバーは、プラットフォームごとに選ぶ次のバックエンドに対応している必要があります。' +tutorial.requirements.description.emphasis: '.NET 10 SDK' +tutorial.requirements.guidance: 'Zenith.NET はアプリケーションから渡されたネイティブサーフェスへ描画します。Silk.NET.Windowing がウィンドウとイベントを管理します。macOS の提示には {cAMetalLayerCs} で表される Metal レイヤーを使い、補助コードがウィンドウへ取り付けます。' +tutorial.requirements.table.headings.graphicsBackend: 'グラフィックスバックエンド' +tutorial.requirements.table.headings.platform: 'プラットフォーム' +tutorial.requirements.table.linux.graphicsBackend: 'Vulkan 1.4' +tutorial.requirements.table.linux.platform: 'Linux(X11 または XWayland)' +tutorial.requirements.table.macOS.graphicsBackend: 'Metal 4' +tutorial.requirements.table.macOS.platform: 'macOS' +tutorial.requirements.table.windows.graphicsBackend: 'DirectX 12' +tutorial.requirements.table.windows.platform: 'Windows' +tutorial.requirements.title: '前提条件' +tutorial.resize.context: 'アプリケーションをもう一度ビルドして実行します。リサイズしても背景がウィンドウ全体を覆うことを確認してください。新しいレンダーパスでは、変更後のアタッチメントの寸法からビューポートとシザーが設定されます。描画コールバックはそのまま残し、後でこのパスに三角形の描画を加えます。' +tutorial.resize.description: 'フレームバッファーの寸法が変わったら、スワップチェーンも合わせて変更します。描画コールバックの後、{windowRun} の前に {framebufferResize} のコールバックを登録します。' +tutorial.resize.details: 'ウィンドウの論理寸法ではなく、ピクセル単位の{link}を受け取ります。最小化によって幅か高さがゼロになった場合、リサイズコールバックはスワップチェーンを変更しません。描画コールバックも、どちらかの寸法がゼロの間はそのまま戻ります。有効な寸法に戻るまで描画を中断するためです。' +tutorial.resize.details.link: 'フレームバッファーサイズの変化' +tutorial.resize.guidance: '描画コールバックは、送信したフレームの完了を待ってから {present} を呼びます。そのため、リサイズコールバックがスワップチェーンの画像を置き換える時点では、以前のフレームによる処理は終わっています。完了とリソースの寿命に関する条件は、{link}で詳しく説明します。' +tutorial.resize.guidance.link: '同期' +tutorial.resize.title: 'リサイズ' +tutorial.shaders.compilation.context: '{appContextBaseDirectory} を使うと、コピーしたシェーダーをアプリケーションの出力ディレクトリから読み込みます。別の作業ディレクトリから起動しても、ファイルを探す場所は変わりません。' +tutorial.shaders.compilation.description: '{triangleSlang} のファイルプロパティで {emphasis} を {detail} に設定します。ビルド時にシェーダーが実行ファイルの隣へコピーされます。' +tutorial.shaders.compilation.description.detail: '新しい場合はコピーする' +tutorial.shaders.compilation.description.emphasis: '出力ディレクトリにコピー' +tutorial.shaders.compilation.details: '{programCs} に戻り、頂点のアップロード後、描画コールバック前にシェーダーの初期化を追加します。' +tutorial.shaders.compilation.guidance: '{zenithCompiler} は {contextGraphicsApi} のバックエンド向けにソースをコンパイルします。{createShader} は、コンパイル済みの記述からシェーダーオブジェクトを作成します。エントリーポイント名 {vSMain} と {fSMain} は、Slang ファイルに定義した二つの関数を選択します。' +tutorial.shaders.compilation.title: 'シェーダーのコンパイル' +tutorial.shaders.context: '{fSInput} は二つのシェーダーステージをつなぎます。頂点シェーダーはクリップ空間の位置を {sVPOSITION} に書き込み、GPU はその位置から三角形の見える範囲を判断します。{cOLOR0} は頂点色を渡すフィールドです。色は三角形の内部で補間されてから、フラグメントシェーダーに届きます。両ステージで色の型とセマンティクスを一致させる必要があります。' +tutorial.shaders.description: 'シェーダーは GPU 上で実行するプログラムです。頂点シェーダーは各頂点の位置を決め、フラグメントシェーダーは画像の覆われた位置の色を決めます。両ステージを一つの Slang ファイルに書き、それぞれにエントリーポイントを定義します。エントリーポイントは、そのステージの実行が始まる関数です。' +tutorial.shaders.details: '{triangleSlang} を作成し、次の入出力構造体を書きます。' +tutorial.shaders.fragment.description: '同じファイルにフラグメントのエントリーポイントを追加します。' +tutorial.shaders.fragment.details: 'ラスタライズは三角形が画像を覆う範囲を調べ、その位置にフラグメントを生成します。各フラグメントの色は、三つの頂点色を補間して求めます。{fSMain} がその色を返し、{sVTARGET} が最初のカラーアタッチメントへの出力を指定します。' +tutorial.shaders.fragment.title: 'フラグメントシェーダー' +tutorial.shaders.guidance: '{vSInput} は頂点シェーダーの入力です。{pOSITION0} と {cOLOR0} はセマンティクスによって属性を対応付けます。C# のフィールド名だけでは、この対応は決まりません。' +tutorial.shaders.title: 'シェーダーステージ' +tutorial.shaders.vertex.description: '{triangleSlang} に頂点のエントリーポイントを追加します。' +tutorial.shaders.vertex.details: 'GPU は入力頂点ごとにこの関数を呼びます。同次座標 {w} を追加し、色をそのまま渡します。頂点処理後に位置を w で割りますが、ここでは 1 なので x、y、z は変わらず、正規化デバイス座標として直接解釈できます。' +tutorial.shaders.vertex.title: '頂点シェーダー' +tutorial.surface.description: 'ネイティブの提示先を{emphasis}に指定します。' +tutorial.surface.description.emphasis: '{windowCenter} の後、{windowRun} の前' +tutorial.surface.details: 'フレームバッファーは、ウィンドウが表示するピクセル画像です。{surface} はネイティブの提示先と寸法を記述し、{framebufferSize} はピクセル単位のサイズを返します。表示倍率によっては、ウィンドウの論理サイズと異なります。' +tutorial.surface.guidance: 'サーフェスにはバックエンドが必要とするネイティブハンドルを渡します。Windows は Win32 ウィンドウ、Linux は X11 のディスプレイとウィンドウ、macOS は取り付けた Metal レイヤーを使います。' +tutorial.surface.title: 'ネイティブサーフェス' +tutorial.swapChain.context: 'スワップチェーンはコンテキストとウィンドウの両方に依存します。{programCs} 末尾の {windowDispose} を次の解放順序に置き換えます。' +tutorial.swapChain.description: 'サーフェス記述の直後にスワップチェーンを作成します。' +tutorial.swapChain.details: '{swapChain} はウィンドウが提示する画像を管理します。{drawable} は現在の画像を、API の画像リソースである {texture} として返します。描画後に {present} が表示を要求し、次の drawable へ進みます。' +tutorial.swapChain.guidance: '{b8G8R8A8UNorm} は青、緑、赤、アルファの順に各 8 ビットを格納します。{uNorm} は整数 0~255 を 0~1 に対応付けます。シェーダー出力は論理的な RGBA のままで、フォーマットは保存表現を定めます。パイプラインは {swapChainDescFormat} でこのアタッチメントに合わせます。' +tutorial.swapChain.title: 'スワップチェーン' +tutorial.title: '最初の三角形' +tutorial.troubleshooting.description: 'コンソールの診断と三段階の結果を使い、問題のある箇所を特定します。' +tutorial.troubleshooting.details: '{link}と{detail}で頂点データ、入力レイアウト、描画操作を照合できます。サンプルはウィンドウと送信を共通ホストへ分離していますが、このチュートリアルの処理は {programCs} にまとめています。{context}ではインデックス付き描画、変換、深度テストへ進みます。' +tutorial.troubleshooting.details.context: '回転する立方体' +tutorial.troubleshooting.details.detail: 'Slang シェーダー' +tutorial.troubleshooting.details.link: 'サンプルレンダラー' +tutorial.troubleshooting.table.backend.check: '選択したバックエンドがデバイスおよびインストールされているグラフィックスドライバーでサポートされていることを確認してください。' +tutorial.troubleshooting.table.backend.symptom: 'バックエンドの作成に失敗する' +tutorial.troubleshooting.table.drawing.check: 'アップロードサイズ、入力レイアウト、パイプラインの選択、およびレンダーパス内の描画コマンドの配置を確認してください。' +tutorial.troubleshooting.table.drawing.symptom: '背景は表示されるが三角形が表示されない' +tutorial.troubleshooting.table.headings.check: '確認事項' +tutorial.troubleshooting.table.headings.symptom: '症状' +tutorial.troubleshooting.table.input.check: 'ストライドが 28 バイト、位置と色のオフセットがそれぞれ 0 と 12 バイトであることを確認します。' +tutorial.troubleshooting.table.input.symptom: '頂点の位置や色が破損している' +tutorial.troubleshooting.table.shaders.check: 'コピーされた {triangleSlang}、エントリーポイントのスペル、およびコンパイラーが報告した診断情報を確認してください。' +tutorial.troubleshooting.table.shaders.symptom: '背景色は表示されるがシェーダーを読み込めない' +tutorial.troubleshooting.table.window.check: '.NET プロジェクトがビルドされ、ウィンドウ単体のステップがデスクトップセッションで実行されることを確認してください。Linux では、X11 または XWayland が利用可能であることを確認してください。' +tutorial.troubleshooting.table.window.symptom: 'ウィンドウが開かない' +tutorial.troubleshooting.title: '問題の切り分け' +tutorial.window.description: '{cocoaHelperCs} をダウンロードしてプロジェクトに追加します。この補助クラスが macOS のウィンドウに Metal レイヤーを取り付けます。' +tutorial.window.details: '自動生成された {programCs} の内容を、次のコードに置き換えます。トップレベルステートメントを使うため、明示的な {main} メソッドを書かずに、上から順に実行できます。続く各節でコードを追加する位置を示します。' +tutorial.window.guidance: '{graphicsAPINone} で、グラフィックスコンテキストの作成を Zenith.NET に任せます。{initialize} はネイティブウィンドウを作り、ウィンドウシステムのハンドルを利用可能にします。{center} で画面中央に置き、{run} で閉じるまでイベントを処理します。その後、{dispose} でウィンドウを解放します。' +tutorial.window.notes: 'アプリケーションをビルドして実行し、ウィンドウを開く、移動する、リサイズする、閉じるという操作を確認します。描画コマンドはまだ送信していないため、表示内容は未定義です。次へ進む前にウィンドウを閉じてください。' +tutorial.window.title: 'ウィンドウの作成' +ui.action.copy: 'コピー' +ui.action.navigate: '移動' +ui.action.open: '開く' +ui.action.source: 'ソースを表示' +ui.api.browse: '名前空間と型を参照します。' +ui.api.clearTypeSearch: '型の検索をクリア' +ui.api.findType: '型を検索' +ui.api.loadError: '型を読み込めませんでした。このページを再読み込みしてやり直してください。' +ui.api.loadingNamespaces: '名前空間を読み込み中…' +ui.api.loadingTypes: '型を読み込み中…' +ui.api.matchingTypes: '一致する型' +ui.api.namespace: '名前空間' +ui.api.namespaces: '名前空間' +ui.api.noNamespaceTypes: 'この名前空間には型がありません。' +ui.api.noTypes: '一致する型はありません。' +ui.api.types: '型' +ui.content.reference: 'リファレンス' +ui.content.source: 'ソースコード' +ui.content.tutorial: 'チュートリアル' +ui.contents.close: '目次を閉じる' +ui.contents.open: '目次を開く' +ui.contents.title: '目次' +ui.footer.caption: '.NET 向けのモダンな RHI' +ui.footer.label: 'フッター' +ui.language.label: '言語' +ui.language.unavailable: '未翻訳' +ui.members.clear: 'メンバー検索をクリア' +ui.members.close: 'メンバー検索を閉じる' +ui.members.empty: '一致するメンバーはありません。' +ui.members.open: 'メンバーへ移動' +ui.members.placeholder: '名前またはシグネチャ…' +ui.members.search: 'メンバーを検索' +ui.members.title: 'メンバーを検索' +ui.members.undeclared: 'この型には宣言されたメンバーがありません。' +ui.navigation.api: 'API' +ui.navigation.concepts: '概念' +ui.navigation.home: 'ホーム' +ui.navigation.label: 'メインナビゲーション' ui.navigation.skip: 本文へ移動 -ui.navigation.toggle: "ナビゲーションの切り替え" -ui.outline.title: "このページの内容" -ui.reference.assembly: "アセンブリ" -ui.reference.classes: "クラス" -ui.reference.constructors: "コンストラクター" -ui.reference.declaration: "C# 型宣言" -ui.reference.delegates: "デリゲート" -ui.reference.derived: "派生型" -ui.reference.enums: "列挙型" -ui.reference.events: "イベント" -ui.reference.examples: "例" -ui.reference.exceptions: "例外" -ui.reference.extensionMethods: "拡張メソッド" -ui.reference.fields: "フィールド" -ui.reference.implementations: "明示的なインターフェイスの実装" -ui.reference.implements: "実装" -ui.reference.inheritance: "継承" -ui.reference.inheritedMembers: "継承されたメンバー" -ui.reference.interfaces: "インターフェイス" -ui.reference.metadata: "型のメタデータ" -ui.reference.methods: "メソッド" -ui.reference.namespace: "名前空間" -ui.reference.open: "{name} のリファレンスを開く" -ui.reference.operators: "演算子" -ui.reference.parameters: "パラメーター" -ui.reference.properties: "プロパティ" -ui.reference.related: "関連項目" -ui.reference.relationships: "継承とメタデータ" -ui.reference.remarks: "注記" -ui.reference.returns: "戻り値" -ui.reference.structs: "構造体" -ui.reference.typeParameters: "型パラメーター" -ui.reference.value: "値" -ui.reference.values: "値" -ui.search.close: "検索を閉じる" -ui.search.empty: "「{query}」に一致する結果は見つかりませんでした。" -ui.search.hint: "チュートリアル、概念、サンプル、API リファレンスを検索します。" -ui.search.loading: "検索を読み込み中…" -ui.search.more: "さらに結果を表示" -ui.search.pending: "検索中…" -ui.search.placeholder: "何をお探しですか?" -ui.search.resultCount: "検索結果: {count} 件" -ui.search.title: "ドキュメントを検索" -ui.search.unavailable: "検索は利用できません。以下のページを直接開くことができます。" +ui.navigation.toggle: 'ナビゲーションの切り替え' +ui.outline.title: 'このページの内容' +ui.reference.assembly: 'アセンブリ' +ui.reference.classes: 'クラス' +ui.reference.constructors: 'コンストラクター' +ui.reference.declaration: 'C# 型宣言' +ui.reference.delegates: 'デリゲート' +ui.reference.derived: '派生型' +ui.reference.enums: '列挙型' +ui.reference.events: 'イベント' +ui.reference.examples: '例' +ui.reference.exceptions: '例外' +ui.reference.extensionMethods: '拡張メソッド' +ui.reference.fields: 'フィールド' +ui.reference.implementations: '明示的なインターフェイスの実装' +ui.reference.implements: '実装' +ui.reference.inheritance: '継承' +ui.reference.inheritedMembers: '継承されたメンバー' +ui.reference.interfaces: 'インターフェイス' +ui.reference.metadata: '型のメタデータ' +ui.reference.methods: 'メソッド' +ui.reference.namespace: '名前空間' +ui.reference.open: '{name} のリファレンスを開く' +ui.reference.operators: '演算子' +ui.reference.parameters: 'パラメーター' +ui.reference.properties: 'プロパティ' +ui.reference.related: '関連項目' +ui.reference.relationships: '継承とメタデータ' +ui.reference.remarks: '注記' +ui.reference.returns: '戻り値' +ui.reference.structs: '構造体' +ui.reference.typeParameters: '型パラメーター' +ui.reference.value: '値' +ui.reference.values: '値' +ui.search.close: '検索を閉じる' +ui.search.empty: '「{query}」に一致する結果は見つかりませんでした。' +ui.search.hint: 'チュートリアル、概念、サンプル、API リファレンスを検索します。' +ui.search.loading: '検索を読み込み中…' +ui.search.more: 'さらに結果を表示' +ui.search.pending: '検索中…' +ui.search.placeholder: '何をお探しですか?' +ui.search.resultCount: '検索結果: {count} 件' +ui.search.title: 'ドキュメントを検索' +ui.search.unavailable: '検索は利用できません。以下のページを直接開くことができます。' diff --git a/documents/locales/ja-JP/translation.md b/documents/locales/ja-JP/translation.md index 70baf9a1..cfc3ef31 100644 --- a/documents/locales/ja-JP/translation.md +++ b/documents/locales/ja-JP/translation.md @@ -2,7 +2,7 @@ ## リソースと構成 -[英語のリソース辞書](../en-US/strings.yml)を唯一の原文とします。プロジェクトの規約は[ドキュメント保守ガイド](../../authoring.md)を参照してください。新しい翻訳を始めるときは、英語のファイル全体をこのディレクトリの `strings.yml` にコピーします。先頭行の `### YamlMime:Resources` と UTF-8 エンコーディングを維持してください。更新時は英語の変更点を既存の訳文に反映し、ファイル全体を上書きしないでください。この `translation.md` は翻訳後も保持し、サイトには公開しません。 +[英語のリソース辞書](../en-US/strings.yml)を唯一の原文とします。プロジェクトの規約は[ドキュメント保守ガイド](../../maintenance.md)を参照してください。新しい翻訳を始めるときは、英語のファイル全体をこのディレクトリの `strings.yml` にコピーします。先頭行の `### YamlMime:Resources` と UTF-8 エンコーディングを維持してください。更新時は英語の変更点を既存の訳文に反映し、ファイル全体を上書きしないでください。この `translation.md` は翻訳後も保持し、サイトには公開しません。 ナビゲーション、章の順序、アンカー、リンク、書式、コード、画像は `locales/` の外で共通管理します。このディレクトリに記事、TOC、テンプレート、スクリプト、設定を追加しないでください。 @@ -65,21 +65,21 @@ docfx serve documents/_site --hostname 127.0.0.1 --port 8080 ## 用語 -| 英語 | 使用する表現 | -| --- | --- | -| API / GPU / RHI | 略語を維持し、原文に従って説明する | -| barrier | バリア | -| buffer | バッファー。`Buffer` は変更しない | -| command buffer | コマンドバッファー | -| command queue | コマンドキュー | -| drawable | 現在のフレームの出力テクスチャ。`Drawable` は変更せず、常にスワップチェーンの画像とは解釈しない | -| graphics context | グラフィックスコンテキスト | -| pipeline | パイプライン | -| readback | リードバック | -| render pass | レンダーパス | -| resource | リソース | -| shader | シェーダー | -| swap chain | スワップチェーン | -| texture | テクスチャ | -| timeline | タイムライン | -| upload | アップロード | +| 英語 | 使用する表現 | +| ---------------- | ----------------------------------------------------------------------------------------------- | +| API / GPU / RHI | 略語を維持し、原文に従って説明する | +| barrier | バリア | +| buffer | バッファー。`Buffer` は変更しない | +| command buffer | コマンドバッファー | +| command queue | コマンドキュー | +| drawable | 現在のフレームの出力テクスチャ。`Drawable` は変更せず、常にスワップチェーンの画像とは解釈しない | +| graphics context | グラフィックスコンテキスト | +| pipeline | パイプライン | +| readback | リードバック | +| render pass | レンダーパス | +| resource | リソース | +| shader | シェーダー | +| swap chain | スワップチェーン | +| texture | テクスチャ | +| timeline | タイムライン | +| upload | アップロード | diff --git a/documents/locales/ko-KR/strings.yml b/documents/locales/ko-KR/strings.yml index 18b11508..5396aadf 100644 --- a/documents/locales/ko-KR/strings.yml +++ b/documents/locales/ko-KR/strings.yml @@ -1,360 +1,360 @@ ### YamlMime:Resources -concepts.execution.context.description: "{graphicsContext}는 특정 백엔드를 통해 애플리케이션을 GPU 장치에 연결하고 그래픽스, 컴퓨트, 전송 큐를 제공합니다. 함께 사용하는 리소스는 같은 컨텍스트에 속해야 합니다. 버퍼, 텍스처, 셰이더, 파이프라인과 그 핸들은 서로 다른 컨텍스트 사이에서 바인딩할 수 없습니다." -concepts.execution.context.details: "{capabilities}는 장치 이름과 지원 기능을 알려 줍니다. 해당 기능의 리소스를 만들기 전에 {rayTracingSupported}와 {meshShadingSupported}로 지원 여부를 확인합니다. {link} 및 {detail} 예제는 초기화 과정에서 이 검사를 수행합니다." +concepts.execution.context.description: '{graphicsContext}는 특정 백엔드를 통해 애플리케이션을 GPU 장치에 연결하고 그래픽스, 컴퓨트, 전송 큐를 제공합니다. 함께 사용하는 리소스는 같은 컨텍스트에 속해야 합니다. 버퍼, 텍스처, 셰이더, 파이프라인과 그 핸들은 서로 다른 컨텍스트 사이에서 바인딩할 수 없습니다.' +concepts.execution.context.details: '{capabilities}는 장치 이름과 지원 기능을 알려 줍니다. 해당 기능의 리소스를 만들기 전에 {rayTracingSupported}와 {meshShadingSupported}로 지원 여부를 확인합니다. {link} 및 {detail} 예제는 초기화 과정에서 이 검사를 수행합니다.' concepts.execution.context.details.detail: 메시 셰이딩 concepts.execution.context.details.link: 레이 트레이싱 -concepts.execution.context.title: "그래픽스 컨텍스트" -concepts.execution.description: "GPU 작업은 CPU에서 준비합니다. 애플리케이션이 리소스를 만들고 이를 사용하는 명령을 기록한 뒤 큐에 제출하면, GPU가 명령을 실행하는 동안 CPU는 다른 작업을 계속할 수 있습니다. 사용 중인 리소스는 GPU 실행이 끝날 때까지 유효하게 유지해야 합니다." -concepts.execution.ownership.description: "소유권은 객체를 해제할 주체를 정하고, GPU 작업의 완료 여부는 해제할 수 있는 시점을 정합니다. C# 참조가 남아 있어도 {dispose}를 호출하면 네이티브 리소스가 해제됩니다. 명령을 제출한다고 해당 리소스의 소유권이 큐로 넘어가지는 않습니다." -concepts.execution.ownership.details: "애플리케이션을 종료할 때는 새 작업 제출을 중단하고, 관련된 모든 큐에서 리소스의 마지막 사용이 끝날 때까지 기다립니다. 그런 다음 애플리케이션 리소스를 해제하고 컨텍스트를 정리합니다. 컨텍스트는 자체 큐와 내부 보조 객체를 해제하므로 애플리케이션 작업이 모두 끝난 뒤 마지막에 정리해야 합니다." -concepts.execution.ownership.guidance: "렌더링 중에는 덮어쓸 데이터나 교체할 리소스를 사용하는 작업의 완료 시점을 추적합니다. 해당 작업이 끝날 때까지 기다린 뒤 저장 공간을 수정하거나 해제합니다. 뷰와 원본 리소스에도 이 수명 관리 원칙을 적용하는 방법은 {link} 문서에서 설명합니다." +concepts.execution.context.title: '그래픽스 컨텍스트' +concepts.execution.description: 'GPU 작업은 CPU에서 준비합니다. 애플리케이션이 리소스를 만들고 이를 사용하는 명령을 기록한 뒤 큐에 제출하면, GPU가 명령을 실행하는 동안 CPU는 다른 작업을 계속할 수 있습니다. 사용 중인 리소스는 GPU 실행이 끝날 때까지 유효하게 유지해야 합니다.' +concepts.execution.ownership.description: '소유권은 객체를 해제할 주체를 정하고, GPU 작업의 완료 여부는 해제할 수 있는 시점을 정합니다. C# 참조가 남아 있어도 {dispose}를 호출하면 네이티브 리소스가 해제됩니다. 명령을 제출한다고 해당 리소스의 소유권이 큐로 넘어가지는 않습니다.' +concepts.execution.ownership.details: '애플리케이션을 종료할 때는 새 작업 제출을 중단하고, 관련된 모든 큐에서 리소스의 마지막 사용이 끝날 때까지 기다립니다. 그런 다음 애플리케이션 리소스를 해제하고 컨텍스트를 정리합니다. 컨텍스트는 자체 큐와 내부 보조 객체를 해제하므로 애플리케이션 작업이 모두 끝난 뒤 마지막에 정리해야 합니다.' +concepts.execution.ownership.guidance: '렌더링 중에는 덮어쓸 데이터나 교체할 리소스를 사용하는 작업의 완료 시점을 추적합니다. 해당 작업이 끝날 때까지 기다린 뒤 저장 공간을 수정하거나 해제합니다. 뷰와 원본 리소스에도 이 수명 관리 원칙을 적용하는 방법은 {link} 문서에서 설명합니다.' concepts.execution.ownership.guidance.link: 리소스 관리 concepts.execution.ownership.table.applicationResources.object: 애플리케이션이 생성한 리소스 concepts.execution.ownership.table.applicationResources.ownership: 애플리케이션이 마지막 GPU 사용 후 해제합니다. concepts.execution.ownership.table.commandBuffers.object: 대여한 명령 버퍼 concepts.execution.ownership.table.commandBuffers.ownership: 큐가 관리하고 재활용합니다. -concepts.execution.ownership.table.headings.object: "객체" -concepts.execution.ownership.table.headings.ownership: "해제 책임" +concepts.execution.ownership.table.headings.object: '객체' +concepts.execution.ownership.table.headings.ownership: '해제 책임' concepts.execution.ownership.table.queues.object: 컨텍스트 큐 및 해당 타임라인 concepts.execution.ownership.table.queues.ownership: 컨텍스트와 큐가 관리합니다. concepts.execution.ownership.table.swapChainDrawable.ownership: 스왑 체인이 관리합니다. -concepts.execution.ownership.title: "소유권과 수명" -concepts.execution.pipelines.description: "그래픽스 파이프라인은 셰이더, 정점 입력 레이아웃, 프리미티브 조립, 어태치먼트의 포맷, 그리기 상태를 정의합니다. 정점, 인덱스, 상수 데이터를 바인딩하기 전에 파이프라인을 선택합니다. 어태치먼트의 포맷과 샘플 수는 렌더 패스와 일치해야 합니다." -concepts.execution.pipelines.details: "컴퓨트 파이프라인은 디스패치가 실행할 셰이더 진입점을 선택합니다. 그래픽스 렌더 패스 밖에서 파이프라인과 상수를 바인딩한 뒤 디스패치합니다." -concepts.execution.pipelines.guidance: "{link}에서는 그래픽스 명령 순서를, {detail}에서는 계산 결과를 표시하는 패스 앞에 컴퓨트 디스패치를 추가하는 구성을 볼 수 있습니다." -concepts.execution.pipelines.guidance.detail: "컴퓨트 예제" +concepts.execution.ownership.title: '소유권과 수명' +concepts.execution.pipelines.description: '그래픽스 파이프라인은 셰이더, 정점 입력 레이아웃, 프리미티브 조립, 어태치먼트의 포맷, 그리기 상태를 정의합니다. 정점, 인덱스, 상수 데이터를 바인딩하기 전에 파이프라인을 선택합니다. 어태치먼트의 포맷과 샘플 수는 렌더 패스와 일치해야 합니다.' +concepts.execution.pipelines.details: '컴퓨트 파이프라인은 디스패치가 실행할 셰이더 진입점을 선택합니다. 그래픽스 렌더 패스 밖에서 파이프라인과 상수를 바인딩한 뒤 디스패치합니다.' +concepts.execution.pipelines.guidance: '{link}에서는 그래픽스 명령 순서를, {detail}에서는 계산 결과를 표시하는 패스 앞에 컴퓨트 디스패치를 추가하는 구성을 볼 수 있습니다.' +concepts.execution.pipelines.guidance.detail: '컴퓨트 예제' concepts.execution.pipelines.guidance.link: 삼각형의 렌더링 콜백 -concepts.execution.pipelines.title: "파이프라인 상태" -concepts.execution.queues.description: "그리기, 계산, 복사를 한 프레임에서 수행한다면 일반적으로 {graphicsQueue}부터 사용합니다. 서로 의존하는 작업을 한 큐에 두면 순서를 관리하기 쉽습니다." -concepts.execution.queues.details: "큐를 나누면 독립적인 작업을 각각 제출할 수 있지만, 각 큐가 반드시 독립된 하드웨어 엔진에 대응하는 것은 아닙니다. 작업을 겹쳐 실행할 때 이점이 있다면 추가 큐를 사용합니다. 한 큐가 다른 큐에서 만든 데이터를 사용한다면 두 제출 사이에 의존성을 명시합니다." -concepts.execution.queues.guidance: "한 큐 안에서도 뒤의 접근이 앞서 쓴 데이터를 볼 수 있도록 배리어나 텍스처 전환이 필요할 수 있습니다. 이러한 메모리 의존성은 제출 순서와 구별됩니다. 구체적인 표현 방법은 {link} 문서에서 설명합니다." +concepts.execution.pipelines.title: '파이프라인 상태' +concepts.execution.queues.description: '그리기, 계산, 복사를 한 프레임에서 수행한다면 일반적으로 {graphicsQueue}부터 사용합니다. 서로 의존하는 작업을 한 큐에 두면 순서를 관리하기 쉽습니다.' +concepts.execution.queues.details: '큐를 나누면 독립적인 작업을 각각 제출할 수 있지만, 각 큐가 반드시 독립된 하드웨어 엔진에 대응하는 것은 아닙니다. 작업을 겹쳐 실행할 때 이점이 있다면 추가 큐를 사용합니다. 한 큐가 다른 큐에서 만든 데이터를 사용한다면 두 제출 사이에 의존성을 명시합니다.' +concepts.execution.queues.guidance: '한 큐 안에서도 뒤의 접근이 앞서 쓴 데이터를 볼 수 있도록 배리어나 텍스처 전환이 필요할 수 있습니다. 이러한 메모리 의존성은 제출 순서와 구별됩니다. 구체적인 표현 방법은 {link} 문서에서 설명합니다.' concepts.execution.queues.guidance.link: 동기화 -concepts.execution.queues.table.computeQueue.workToRecord: "그래픽 렌더 패스를 제외한 컴퓨트 디스패치 및 호환 가능한 전송 작업." -concepts.execution.queues.table.graphicsQueue.workToRecord: "렌더 패스, 그리기, 컴퓨트 및 전송 작업." +concepts.execution.queues.table.computeQueue.workToRecord: '그래픽 렌더 패스를 제외한 컴퓨트 디스패치 및 호환 가능한 전송 작업.' +concepts.execution.queues.table.graphicsQueue.workToRecord: '렌더 패스, 그리기, 컴퓨트 및 전송 작업.' concepts.execution.queues.table.headings.queue: 큐 -concepts.execution.queues.table.headings.workToRecord: "지원 작업" -concepts.execution.queues.table.transferQueue.workToRecord: "업로드, 다운로드 및 복사 작업. 그리기나 컴퓨트 디스패치는 지원하지 않습니다." -concepts.execution.queues.title: "큐 선택" -concepts.execution.recording.context: "큐는 완료된 명령 버퍼를 회수해 재사용합니다. 명령을 기록할 때마다 {queueCommandBuffer}로 버퍼를 가져오고, 한 번에 한 스레드에서 기록한 뒤 한 번만 제출합니다. 제출 후에는 큐가 버퍼를 관리하므로 수정하거나 다시 제출하거나 해제하지 않습니다." -concepts.execution.recording.description: "{queueCommandBuffer}가 반환하는 {commandBuffer}는 이미 기록을 시작한 상태입니다. 작업과 의존 관계를 기록한 후 {submit}을 한 번 호출합니다. 기록이 종료되고 명령이 제출되며, 해당 큐의 완료 지점을 나타내는 {timelineValue}가 반환됩니다." -concepts.execution.recording.details: "삼각형 튜토리얼은 {commandBuffer}에 프레임을 기록한 뒤 다음과 같이 제출하고 완료를 기다립니다." -concepts.execution.recording.guidance: "기록은 명령 시퀀스를 구성하고, {submit}은 그 시퀀스의 실행을 예약합니다. 이어서 {wait}를 호출하면 해당 제출이 끝날 때까지 CPU 스레드가 대기합니다. 튜토리얼에서는 각 프레임이 끝난 뒤 다음 프레임을 시작하므로 실행 흐름을 쉽게 따라갈 수 있습니다." -concepts.execution.recording.title: "명령 기록과 제출" +concepts.execution.queues.table.headings.workToRecord: '지원 작업' +concepts.execution.queues.table.transferQueue.workToRecord: '업로드, 다운로드 및 복사 작업. 그리기나 컴퓨트 디스패치는 지원하지 않습니다.' +concepts.execution.queues.title: '큐 선택' +concepts.execution.recording.context: '큐는 완료된 명령 버퍼를 회수해 재사용합니다. 명령을 기록할 때마다 {queueCommandBuffer}로 버퍼를 가져오고, 한 번에 한 스레드에서 기록한 뒤 한 번만 제출합니다. 제출 후에는 큐가 버퍼를 관리하므로 수정하거나 다시 제출하거나 해제하지 않습니다.' +concepts.execution.recording.description: '{queueCommandBuffer}가 반환하는 {commandBuffer}는 이미 기록을 시작한 상태입니다. 작업과 의존 관계를 기록한 후 {submit}을 한 번 호출합니다. 기록이 종료되고 명령이 제출되며, 해당 큐의 완료 지점을 나타내는 {timelineValue}가 반환됩니다.' +concepts.execution.recording.details: '삼각형 튜토리얼은 {commandBuffer}에 프레임을 기록한 뒤 다음과 같이 제출하고 완료를 기다립니다.' +concepts.execution.recording.guidance: '기록은 명령 시퀀스를 구성하고, {submit}은 그 시퀀스의 실행을 예약합니다. 이어서 {wait}를 호출하면 해당 제출이 끝날 때까지 CPU 스레드가 대기합니다. 튜토리얼에서는 각 프레임이 끝난 뒤 다음 프레임을 시작하므로 실행 흐름을 쉽게 따라갈 수 있습니다.' +concepts.execution.recording.title: '명령 기록과 제출' concepts.execution.title: 실행 모델 -concepts.platforms.description: "화면 표시는 애플리케이션이나 UI 컨트롤이 관리합니다. 이 선택에 따라 프레임의 출력 텍스처를 얻고 명령을 기록·제출하며 결과를 표시할 주체가 정해집니다. 이 출력 텍스처를 drawable이라고 합니다." -concepts.platforms.frame.context: "패스 안에서 파이프라인 바인딩과 그리기 명령을 기록하고, 핸들러가 반환하기 전에 패스를 끝냅니다. 명령 제출과 결과 표시는 컨트롤이 담당합니다. 핸들러는 명령 버퍼를 직접 제출하거나 제공받은 두 객체를 해제해서는 안 됩니다. 출력 텍스처의 레이아웃을 바꿨다면 반환 전에 {colorAttachment}로 복원해 컨트롤이 마지막 전환을 수행할 수 있도록 합니다." -concepts.platforms.frame.description: "컨트롤은 {iZenithView}를 구현합니다. 애플리케이션은 {graphicsContext}를 지정하고 {updateRequested}에서 장면을 갱신하며, {renderRequested}에서 전달받은 {renderEventArgs}로 명령을 기록합니다." -concepts.platforms.frame.details: "매 프레임 컨트롤은 출력 텍스처와 명령 버퍼를 가져오고, 텍스처를 {colorAttachment}로 전환한 뒤 업데이트와 렌더링 핸들러를 호출합니다. 이어서 기록된 작업을 제출하고 프레임워크의 표시 방식으로 이미지를 화면에 표시합니다." -concepts.platforms.frame.guidance: "파일에 {usingZenithNET} 구문을 추가합니다. {view}라는 {iZenithView} 인스턴스가 초기화되어 있고 그래픽스 컨텍스트가 할당되어 있다면, 다음 핸들러를 등록해 출력 텍스처를 지울 수 있습니다." -concepts.platforms.frame.notes: "초기 전환은 {undefined}를 사용하므로 이전 이미지의 내용은 버릴 수 있습니다. 매 프레임 이미지 전체를 그리거나 지웁니다. 누적 결과나 캐시한 렌더링 결과는 애플리케이션이 소유한 텍스처에 보관한 뒤 컨트롤의 출력 텍스처에 그립니다." -concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat}은 이 통합들이 사용하는 기본 색상 형식을 제공합니다." -concepts.platforms.frame.title: "UI 컨트롤에서 렌더링" -concepts.platforms.integration.context: "WinForms, WPF, Windows용 WinUI 통합은 Windows에서 실행됩니다. MAUI는 대상 플랫폼의 워크로드를 설치하고, {extensionsCs}에서처럼 {useZenithView}로 컨트롤 핸들러를 등록합니다." -concepts.platforms.integration.description: "이벤트 인터페이스는 공통이지만 표시 방식은 프레임워크마다 다릅니다." -concepts.platforms.integration.details: "각 구현은 GPU 이미지를 UI에 전달하는 방식이 다릅니다. 비트맵 리드백은 표시 전에 픽셀을 CPU 메모리로 복사합니다. 공유 텍스처 상호 운용은 이 CPU 복사를 피하지만 GPU 복사와 동기화는 여전히 필요할 수 있습니다. 통합을 선택할 때는 공통 {renderRequested} 이벤트뿐 아니라 이 표시 경로도 고려합니다." -concepts.platforms.integration.guidance: "NuGet으로 사용하는 UI 프레임워크의 통합 패키지를 추가합니다. Avalonia에는 {avaloniaPackage}를 사용합니다." +concepts.platforms.description: '화면 표시는 애플리케이션이나 UI 컨트롤이 관리합니다. 이 선택에 따라 프레임의 출력 텍스처를 얻고 명령을 기록·제출하며 결과를 표시할 주체가 정해집니다. 이 출력 텍스처를 drawable이라고 합니다.' +concepts.platforms.frame.context: '패스 안에서 파이프라인 바인딩과 그리기 명령을 기록하고, 핸들러가 반환하기 전에 패스를 끝냅니다. 명령 제출과 결과 표시는 컨트롤이 담당합니다. 핸들러는 명령 버퍼를 직접 제출하거나 제공받은 두 객체를 해제해서는 안 됩니다. 출력 텍스처의 레이아웃을 바꿨다면 반환 전에 {colorAttachment}로 복원해 컨트롤이 마지막 전환을 수행할 수 있도록 합니다.' +concepts.platforms.frame.description: '컨트롤은 {iZenithView}를 구현합니다. 애플리케이션은 {graphicsContext}를 지정하고 {updateRequested}에서 장면을 갱신하며, {renderRequested}에서 전달받은 {renderEventArgs}로 명령을 기록합니다.' +concepts.platforms.frame.details: '매 프레임 컨트롤은 출력 텍스처와 명령 버퍼를 가져오고, 텍스처를 {colorAttachment}로 전환한 뒤 업데이트와 렌더링 핸들러를 호출합니다. 이어서 기록된 작업을 제출하고 프레임워크의 표시 방식으로 이미지를 화면에 표시합니다.' +concepts.platforms.frame.guidance: '파일에 {usingZenithNET} 구문을 추가합니다. {view}라는 {iZenithView} 인스턴스가 초기화되어 있고 그래픽스 컨텍스트가 할당되어 있다면, 다음 핸들러를 등록해 출력 텍스처를 지울 수 있습니다.' +concepts.platforms.frame.notes: '초기 전환은 {undefined}를 사용하므로 이전 이미지의 내용은 버릴 수 있습니다. 매 프레임 이미지 전체를 그리거나 지웁니다. 누적 결과나 캐시한 렌더링 결과는 애플리케이션이 소유한 텍스처에 보관한 뒤 컨트롤의 출력 텍스처에 그립니다.' +concepts.platforms.frame.reference: '{zenithViewHelperDrawableFormat}은 이 통합들이 사용하는 기본 색상 형식을 제공합니다.' +concepts.platforms.frame.title: 'UI 컨트롤에서 렌더링' +concepts.platforms.integration.context: 'WinForms, WPF, Windows용 WinUI 통합은 Windows에서 실행됩니다. MAUI는 대상 플랫폼의 워크로드를 설치하고, {extensionsCs}에서처럼 {useZenithView}로 컨트롤 핸들러를 등록합니다.' +concepts.platforms.integration.description: '이벤트 인터페이스는 공통이지만 표시 방식은 프레임워크마다 다릅니다.' +concepts.platforms.integration.details: '각 구현은 GPU 이미지를 UI에 전달하는 방식이 다릅니다. 비트맵 리드백은 표시 전에 픽셀을 CPU 메모리로 복사합니다. 공유 텍스처 상호 운용은 이 CPU 복사를 피하지만 GPU 복사와 동기화는 여전히 필요할 수 있습니다. 통합을 선택할 때는 공통 {renderRequested} 이벤트뿐 아니라 이 표시 경로도 고려합니다.' +concepts.platforms.integration.guidance: 'NuGet으로 사용하는 UI 프레임워크의 통합 패키지를 추가합니다. Avalonia에는 {avaloniaPackage}를 사용합니다.' concepts.platforms.integration.table.avalonia.integration: Avalonia concepts.platforms.integration.table.avalonia.presentation: 텍스처에 렌더링하고 픽셀을 {writeableBitmap}으로 다운로드합니다. {zenithViewCs} 및 {surfaceCs}를 참조하세요. concepts.platforms.integration.table.headings.integration: 통합 -concepts.platforms.integration.table.headings.presentation: "표시 방식" +concepts.platforms.integration.table.headings.presentation: '표시 방식' concepts.platforms.integration.table.maui.integration: .NET MAUI -concepts.platforms.integration.table.maui.presentation: "Android, iOS 및 Mac Catalyst에서는 네이티브 서피스를 사용하고 Windows에서는 공유 텍스처를 이용한 합성 방식을 사용합니다. {link}을 참조하세요." +concepts.platforms.integration.table.maui.presentation: 'Android, iOS 및 Mac Catalyst에서는 네이티브 서피스를 사용하고 Windows에서는 공유 텍스처를 이용한 합성 방식을 사용합니다. {link}을 참조하세요.' concepts.platforms.integration.table.maui.presentation.link: 플랫폼 구현 concepts.platforms.integration.table.uno.integration: Uno 경로 concepts.platforms.integration.table.uno.presentation: 픽셀을 {writeableBitmap}으로 다운로드합니다. {zenithViewUnoCs}를 참조하세요. concepts.platforms.integration.table.winForms.integration: WinForms concepts.platforms.integration.table.winForms.presentation: 컨트롤의 {hWND}에 대한 Zenith.NET 스왑 체인을 생성합니다. {zenithViewCs}를 참조하세요. concepts.platforms.integration.table.winUI.integration: Windows의 WinUI -concepts.platforms.integration.table.winUI.presentation: "가져온 공유 Direct3D 11 텍스처에 렌더링한 다음 {swapChainPanel}에 연결된 합성용 스왑 체인에 복사합니다. {zenithViewWinUICs}를 참조하세요." +concepts.platforms.integration.table.winUI.presentation: '가져온 공유 Direct3D 11 텍스처에 렌더링한 다음 {swapChainPanel}에 연결된 합성용 스왑 체인에 복사합니다. {zenithViewWinUICs}를 참조하세요.' concepts.platforms.integration.table.wpf.integration: WPF concepts.platforms.integration.table.wpf.presentation: 공유 Direct3D 11 텍스처를 가져온 다음 Direct3D 상호 운용성을 통해 {d3DImage}로 표시되는 서피스에 복사합니다. {surfaceCs}를 참조하세요. -concepts.platforms.integration.title: "프레임워크와 표시 방식" -concepts.platforms.lifecycle.context: "호환되는 어태치먼트를 만들 때는 렌더 이벤트가 제공한 출력 텍스처의 {descWidth}, {descHeight}, {descFormat}, {descSampleCount}를 사용합니다. 이 텍스처의 크기가 렌더 타깃의 실제 크기입니다. 컨트롤의 레이아웃 크기나 화면 배율로 추정하지 않습니다." -concepts.platforms.lifecycle.description: "스왑 체인은 프레임버퍼의 픽셀 너비와 높이를 사용합니다. 화면 배율이 적용되면 이 크기는 창의 논리적 크기와 다를 수 있습니다. 너비나 높이가 0인 동안에는 렌더링과 스왑 체인 크기 변경을 미룹니다. {swapChainDrawable}은 매 프레임 가져옵니다. 이 텍스처는 스왑 체인이 소유하며 화면 표시나 크기 변경 후 교체될 수 있습니다." -concepts.platforms.lifecycle.details: "프레임버퍼 크기가 바뀌면 GPU가 이전 이미지의 사용을 마칠 때까지 기다린 뒤 {swapChainResize}를 호출합니다. 네이티브 표시 대상을 교체할 때도 사용이 끝난 뒤 새 서피스 설명과 핸들을 {swapChainRefresh}에 전달합니다. 종료할 때는 네이티브 표시 대상을 파괴하기 전에 스왑 체인을 해제합니다." -concepts.platforms.lifecycle.guidance: "애플리케이션이 소유한 깊이 텍스처나 오프스크린 텍스처가 창 크기를 따른다면, 크기가 바뀔 때 다시 만들고 해당 핸들을 담은 상수도 갱신합니다. 어태치먼트 형식과 샘플 수가 계속 일치하면 파이프라인은 재사용할 수 있습니다. {link}는 크기가 바뀌는 텍스처와 재사용하는 파이프라인을 분리하는 예를 보여 줍니다." +concepts.platforms.integration.title: '프레임워크와 표시 방식' +concepts.platforms.lifecycle.context: '호환되는 어태치먼트를 만들 때는 렌더 이벤트가 제공한 출력 텍스처의 {descWidth}, {descHeight}, {descFormat}, {descSampleCount}를 사용합니다. 이 텍스처의 크기가 렌더 타깃의 실제 크기입니다. 컨트롤의 레이아웃 크기나 화면 배율로 추정하지 않습니다.' +concepts.platforms.lifecycle.description: '스왑 체인은 프레임버퍼의 픽셀 너비와 높이를 사용합니다. 화면 배율이 적용되면 이 크기는 창의 논리적 크기와 다를 수 있습니다. 너비나 높이가 0인 동안에는 렌더링과 스왑 체인 크기 변경을 미룹니다. {swapChainDrawable}은 매 프레임 가져옵니다. 이 텍스처는 스왑 체인이 소유하며 화면 표시나 크기 변경 후 교체될 수 있습니다.' +concepts.platforms.lifecycle.details: '프레임버퍼 크기가 바뀌면 GPU가 이전 이미지의 사용을 마칠 때까지 기다린 뒤 {swapChainResize}를 호출합니다. 네이티브 표시 대상을 교체할 때도 사용이 끝난 뒤 새 서피스 설명과 핸들을 {swapChainRefresh}에 전달합니다. 종료할 때는 네이티브 표시 대상을 파괴하기 전에 스왑 체인을 해제합니다.' +concepts.platforms.lifecycle.guidance: '애플리케이션이 소유한 깊이 텍스처나 오프스크린 텍스처가 창 크기를 따른다면, 크기가 바뀔 때 다시 만들고 해당 핸들을 담은 상수도 갱신합니다. 어태치먼트 형식과 샘플 수가 계속 일치하면 파이프라인은 재사용할 수 있습니다. {link}는 크기가 바뀌는 텍스처와 재사용하는 파이프라인을 분리하는 예를 보여 줍니다.' concepts.platforms.lifecycle.guidance.link: 회전하는 큐브 렌더러 -concepts.platforms.lifecycle.title: "스왑 체인의 크기와 수명" -concepts.platforms.ownership.description: "애플리케이션은 할당한 컨텍스트와 자체 렌더링 리소스를 소유하고, 컨트롤은 화면 표시 리소스를 소유합니다. 뷰의 {graphicsContext}가 바뀌면 스케줄러는 새 컨텍스트에 맞게 컨트롤 리소스를 다시 만듭니다. 애플리케이션의 파이프라인, 버퍼, 텍스처도 새 컨텍스트에서 다시 만들어야 합니다." -concepts.platforms.ownership.details: "렌더링 리소스를 교체하기 전에 뷰의 프레임 처리를 중단하고 해당 리소스를 사용하는 GPU 작업이 끝날 때까지 기다립니다. 그런 다음 이전 리소스나 컨텍스트를 해제합니다. 뷰를 제거할 때도 할당한 컨텍스트를 해제할 책임은 애플리케이션에 있습니다." -concepts.platforms.ownership.guidance: "공통 {frameSchedulerCs}는 뷰의 UI 디스패처를 통해 프레임 핸들러를 실행합니다. 핸들러에서는 장면 데이터 갱신과 명령 기록에 집중합니다. 여기서 CPU 작업이 오래 걸리면 인터페이스의 응답도 지연됩니다." -concepts.platforms.ownership.title: "애플리케이션과 컨트롤의 소유권" -concepts.platforms.surface.description: "{link}은 Silk.NET으로 창을 만들고 이벤트를 처리합니다. Zenith.NET은 네이티브 창 핸들과 크기를 {surface} 설명으로 전달받아 {swapChain}을 만듭니다. 운영체제 창의 관리는 애플리케이션이 계속 맡습니다." -concepts.platforms.surface.description.link: "삼각형 튜토리얼" -concepts.platforms.surface.details: "서피스 핸들은 선택한 백엔드와 일치해야 합니다." -concepts.platforms.surface.guidance: "{appCs}의 예제 호스트는 Windows, macOS, X11을 지원합니다. Linux 창에서 Xlib 핸들을 제공하므로 Wayland 세션에서 실행하려면 XWayland가 필요합니다. 네이티브 Wayland 애플리케이션은 {surfaceWayland}로 디스플레이와 서피스 핸들을 전달합니다." +concepts.platforms.lifecycle.title: '스왑 체인의 크기와 수명' +concepts.platforms.ownership.description: '애플리케이션은 할당한 컨텍스트와 자체 렌더링 리소스를 소유하고, 컨트롤은 화면 표시 리소스를 소유합니다. 뷰의 {graphicsContext}가 바뀌면 스케줄러는 새 컨텍스트에 맞게 컨트롤 리소스를 다시 만듭니다. 애플리케이션의 파이프라인, 버퍼, 텍스처도 새 컨텍스트에서 다시 만들어야 합니다.' +concepts.platforms.ownership.details: '렌더링 리소스를 교체하기 전에 뷰의 프레임 처리를 중단하고 해당 리소스를 사용하는 GPU 작업이 끝날 때까지 기다립니다. 그런 다음 이전 리소스나 컨텍스트를 해제합니다. 뷰를 제거할 때도 할당한 컨텍스트를 해제할 책임은 애플리케이션에 있습니다.' +concepts.platforms.ownership.guidance: '공통 {frameSchedulerCs}는 뷰의 UI 디스패처를 통해 프레임 핸들러를 실행합니다. 핸들러에서는 장면 데이터 갱신과 명령 기록에 집중합니다. 여기서 CPU 작업이 오래 걸리면 인터페이스의 응답도 지연됩니다.' +concepts.platforms.ownership.title: '애플리케이션과 컨트롤의 소유권' +concepts.platforms.surface.description: '{link}은 Silk.NET으로 창을 만들고 이벤트를 처리합니다. Zenith.NET은 네이티브 창 핸들과 크기를 {surface} 설명으로 전달받아 {swapChain}을 만듭니다. 운영체제 창의 관리는 애플리케이션이 계속 맡습니다.' +concepts.platforms.surface.description.link: '삼각형 튜토리얼' +concepts.platforms.surface.details: '서피스 핸들은 선택한 백엔드와 일치해야 합니다.' +concepts.platforms.surface.guidance: '{appCs}의 예제 호스트는 Windows, macOS, X11을 지원합니다. Linux 창에서 Xlib 핸들을 제공하므로 Wayland 세션에서 실행하려면 XWayland가 필요합니다. 네이티브 Wayland 애플리케이션은 {surfaceWayland}로 디스플레이와 서피스 핸들을 전달합니다.' concepts.platforms.surface.table.android.backend: Android의 Vulkan. concepts.platforms.surface.table.apple.backend: Apple 플랫폼의 Metal. -concepts.platforms.surface.table.headings.backend: "백엔드와 플랫폼" +concepts.platforms.surface.table.headings.backend: '백엔드와 플랫폼' concepts.platforms.surface.table.headings.factory: 서피스 팩토리 concepts.platforms.surface.table.headings.handles: 호스트에서 제공하는 핸들 concepts.platforms.surface.table.wayland.backend: 네이티브 Wayland 호스트를 사용하는 Vulkan. concepts.platforms.surface.table.wayland.handles: Wayland 디스플레이 및 서피스 concepts.platforms.surface.table.win32.backend: Windows의 DirectX 12 또는 Vulkan. concepts.platforms.surface.table.xlib.backend: X11 또는 XWayland를 사용하는 Linux의 Vulkan. -concepts.platforms.surface.table.xlib.handles: "X11 디스플레이 및 창" -concepts.platforms.surface.title: "네이티브 표시 서피스" +concepts.platforms.surface.table.xlib.handles: 'X11 디스플레이 및 창' +concepts.platforms.surface.title: '네이티브 표시 서피스' concepts.platforms.title: 플랫폼 통합 -concepts.resources.allocation.context: "힙에 배치한 리소스는 수명 내내 그 힙의 저장 공간에 의존합니다. GPU의 마지막 사용이 끝난 뒤 리소스를 먼저 해제하고 힙을 해제합니다." -concepts.resources.allocation.description: "애플리케이션이 메모리 할당을 직접 관리해야 한다면 {heap}을 사용합니다. 힙은 리소스를 지정한 바이트 오프셋에 배치할 저장 공간을 제공합니다. 오프셋을 선택하고 어느 영역이 사용 중인지 추적하는 일은 애플리케이션이 맡습니다." -concepts.resources.allocation.details: "리소스를 만들 때 사용할 버퍼 또는 텍스처 설명으로 {contextGetSizeAndAlignment}를 호출합니다. 반환된 정렬 값의 배수인 오프셋에 반환된 크기만큼 공간을 확보하되, 힙의 범위를 벗어나거나 아직 사용 중인 다른 할당과 겹치지 않도록 합니다. 텍스처에는 백엔드별 패딩이 포함될 수 있으므로 픽셀 수와 픽셀당 바이트 수만으로 할당 크기를 계산할 수 없습니다." -concepts.resources.allocation.guidance: "힙에 배치하는 버퍼의 상주 특성은 힙과 같아야 합니다. 텍스처를 저장할 때는 GPU 전용 힙을 사용합니다." -concepts.resources.allocation.title: "힙에 리소스 배치" +concepts.resources.allocation.context: '힙에 배치한 리소스는 수명 내내 그 힙의 저장 공간에 의존합니다. GPU의 마지막 사용이 끝난 뒤 리소스를 먼저 해제하고 힙을 해제합니다.' +concepts.resources.allocation.description: '애플리케이션이 메모리 할당을 직접 관리해야 한다면 {heap}을 사용합니다. 힙은 리소스를 지정한 바이트 오프셋에 배치할 저장 공간을 제공합니다. 오프셋을 선택하고 어느 영역이 사용 중인지 추적하는 일은 애플리케이션이 맡습니다.' +concepts.resources.allocation.details: '리소스를 만들 때 사용할 버퍼 또는 텍스처 설명으로 {contextGetSizeAndAlignment}를 호출합니다. 반환된 정렬 값의 배수인 오프셋에 반환된 크기만큼 공간을 확보하되, 힙의 범위를 벗어나거나 아직 사용 중인 다른 할당과 겹치지 않도록 합니다. 텍스처에는 백엔드별 패딩이 포함될 수 있으므로 픽셀 수와 픽셀당 바이트 수만으로 할당 크기를 계산할 수 없습니다.' +concepts.resources.allocation.guidance: '힙에 배치하는 버퍼의 상주 특성은 힙과 같아야 합니다. 텍스처를 저장할 때는 GPU 전용 힙을 사용합니다.' +concepts.resources.allocation.title: '힙에 리소스 배치' concepts.resources.bufferUsages.table.constant.role: 상수 버퍼 바인딩을 통해 읽는 셰이더 매개 변수. -concepts.resources.bufferUsages.table.headings.role: "역할" +concepts.resources.bufferUsages.table.headings.role: '역할' concepts.resources.bufferUsages.table.headings.usage: 용도 -concepts.resources.bufferUsages.table.index.role: "인덱스 그리기에 사용되는 인덱스." -concepts.resources.bufferUsages.table.indirect.role: "간접 그리기 또는 디스패치 명령이 읽는 인수." -concepts.resources.bufferUsages.table.none.role: "버퍼 용도 플래그를 선언하지 않음." -concepts.resources.bufferUsages.table.storageReadOnly.role: "읽기 전용 셰이더 바인딩으로 접근하는 버퍼 데이터." -concepts.resources.bufferUsages.table.storageReadWrite.role: "읽기 및 쓰기 셰이더 바인딩으로 접근하는 버퍼 데이터." -concepts.resources.bufferUsages.table.transferDst.role: "GPU 복사의 대상 저장 공간." -concepts.resources.bufferUsages.table.transferSrc.role: "GPU 복사의 원본 데이터." -concepts.resources.bufferUsages.table.vertex.role: "그리기에 사용하는 정점 속성." +concepts.resources.bufferUsages.table.index.role: '인덱스 그리기에 사용되는 인덱스.' +concepts.resources.bufferUsages.table.indirect.role: '간접 그리기 또는 디스패치 명령이 읽는 인수.' +concepts.resources.bufferUsages.table.none.role: '버퍼 용도 플래그를 선언하지 않음.' +concepts.resources.bufferUsages.table.storageReadOnly.role: '읽기 전용 셰이더 바인딩으로 접근하는 버퍼 데이터.' +concepts.resources.bufferUsages.table.storageReadWrite.role: '읽기 및 쓰기 셰이더 바인딩으로 접근하는 버퍼 데이터.' +concepts.resources.bufferUsages.table.transferDst.role: 'GPU 복사의 대상 저장 공간.' +concepts.resources.bufferUsages.table.transferSrc.role: 'GPU 복사의 원본 데이터.' +concepts.resources.bufferUsages.table.vertex.role: '그리기에 사용하는 정점 속성.' concepts.resources.bufferUsages.title: 버퍼 용도 -concepts.resources.description: "리소스 설명은 애플리케이션이 저장 공간을 어떤 용도로 사용할지 정합니다. 예를 들어 렌더 타깃으로 쓰고, 셰이더에서 샘플링하고, CPU로 다시 복사하는 텍스처에는 세 작업의 용도 플래그가 모두 필요합니다. 메모리 배치는 CPU 접근 방식을 결정하고, 동기화와 수명 관리는 데이터에 접근하거나 저장 공간을 해제할 수 있는 시점을 결정합니다." -concepts.resources.memory.context: "CPU에서 접근할 수 있는 버퍼의 경우 {map}은 데이터를 읽거나 쓸 주소를 제공합니다. 매핑과 {unmap}은 GPU 작업을 기다리지 않습니다. 따라서 GPU가 쓴 결과를 읽으려면 쓰기가 끝날 때까지 기다려야 하고, 같은 바이트를 수정하려면 진행 중인 GPU 접근이 끝날 때까지 기다려야 합니다." -concepts.resources.memory.description: "{bufferDesc}의 {residency} 필드는 할당 영역에 대한 CPU 접근 방식을 지정합니다." -concepts.resources.memory.details: "상주 특성은 CPU와 GPU가 물리 메모리를 공유하는 시스템에서도 CPU 접근 요구 사항을 나타냅니다. 삼각형은 작은 정점 버퍼를 직접 초기화하기 위해 {cpuWriteOnly}를 사용합니다. 더 큰 정적 지오메트리에는 GPU 전용 저장 공간을 만들고 데이터를 업로드하는 방식이 적합할 수 있습니다." -concepts.resources.memory.guidance: "컨텍스트에서 직접 만든 텍스처는 GPU 저장 공간을 사용합니다. 따라서 {textureDesc}에는 상주 특성 필드가 없으며, 애플리케이션은 업로드와 다운로드로 텍스처 데이터를 CPU 메모리와 주고받습니다." -concepts.resources.memory.table.cpuReadOnly.cPUAccess: "읽기 전용" -concepts.resources.memory.table.cpuReadOnly.typicalRole: "GPU가 생성하고 CPU가 읽는 데이터" -concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "쓰기 전용" -concepts.resources.memory.table.cpuWriteOnly.typicalRole: "CPU가 제공하거나 갱신하는 데이터" -concepts.resources.memory.table.gpuOnly.cPUAccess: "없음" -concepts.resources.memory.table.gpuOnly.typicalRole: "정적 지오메트리와 GPU 작업 데이터" -concepts.resources.memory.table.headings.cPUAccess: "의도한 CPU 접근" -concepts.resources.memory.table.headings.residency: "상주 방식" +concepts.resources.description: '리소스 설명은 애플리케이션이 저장 공간을 어떤 용도로 사용할지 정합니다. 예를 들어 렌더 타깃으로 쓰고, 셰이더에서 샘플링하고, CPU로 다시 복사하는 텍스처에는 세 작업의 용도 플래그가 모두 필요합니다. 메모리 배치는 CPU 접근 방식을 결정하고, 동기화와 수명 관리는 데이터에 접근하거나 저장 공간을 해제할 수 있는 시점을 결정합니다.' +concepts.resources.memory.context: 'CPU에서 접근할 수 있는 버퍼의 경우 {map}은 데이터를 읽거나 쓸 주소를 제공합니다. 매핑과 {unmap}은 GPU 작업을 기다리지 않습니다. 따라서 GPU가 쓴 결과를 읽으려면 쓰기가 끝날 때까지 기다려야 하고, 같은 바이트를 수정하려면 진행 중인 GPU 접근이 끝날 때까지 기다려야 합니다.' +concepts.resources.memory.description: '{bufferDesc}의 {residency} 필드는 할당 영역에 대한 CPU 접근 방식을 지정합니다.' +concepts.resources.memory.details: '상주 특성은 CPU와 GPU가 물리 메모리를 공유하는 시스템에서도 CPU 접근 요구 사항을 나타냅니다. 삼각형은 작은 정점 버퍼를 직접 초기화하기 위해 {cpuWriteOnly}를 사용합니다. 더 큰 정적 지오메트리에는 GPU 전용 저장 공간을 만들고 데이터를 업로드하는 방식이 적합할 수 있습니다.' +concepts.resources.memory.guidance: '컨텍스트에서 직접 만든 텍스처는 GPU 저장 공간을 사용합니다. 따라서 {textureDesc}에는 상주 특성 필드가 없으며, 애플리케이션은 업로드와 다운로드로 텍스처 데이터를 CPU 메모리와 주고받습니다.' +concepts.resources.memory.table.cpuReadOnly.cPUAccess: '읽기 전용' +concepts.resources.memory.table.cpuReadOnly.typicalRole: 'GPU가 생성하고 CPU가 읽는 데이터' +concepts.resources.memory.table.cpuWriteOnly.cPUAccess: '쓰기 전용' +concepts.resources.memory.table.cpuWriteOnly.typicalRole: 'CPU가 제공하거나 갱신하는 데이터' +concepts.resources.memory.table.gpuOnly.cPUAccess: '없음' +concepts.resources.memory.table.gpuOnly.typicalRole: '정적 지오메트리와 GPU 작업 데이터' +concepts.resources.memory.table.headings.cPUAccess: '의도한 CPU 접근' +concepts.resources.memory.table.headings.residency: '상주 방식' concepts.resources.memory.table.headings.typicalRole: 일반적인 역할 -concepts.resources.memory.title: "CPU 접근과 메모리 배치" -concepts.resources.textureUsages.description: "전송 플래그는 리소스가 GPU 복사의 원본인지 대상인지를 나타냅니다. CPU가 저장 공간에 직접 접근할 수 있는지는 별도로 메모리 배치를 선택할 때 정합니다." -concepts.resources.textureUsages.details: "용도 플래그는 텍스처가 수행할 수 있는 역할을 선언합니다. 역할을 바꿔 사용할 때는 해당 {link} 요구 사항을 따라야 하며, 선택한 장치가 그 텍스처 형식의 용도를 지원해야 합니다." -concepts.resources.textureUsages.details.link: "레이아웃과 동기화" -concepts.resources.textureUsages.table.colorAttachment.role: "렌더 패스의 색상 어태치먼트." -concepts.resources.textureUsages.table.depthStencilAttachment.role: "렌더 패스의 깊이/스텐실 어태치먼트." -concepts.resources.textureUsages.table.headings.role: "역할" +concepts.resources.memory.title: 'CPU 접근과 메모리 배치' +concepts.resources.textureUsages.description: '전송 플래그는 리소스가 GPU 복사의 원본인지 대상인지를 나타냅니다. CPU가 저장 공간에 직접 접근할 수 있는지는 별도로 메모리 배치를 선택할 때 정합니다.' +concepts.resources.textureUsages.details: '용도 플래그는 텍스처가 수행할 수 있는 역할을 선언합니다. 역할을 바꿔 사용할 때는 해당 {link} 요구 사항을 따라야 하며, 선택한 장치가 그 텍스처 형식의 용도를 지원해야 합니다.' +concepts.resources.textureUsages.details.link: '레이아웃과 동기화' +concepts.resources.textureUsages.table.colorAttachment.role: '렌더 패스의 색상 어태치먼트.' +concepts.resources.textureUsages.table.depthStencilAttachment.role: '렌더 패스의 깊이/스텐실 어태치먼트.' +concepts.resources.textureUsages.table.headings.role: '역할' concepts.resources.textureUsages.table.headings.usage: 용도 -concepts.resources.textureUsages.table.none.role: "텍스처 용도 플래그를 선언하지 않음." -concepts.resources.textureUsages.table.sampled.role: "샘플링 텍스처 바인딩을 통해 읽는 텍스처 데이터." -concepts.resources.textureUsages.table.storage.role: "스토리지 텍스처 바인딩을 통해 셰이더가 읽거나 쓰는 텍스처 데이터." -concepts.resources.textureUsages.table.transferDst.role: "GPU 복사의 대상 이미지 저장 공간." -concepts.resources.textureUsages.table.transferSrc.role: "GPU 복사의 원본 이미지 데이터." +concepts.resources.textureUsages.table.none.role: '텍스처 용도 플래그를 선언하지 않음.' +concepts.resources.textureUsages.table.sampled.role: '샘플링 텍스처 바인딩을 통해 읽는 텍스처 데이터.' +concepts.resources.textureUsages.table.storage.role: '스토리지 텍스처 바인딩을 통해 셰이더가 읽거나 쓰는 텍스처 데이터.' +concepts.resources.textureUsages.table.transferDst.role: 'GPU 복사의 대상 이미지 저장 공간.' +concepts.resources.textureUsages.table.transferSrc.role: 'GPU 복사의 원본 이미지 데이터.' concepts.resources.textureUsages.title: 텍스처 용도 concepts.resources.title: 리소스 관리 -concepts.resources.transfers.context: "다운로드는 먼저 GPU 데이터를 내부 리드백 공간으로 복사합니다. 라이브러리는 완료된 명령 버퍼를 회수할 때 이 데이터를 지정한 CPU 대상으로 복사합니다. 다운로드를 제출해 받은 값에서 {wait}를 호출하면 두 단계가 모두 완료됩니다. 이 호출이 반환할 때까지 대상 메모리를 할당된 상태로 유지하고, 관리형 메모리라면 고정 상태도 유지합니다." -concepts.resources.transfers.description: "업로드는 CPU 데이터를 GPU 리소스로 복사하고, 다운로드는 리소스 데이터를 CPU 메모리로 복사합니다. 버퍼와 텍스처의 메서드는 이 전송을 완료한 뒤 반환합니다." -concepts.resources.transfers.details: "이 메서드들을 호출하기 전에 다른 큐의 충돌하는 접근을 정리해야 합니다. 메서드 내부의 대기는 자체 전송만 대상으로 하며 다른 큐와의 의존성을 설정하지 않습니다. 매핑된 메모리로 직접 복사하는 경로에서는 충돌하는 GPU 접근을 기다리는 일도 전적으로 호출자가 담당합니다." -concepts.resources.transfers.guidance: "전송을 다른 GPU 작업과 함께 제출하려면 {commandBufferUpload} 또는 {commandBufferDownload}로 기록합니다. 업로드 원본과 다운로드 대상은 메모리를 유효하게 유지해야 하는 기간이 서로 다릅니다." -concepts.resources.transfers.item: "업로드를 호출하면 라이브러리가 원본 데이터를 임시 전송 공간인 스테이징 메모리에 복사합니다. 이후 GPU는 이 공간에서 읽으므로 애플리케이션의 원본 포인터는 호출이 반환할 때까지만 필요합니다." -concepts.resources.transfers.notes: "텍스처 전송에서 행 스트라이드는 CPU 데이터의 인접한 행 사이의 바이트 거리이고, 슬라이스 스트라이드는 인접한 깊이 슬라이스 사이의 거리입니다. 이 값으로 CPU에 배치된 데이터와 GPU의 텍스처 저장 공간 사이를 복사할 수 있습니다. GPU 복사 완료와 다운로드 대상에 데이터가 전달되는 시점이 다른 이유는 {link} 문서에서 설명합니다." +concepts.resources.transfers.context: '다운로드는 먼저 GPU 데이터를 내부 리드백 공간으로 복사합니다. 라이브러리는 완료된 명령 버퍼를 회수할 때 이 데이터를 지정한 CPU 대상으로 복사합니다. 다운로드를 제출해 받은 값에서 {wait}를 호출하면 두 단계가 모두 완료됩니다. 이 호출이 반환할 때까지 대상 메모리를 할당된 상태로 유지하고, 관리형 메모리라면 고정 상태도 유지합니다.' +concepts.resources.transfers.description: '업로드는 CPU 데이터를 GPU 리소스로 복사하고, 다운로드는 리소스 데이터를 CPU 메모리로 복사합니다. 버퍼와 텍스처의 메서드는 이 전송을 완료한 뒤 반환합니다.' +concepts.resources.transfers.details: '이 메서드들을 호출하기 전에 다른 큐의 충돌하는 접근을 정리해야 합니다. 메서드 내부의 대기는 자체 전송만 대상으로 하며 다른 큐와의 의존성을 설정하지 않습니다. 매핑된 메모리로 직접 복사하는 경로에서는 충돌하는 GPU 접근을 기다리는 일도 전적으로 호출자가 담당합니다.' +concepts.resources.transfers.guidance: '전송을 다른 GPU 작업과 함께 제출하려면 {commandBufferUpload} 또는 {commandBufferDownload}로 기록합니다. 업로드 원본과 다운로드 대상은 메모리를 유효하게 유지해야 하는 기간이 서로 다릅니다.' +concepts.resources.transfers.item: '업로드를 호출하면 라이브러리가 원본 데이터를 임시 전송 공간인 스테이징 메모리에 복사합니다. 이후 GPU는 이 공간에서 읽으므로 애플리케이션의 원본 포인터는 호출이 반환할 때까지만 필요합니다.' +concepts.resources.transfers.notes: '텍스처 전송에서 행 스트라이드는 CPU 데이터의 인접한 행 사이의 바이트 거리이고, 슬라이스 스트라이드는 인접한 깊이 슬라이스 사이의 거리입니다. 이 값으로 CPU에 배치된 데이터와 GPU의 텍스처 저장 공간 사이를 복사할 수 있습니다. GPU 복사 완료와 다운로드 대상에 데이터가 전달되는 시점이 다른 이유는 {link} 문서에서 설명합니다.' concepts.resources.transfers.notes.link: 동기화 -concepts.resources.transfers.table.bufferDownload.transfer: "{cpuReadOnly}이면 매핑된 메모리에서 직접 복사합니다. 그 외에는 전송 큐에 다운로드를 제출하고 완료를 기다립니다." -concepts.resources.transfers.table.bufferUpload.transfer: "{cpuWriteOnly}이면 매핑된 메모리에 직접 복사합니다. 그 외에는 전송 큐에 업로드를 제출하고 완료를 기다립니다." -concepts.resources.transfers.table.headings.method: "메서드" -concepts.resources.transfers.table.headings.transfer: "전송 동작" -concepts.resources.transfers.table.textureTransfers.method: "{textureUpload} / {textureDownload}" -concepts.resources.transfers.table.textureTransfers.transfer: "복사와 텍스처 전환을 그래픽스 큐에 제출한 뒤 완료를 기다립니다. 선택한 하위 리소스는 요청한 최종 레이아웃으로 남습니다." -concepts.resources.transfers.title: "즉시 전송과 기록된 전송" -concepts.resources.usages.description: "{bufferUsages}와 {textureUsages}는 리소스 용도를 선언하는 플래그 열거형입니다. 각각 {bufferDescUsages}와 {textureDescUsages}에 지정합니다. 여러 용도가 필요하면 {value}로 해당 멤버를 결합합니다." -concepts.resources.usages.title: "리소스 용도" -concepts.resources.views.description: "{bufferView}는 버퍼의 영역과 그 데이터를 해석하는 방식을 기술합니다. {textureView}는 하위 리소스 범위를 선택하고, 호환되는 텍스처 유형과 포맷을 지정합니다. 둘 다 기존 저장 공간을 참조하며, 생성 시 선언한 용도를 따릅니다. 뷰 범위는 접근 대상을 기술하지만 모든 백엔드에서 동일한 셰이더 범위 검사를 보장하지는 않습니다." -concepts.resources.views.details: "리소스 자체의 핸들은 기본 뷰를 제공합니다. 다른 영역이나 호환되는 다른 해석 방식이 필요하면 별도 뷰를 만듭니다. GPU가 사용을 마칠 때까지 뷰와 원본 리소스를 모두 유지해야 합니다. 핸들만으로는 어느 객체의 수명도 유지되지 않습니다. 둘 중 하나를 교체하면 이전 {link}이 들어 있는 상수도 갱신합니다." -concepts.resources.views.details.link: "리소스 핸들" -concepts.resources.views.title: "뷰와 원본 리소스" -concepts.shaders.binding.context: "컴퓨트 예제는 {input}에 {inputTextureSampledHandle}을, {output}에 {outputTextureStorageHandle}을 지정합니다. Slang의 {descriptorHandle} 형식 인수가 각 리소스의 셰이더 접근 방식을 정합니다." -concepts.shaders.binding.description: "{setConstantBuffer}는 현재 파이프라인이 상수를 읽을 버퍼와 시작 바이트 오프셋을 선택합니다. 셰이더가 사용하기 전에 해당 공간에 매개변수를 업로드합니다. 이전 GPU 작업이 같은 바이트를 아직 읽고 있다면 그 작업이 끝난 뒤 데이터를 갱신합니다." -concepts.shaders.binding.details: "명령 버퍼, 컴퓨트 파이프라인, 데이터가 채워진 상수 버퍼, 스레드 그룹 수를 준비한 뒤 다음 순서로 디스패치를 기록합니다. 상수 버퍼 바인딩은 현재 파이프라인에 적용되므로 파이프라인을 먼저 선택합니다." -concepts.shaders.binding.guidance: "여기서 {commandBuffer}는 {computePipeline}을 사용하는 디스패치를 기록합니다. 셰이더 매개변수는 {constantBuffer}에 저장되어 있습니다. 버퍼에는 {bufferUsagesConstant} 용도가 필요하고, 오프셋 0은 버퍼의 시작을 선택합니다. 여러 상수 레코드가 한 버퍼를 공유한다면 각 레코드의 시작 오프셋도 백엔드의 바인딩 정렬을 따라야 합니다. 이는 레코드 내부의 필드 배치와 별개의 조건입니다." -concepts.shaders.binding.notes: "{resourceHandle}은 32비트 필드 두 개를 포함하며 해석은 백엔드에 따라 다릅니다. 이 값은 리소스를 생성한 컨텍스트에서만 유효합니다." -concepts.shaders.binding.reference: "핸들을 얻은 리소스와 뷰는 셰이더의 마지막 접근이 끝날 때까지 유지합니다. 텍스처나 뷰를 교체하면 이전 핸들을 담은 상수를 갱신합니다. 소유권 규칙은 {link}에서 설명합니다." +concepts.resources.transfers.table.bufferDownload.transfer: '{cpuReadOnly}이면 매핑된 메모리에서 직접 복사합니다. 그 외에는 전송 큐에 다운로드를 제출하고 완료를 기다립니다.' +concepts.resources.transfers.table.bufferUpload.transfer: '{cpuWriteOnly}이면 매핑된 메모리에 직접 복사합니다. 그 외에는 전송 큐에 업로드를 제출하고 완료를 기다립니다.' +concepts.resources.transfers.table.headings.method: '메서드' +concepts.resources.transfers.table.headings.transfer: '전송 동작' +concepts.resources.transfers.table.textureTransfers.method: '{textureUpload} / {textureDownload}' +concepts.resources.transfers.table.textureTransfers.transfer: '복사와 텍스처 전환을 그래픽스 큐에 제출한 뒤 완료를 기다립니다. 선택한 하위 리소스는 요청한 최종 레이아웃으로 남습니다.' +concepts.resources.transfers.title: '즉시 전송과 기록된 전송' +concepts.resources.usages.description: '{bufferUsages}와 {textureUsages}는 리소스 용도를 선언하는 플래그 열거형입니다. 각각 {bufferDescUsages}와 {textureDescUsages}에 지정합니다. 여러 용도가 필요하면 {value}로 해당 멤버를 결합합니다.' +concepts.resources.usages.title: '리소스 용도' +concepts.resources.views.description: '{bufferView}는 버퍼의 영역과 그 데이터를 해석하는 방식을 기술합니다. {textureView}는 하위 리소스 범위를 선택하고, 호환되는 텍스처 유형과 포맷을 지정합니다. 둘 다 기존 저장 공간을 참조하며, 생성 시 선언한 용도를 따릅니다. 뷰 범위는 접근 대상을 기술하지만 모든 백엔드에서 동일한 셰이더 범위 검사를 보장하지는 않습니다.' +concepts.resources.views.details: '리소스 자체의 핸들은 기본 뷰를 제공합니다. 다른 영역이나 호환되는 다른 해석 방식이 필요하면 별도 뷰를 만듭니다. GPU가 사용을 마칠 때까지 뷰와 원본 리소스를 모두 유지해야 합니다. 핸들만으로는 어느 객체의 수명도 유지되지 않습니다. 둘 중 하나를 교체하면 이전 {link}이 들어 있는 상수도 갱신합니다.' +concepts.resources.views.details.link: '리소스 핸들' +concepts.resources.views.title: '뷰와 원본 리소스' +concepts.shaders.binding.context: '컴퓨트 예제는 {input}에 {inputTextureSampledHandle}을, {output}에 {outputTextureStorageHandle}을 지정합니다. Slang의 {descriptorHandle} 형식 인수가 각 리소스의 셰이더 접근 방식을 정합니다.' +concepts.shaders.binding.description: '{setConstantBuffer}는 현재 파이프라인이 상수를 읽을 버퍼와 시작 바이트 오프셋을 선택합니다. 셰이더가 사용하기 전에 해당 공간에 매개변수를 업로드합니다. 이전 GPU 작업이 같은 바이트를 아직 읽고 있다면 그 작업이 끝난 뒤 데이터를 갱신합니다.' +concepts.shaders.binding.details: '명령 버퍼, 컴퓨트 파이프라인, 데이터가 채워진 상수 버퍼, 스레드 그룹 수를 준비한 뒤 다음 순서로 디스패치를 기록합니다. 상수 버퍼 바인딩은 현재 파이프라인에 적용되므로 파이프라인을 먼저 선택합니다.' +concepts.shaders.binding.guidance: '여기서 {commandBuffer}는 {computePipeline}을 사용하는 디스패치를 기록합니다. 셰이더 매개변수는 {constantBuffer}에 저장되어 있습니다. 버퍼에는 {bufferUsagesConstant} 용도가 필요하고, 오프셋 0은 버퍼의 시작을 선택합니다. 여러 상수 레코드가 한 버퍼를 공유한다면 각 레코드의 시작 오프셋도 백엔드의 바인딩 정렬을 따라야 합니다. 이는 레코드 내부의 필드 배치와 별개의 조건입니다.' +concepts.shaders.binding.notes: '{resourceHandle}은 32비트 필드 두 개를 포함하며 해석은 백엔드에 따라 다릅니다. 이 값은 리소스를 생성한 컨텍스트에서만 유효합니다.' +concepts.shaders.binding.reference: '핸들을 얻은 리소스와 뷰는 셰이더의 마지막 접근이 끝날 때까지 유지합니다. 텍스처나 뷰를 교체하면 이전 핸들을 담은 상수를 갱신합니다. 소유권 규칙은 {link}에서 설명합니다.' concepts.shaders.binding.reference.link: 리소스 관리 -concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: "셰이더 형식 {t}의 구조화 요소 읽기" -concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: "셰이더 형식 {t}의 구조화 요소 읽기 및 쓰기" +concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: '셰이더 형식 {t}의 구조화 요소 읽기' +concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: '셰이더 형식 {t}의 구조화 요소 읽기 및 쓰기' concepts.shaders.binding.table.headings.access: 의도된 접근 -concepts.shaders.binding.table.headings.cHandle: "C# 핸들" +concepts.shaders.binding.table.headings.cHandle: 'C# 핸들' concepts.shaders.binding.table.headings.slangFieldType: Slang 필드 형식 -concepts.shaders.binding.table.samplerHandle.access: "텍스처 샘플링 상태" -concepts.shaders.binding.table.textureSampledHandle.access: "텍스처 읽기" -concepts.shaders.binding.table.textureStorageHandle.access: "스토리지 텍스처 읽기 및 쓰기" -concepts.shaders.binding.title: "상수 버퍼와 리소스 핸들" -concepts.shaders.compilation.description: "{zenithCompiler}는 지정한 Slang 진입점을 {shaderDesc}로 컴파일합니다. 컨텍스트의 {graphicsApi}에 따라 DirectX 12용 DXIL, Metal 라이브러리, Vulkan용 SPIR-V를 생성합니다." -concepts.shaders.compilation.details: "{context}라는 그래픽스 컨텍스트를 이미 만든 상태에서, 실행 파일 옆에 복사해 둔 삼각형 셰이더를 다음과 같이 컴파일합니다." -concepts.shaders.compilation.guidance: "진입점 이름 {vSMain}은 셰이더 파일의 선언과 일치해야 합니다. 초기화 중에 셰이더를 컴파일하고 파이프라인을 만든 뒤, 렌더링 중에는 파이프라인을 재사용합니다. 파이프라인 생성이 끝나면 셰이더 객체를 해제할 수 있습니다. {link} 튜토리얼에서 이 순서를 확인할 수 있습니다." +concepts.shaders.binding.table.samplerHandle.access: '텍스처 샘플링 상태' +concepts.shaders.binding.table.textureSampledHandle.access: '텍스처 읽기' +concepts.shaders.binding.table.textureStorageHandle.access: '스토리지 텍스처 읽기 및 쓰기' +concepts.shaders.binding.title: '상수 버퍼와 리소스 핸들' +concepts.shaders.compilation.description: '{zenithCompiler}는 지정한 Slang 진입점을 {shaderDesc}로 컴파일합니다. 컨텍스트의 {graphicsApi}에 따라 DirectX 12용 DXIL, Metal 라이브러리, Vulkan용 SPIR-V를 생성합니다.' +concepts.shaders.compilation.details: '{context}라는 그래픽스 컨텍스트를 이미 만든 상태에서, 실행 파일 옆에 복사해 둔 삼각형 셰이더를 다음과 같이 컴파일합니다.' +concepts.shaders.compilation.guidance: '진입점 이름 {vSMain}은 셰이더 파일의 선언과 일치해야 합니다. 초기화 중에 셰이더를 컴파일하고 파이프라인을 만든 뒤, 렌더링 중에는 파이프라인을 재사용합니다. 파이프라인 생성이 끝나면 셰이더 객체를 해제할 수 있습니다. {link} 튜토리얼에서 이 순서를 확인할 수 있습니다.' concepts.shaders.compilation.guidance.link: 첫 번째 삼각형 -concepts.shaders.compilation.title: "셰이더 컴파일" -concepts.shaders.description: "C#과 Slang의 선언은 각 값의 위치와 셰이더의 접근 방식이 일치해야 합니다. 정점 입력 레이아웃은 정점 속성을 기술하고, 셰이더의 버퍼 선언은 매개변수와 배열을 기술하며, 리소스 핸들은 셰이더가 사용할 리소스를 가리킵니다." -concepts.shaders.dispatch.description: "{dispatch}는 실행할 스레드 그룹 수를 지정합니다. 컴퓨트 예제는 {numthreads}를 선언하므로 한 그룹은 16 × 16개 스레드로 구성됩니다. 이미지 전체를 처리하려면 너비와 높이를 각각 16으로 나누고 올림합니다. 예를 들어 17 × 19 이미지는 2 × 2개 그룹이 필요합니다. 셰이더는 각 스레드의 좌표를 확인하고 이미지 범위 밖이면 처리를 건너뜁니다." -concepts.shaders.dispatch.details: "선언한 그룹 크기는 {shaderDescThreadGroupSize}에서 확인할 수 있으며, 이 값으로 {dispatch}에 전달할 그룹 수를 계산합니다. 전체 계산은 {computeShaderRendererCs}에 있습니다. 디스패치 이후 결과 이미지에 접근할 때는 {link} 문서의 요구 사항을 따릅니다." +concepts.shaders.compilation.title: '셰이더 컴파일' +concepts.shaders.description: 'C#과 Slang의 선언은 각 값의 위치와 셰이더의 접근 방식이 일치해야 합니다. 정점 입력 레이아웃은 정점 속성을 기술하고, 셰이더의 버퍼 선언은 매개변수와 배열을 기술하며, 리소스 핸들은 셰이더가 사용할 리소스를 가리킵니다.' +concepts.shaders.dispatch.description: '{dispatch}는 실행할 스레드 그룹 수를 지정합니다. 컴퓨트 예제는 {numthreads}를 선언하므로 한 그룹은 16 × 16개 스레드로 구성됩니다. 이미지 전체를 처리하려면 너비와 높이를 각각 16으로 나누고 올림합니다. 예를 들어 17 × 19 이미지는 2 × 2개 그룹이 필요합니다. 셰이더는 각 스레드의 좌표를 확인하고 이미지 범위 밖이면 처리를 건너뜁니다.' +concepts.shaders.dispatch.details: '선언한 그룹 크기는 {shaderDescThreadGroupSize}에서 확인할 수 있으며, 이 값으로 {dispatch}에 전달할 그룹 수를 계산합니다. 전체 계산은 {computeShaderRendererCs}에 있습니다. 디스패치 이후 결과 이미지에 접근할 때는 {link} 문서의 요구 사항을 따릅니다.' concepts.shaders.dispatch.details.link: 동기화 -concepts.shaders.dispatch.title: "스레드 그룹" -concepts.shaders.layout.context: "{link}는 이미지 크기와 텍스처 핸들 두 개로 이 구성을 보여 줍니다. 명시적 오프셋으로 각 필드의 시작 위치를 지정합니다. 다음 선언에는 {systemRuntimeInteropServices}와 {zenithNET} 네임스페이스를 사용합니다." -concepts.shaders.layout.context.link: "컴퓨트 예제의 C# 상수" -concepts.shaders.layout.description: "정점 입력에서 {inputLayout}은 각 속성의 형식, 오프셋, 시맨틱과 정점 간 스트라이드를 기술합니다. 삼각형은 {float3} 위치 뒤에 {float4} 색상을 배치합니다. 색상은 바이트 오프셋 12에서 시작하고 정점 하나는 28바이트를 차지합니다. {inputLayoutAdd}는 요소 형식으로 이 조밀한 배치를 계산합니다. C# 구조체에 패딩이 있다면 이를 반영한 오프셋과 스트라이드를 지정해야 합니다." -concepts.shaders.layout.details: "상수 버퍼에는 셰이더 매개변수를, 구조화 버퍼에는 형식이 지정된 요소의 배열을 저장합니다. 이들의 배치는 {inputLayout}이 아니라 Slang 선언을 따릅니다. C#의 필드 오프셋, 요소 크기, 패딩을 컴파일된 셰이더 레이아웃에 맞춥니다. 관리되지 않는 C# 형식은 바이트로 복사할 수 있지만, 그 메모리 배치가 셰이더의 배치와 반드시 일치하는 것은 아닙니다. 정점에서 촘촘히 배치한 {float3}도 셰이더 버퍼에서는 다른 정렬이 필요할 수 있습니다." -concepts.shaders.layout.guidance: "셰이더 매개변수에는 일반 값뿐 아니라 리소스 핸들도 포함할 수 있습니다. 핸들은 이미 존재하는 저장 공간을 가리키므로 상수 버퍼에 핸들을 복사해도 리소스의 내용까지 복사되지는 않습니다." -concepts.shaders.layout.notes: "{computeShaderSlang}의 대응 선언은 다음과 같습니다." -concepts.shaders.layout.reference: "두 크기 값이 처음 8바이트를 차지하고, 그 뒤에 각각 8바이트인 핸들 두 개가 이어집니다. C# 예제는 전체 레코드에 256바이트를 확보합니다. 다른 레코드의 크기는 그 필드와 레이아웃 및 정렬 요구 사항에 맞춰 정합니다." -concepts.shaders.layout.title: "데이터 배치" -concepts.shaders.matrices.description: "컴파일러는 각 행을 연속으로 저장하는 행 우선 행렬 배치를 사용합니다. {link}에서는 {matrix4x4} 세 개를 오프셋 0, 64, 128에 저장합니다. 해당 {detail}는 {mulVectorMatrix}를 모델, 뷰, 투영 순으로 적용합니다." +concepts.shaders.dispatch.title: '스레드 그룹' +concepts.shaders.layout.context: '{link}는 이미지 크기와 텍스처 핸들 두 개로 이 구성을 보여 줍니다. 명시적 오프셋으로 각 필드의 시작 위치를 지정합니다. 다음 선언에는 {systemRuntimeInteropServices}와 {zenithNET} 네임스페이스를 사용합니다.' +concepts.shaders.layout.context.link: '컴퓨트 예제의 C# 상수' +concepts.shaders.layout.description: '정점 입력에서 {inputLayout}은 각 속성의 형식, 오프셋, 시맨틱과 정점 간 스트라이드를 기술합니다. 삼각형은 {float3} 위치 뒤에 {float4} 색상을 배치합니다. 색상은 바이트 오프셋 12에서 시작하고 정점 하나는 28바이트를 차지합니다. {inputLayoutAdd}는 요소 형식으로 이 조밀한 배치를 계산합니다. C# 구조체에 패딩이 있다면 이를 반영한 오프셋과 스트라이드를 지정해야 합니다.' +concepts.shaders.layout.details: '상수 버퍼에는 셰이더 매개변수를, 구조화 버퍼에는 형식이 지정된 요소의 배열을 저장합니다. 이들의 배치는 {inputLayout}이 아니라 Slang 선언을 따릅니다. C#의 필드 오프셋, 요소 크기, 패딩을 컴파일된 셰이더 레이아웃에 맞춥니다. 관리되지 않는 C# 형식은 바이트로 복사할 수 있지만, 그 메모리 배치가 셰이더의 배치와 반드시 일치하는 것은 아닙니다. 정점에서 촘촘히 배치한 {float3}도 셰이더 버퍼에서는 다른 정렬이 필요할 수 있습니다.' +concepts.shaders.layout.guidance: '셰이더 매개변수에는 일반 값뿐 아니라 리소스 핸들도 포함할 수 있습니다. 핸들은 이미 존재하는 저장 공간을 가리키므로 상수 버퍼에 핸들을 복사해도 리소스의 내용까지 복사되지는 않습니다.' +concepts.shaders.layout.notes: '{computeShaderSlang}의 대응 선언은 다음과 같습니다.' +concepts.shaders.layout.reference: '두 크기 값이 처음 8바이트를 차지하고, 그 뒤에 각각 8바이트인 핸들 두 개가 이어집니다. C# 예제는 전체 레코드에 256바이트를 확보합니다. 다른 레코드의 크기는 그 필드와 레이아웃 및 정렬 요구 사항에 맞춰 정합니다.' +concepts.shaders.layout.title: '데이터 배치' +concepts.shaders.matrices.description: '컴파일러는 각 행을 연속으로 저장하는 행 우선 행렬 배치를 사용합니다. {link}에서는 {matrix4x4} 세 개를 오프셋 0, 64, 128에 저장합니다. 해당 {detail}는 {mulVectorMatrix}를 모델, 뷰, 투영 순으로 적용합니다.' concepts.shaders.matrices.description.detail: 셰이더 concepts.shaders.matrices.description.link: 회전하는 큐브 렌더러 -concepts.shaders.matrices.details: "저장 순서는 메모리의 행렬 요소 배치를, 곱셈 순서는 변환을 정합니다. C#과 Slang에서 서로 맞는 규약을 사용해야 합니다." -concepts.shaders.matrices.title: "행렬 규약" +concepts.shaders.matrices.details: '저장 순서는 메모리의 행렬 요소 배치를, 곱셈 순서는 변환을 정합니다. C#과 Slang에서 서로 맞는 규약을 사용해야 합니다.' +concepts.shaders.matrices.title: '행렬 규약' concepts.shaders.title: 셰이더 데이터 및 바인딩 -concepts.synchronization.backends.description: "DirectX 12와 Vulkan은 텍스처 전환을 레이아웃 및 접근 변경 명령으로 기록합니다. Metal에서는 Zenith.NET의 {transition} 구현이 이에 해당하는 GPU 작업을 수행하지 않습니다. 대신 Metal 백엔드는 명령을 렌더 인코더와 컴퓨트 인코더로 묶고 인코더가 끝날 때 가시성 배리어를 삽입합니다. 연속된 컴퓨트 디스패치처럼 같은 인코더 안에서 의존하는 작업에는 {barrier}를 명시적으로 호출합니다." -concepts.synchronization.backends.details: "{link}에서는 그래픽스 렌더 패스를 시작하면서 컴퓨트 인코더를 끝내므로 그래픽스 작업이 컴퓨트 결과를 볼 수 있습니다. 연속된 두 컴퓨트 디스패치는 같은 인코더에 남아 있으므로 중간에 텍스처 전환을 기록하더라도 의존성을 위한 배리어가 필요합니다. 여러 백엔드에서 사용할 명령 시퀀스는 이처럼 텍스처 레이아웃과 접근 의존성을 함께 고려해야 합니다." -concepts.synchronization.backends.details.link: "컴퓨트 예제" -concepts.synchronization.backends.title: "백엔드별 동작" -concepts.synchronization.barriers.context: "관련 접근을 포함하고 큐에서 지원하는 단계를 선택합니다. {barrierStagesAll}은 지원되는 모든 단계를 포함합니다. 의존성이 일부 단계에만 관련된다면 해당 단계만 선택합니다." -concepts.synchronization.barriers.description: "같은 명령 버퍼에 두 컴퓨트 디스패치를 기록한다고 가정합니다. 첫 번째는 시뮬레이션 데이터를 쓰고 두 번째는 이를 읽습니다. 두 번째가 완료된 쓰기를 볼 수 있도록 디스패치 사이에 배리어를 둡니다. 스토리지 버퍼라면 텍스처 레이아웃을 전환하지 않고 다음과 같이 접근 순서를 정할 수 있습니다." -concepts.synchronization.barriers.details: "첫 번째 인수는 데이터를 만든 단계를, 두 번째는 데이터를 사용할 단계를 지정합니다. 두 인수는 디스패치 사이에 필요한 실행 순서와 메모리 가시성을 기술합니다." -concepts.synchronization.barriers.guidance: "{link}은 시뮬레이션 단계 사이에 이 패턴을 적용합니다. 각 배리어는 데이터를 만드는 디스패치 뒤, 이를 사용하는 디스패치 앞에 놓입니다." +concepts.synchronization.backends.description: 'DirectX 12와 Vulkan은 텍스처 전환을 레이아웃 및 접근 변경 명령으로 기록합니다. Metal에서는 Zenith.NET의 {transition} 구현이 이에 해당하는 GPU 작업을 수행하지 않습니다. 대신 Metal 백엔드는 명령을 렌더 인코더와 컴퓨트 인코더로 묶고 인코더가 끝날 때 가시성 배리어를 삽입합니다. 연속된 컴퓨트 디스패치처럼 같은 인코더 안에서 의존하는 작업에는 {barrier}를 명시적으로 호출합니다.' +concepts.synchronization.backends.details: '{link}에서는 그래픽스 렌더 패스를 시작하면서 컴퓨트 인코더를 끝내므로 그래픽스 작업이 컴퓨트 결과를 볼 수 있습니다. 연속된 두 컴퓨트 디스패치는 같은 인코더에 남아 있으므로 중간에 텍스처 전환을 기록하더라도 의존성을 위한 배리어가 필요합니다. 여러 백엔드에서 사용할 명령 시퀀스는 이처럼 텍스처 레이아웃과 접근 의존성을 함께 고려해야 합니다.' +concepts.synchronization.backends.details.link: '컴퓨트 예제' +concepts.synchronization.backends.title: '백엔드별 동작' +concepts.synchronization.barriers.context: '관련 접근을 포함하고 큐에서 지원하는 단계를 선택합니다. {barrierStagesAll}은 지원되는 모든 단계를 포함합니다. 의존성이 일부 단계에만 관련된다면 해당 단계만 선택합니다.' +concepts.synchronization.barriers.description: '같은 명령 버퍼에 두 컴퓨트 디스패치를 기록한다고 가정합니다. 첫 번째는 시뮬레이션 데이터를 쓰고 두 번째는 이를 읽습니다. 두 번째가 완료된 쓰기를 볼 수 있도록 디스패치 사이에 배리어를 둡니다. 스토리지 버퍼라면 텍스처 레이아웃을 전환하지 않고 다음과 같이 접근 순서를 정할 수 있습니다.' +concepts.synchronization.barriers.details: '첫 번째 인수는 데이터를 만든 단계를, 두 번째는 데이터를 사용할 단계를 지정합니다. 두 인수는 디스패치 사이에 필요한 실행 순서와 메모리 가시성을 기술합니다.' +concepts.synchronization.barriers.guidance: '{link}은 시뮬레이션 단계 사이에 이 패턴을 적용합니다. 각 배리어는 데이터를 만드는 디스패치 뒤, 이를 사용하는 디스패치 앞에 놓입니다.' concepts.synchronization.barriers.guidance.link: FluidTank 시뮬레이션 -concepts.synchronization.barriers.title: "파이프라인 배리어" -concepts.synchronization.dependencies.description: "각 리소스에서 같은 데이터를 다루는 접근을 확인합니다. 어느 한쪽이라도 쓰기라면 필요한 순서를 지켜야 합니다. 읽기끼리는 충돌하지 않지만 텍스처 레이아웃과 프레젠테이션 요구 사항은 여전히 적용됩니다. CPU가 데이터를 갱신하거나 리소스를 해제할 때도 GPU가 해당 저장 공간을 다 쓸 때까지 기다려야 합니다." -concepts.synchronization.dependencies.details: "작업이 실행되는 위치에 따라 적절한 수단을 선택합니다." -concepts.synchronization.dependencies.guidance: "한 작업에 여러 동기화 수단이 필요할 수 있습니다. 예를 들어 다른 큐에서 만든 텍스처를 사용하려면 제출 간 의존성과 다음 용도에 맞는 레이아웃이 모두 필요합니다. CPU가 직접 데이터에 접근하거나 메모리를 해제해야 하는 경우가 아니라면 이 두 작업 때문에 CPU를 대기시킬 필요는 없습니다." +concepts.synchronization.barriers.title: '파이프라인 배리어' +concepts.synchronization.dependencies.description: '각 리소스에서 같은 데이터를 다루는 접근을 확인합니다. 어느 한쪽이라도 쓰기라면 필요한 순서를 지켜야 합니다. 읽기끼리는 충돌하지 않지만 텍스처 레이아웃과 프레젠테이션 요구 사항은 여전히 적용됩니다. CPU가 데이터를 갱신하거나 리소스를 해제할 때도 GPU가 해당 저장 공간을 다 쓸 때까지 기다려야 합니다.' +concepts.synchronization.dependencies.details: '작업이 실행되는 위치에 따라 적절한 수단을 선택합니다.' +concepts.synchronization.dependencies.guidance: '한 작업에 여러 동기화 수단이 필요할 수 있습니다. 예를 들어 다른 큐에서 만든 텍스처를 사용하려면 제출 간 의존성과 다음 용도에 맞는 레이아웃이 모두 필요합니다. CPU가 직접 데이터에 접근하거나 메모리를 해제해야 하는 경우가 아니라면 이 두 작업 때문에 CPU를 대기시킬 필요는 없습니다.' concepts.synchronization.dependencies.table.cpuAccess.mechanism: 해당 완료 값에 대해 {wait}를 호출합니다. -concepts.synchronization.dependencies.table.cpuAccess.situation: "CPU 접근이나 리소스 해제에 GPU 완료가 필요" -concepts.synchronization.dependencies.table.crossQueue.mechanism: "생산자의 {timelineValue}를 소비자의 {submit}에 전달합니다." -concepts.synchronization.dependencies.table.crossQueue.situation: "한 큐에서 다른 큐가 만든 데이터를 사용" +concepts.synchronization.dependencies.table.cpuAccess.situation: 'CPU 접근이나 리소스 해제에 GPU 완료가 필요' +concepts.synchronization.dependencies.table.crossQueue.mechanism: '생산자의 {timelineValue}를 소비자의 {submit}에 전달합니다.' +concepts.synchronization.dependencies.table.crossQueue.situation: '한 큐에서 다른 큐가 만든 데이터를 사용' concepts.synchronization.dependencies.table.headings.mechanism: 메커니즘 concepts.synchronization.dependencies.table.headings.situation: 상황 -concepts.synchronization.dependencies.table.layoutChange.mechanism: "이전·다음 레이아웃을 지정한 {commandBufferTransition}." +concepts.synchronization.dependencies.table.layoutChange.mechanism: '이전·다음 레이아웃을 지정한 {commandBufferTransition}.' concepts.synchronization.dependencies.table.layoutChange.situation: 텍스처 하위 리소스 사용 방식 변경 -concepts.synchronization.dependencies.table.pipelineStages.mechanism: "생성 단계와 소비 단계를 지정한 {commandBufferBarrier}." +concepts.synchronization.dependencies.table.pipelineStages.mechanism: '생성 단계와 소비 단계를 지정한 {commandBufferBarrier}.' concepts.synchronization.dependencies.table.pipelineStages.situation: 명령 스트림의 종속 GPU 단계 -concepts.synchronization.dependencies.title: "접근 의존 관계" -concepts.synchronization.description: "동기화는 공유 데이터에 접근하는 순서를 정하고, 뒤의 작업이 필요한 결과를 볼 수 있게 합니다. 쓰기에서 읽기로 이어지는 의존성에서 쓰는 작업을 생산자, 읽는 작업을 소비자라고 합니다. 배리어와 텍스처 전환은 GPU 접근을 조율하며, 타임라인은 제출 간 의존성을 연결하고 CPU가 GPU 완료를 기다릴 수 있게 합니다." -concepts.synchronization.layouts.context: "새 이미지나 전체를 지울 어태치먼트처럼 기존 내용을 버려도 되는 경우 이전 레이아웃에 {undefined}를 사용합니다. 로드, 샘플링, 누적에 기존 내용이 필요하다면 직전 접근의 레이아웃을 지정합니다." -concepts.synchronization.layouts.description: "용도 플래그는 텍스처에 허용된 역할을 선언합니다. {textureLayout}은 밉 레벨과 배열 레이어로 식별한 하위 리소스를 명령 시퀀스의 특정 지점에서 어떻게 접근하는지 나타냅니다. 접근 방식이 바뀌면 전환을 기록합니다. 예를 들어 컴퓨트 예제는 출력 텍스처를 {storage} 레이아웃에서 쓴 뒤 그래픽스 패스에서 샘플링할 수 있도록 준비합니다." -concepts.synchronization.layouts.details: "여기서는 {outputTexture}를 {sampledStorage} 용도로 만들었고 선택한 하위 리소스는 {storage} 상태입니다. {default}는 mip 레벨 0과 배열 레이어 0을 선택합니다. 다른 레벨이나 레이어에는 영향을 주지 않습니다." -concepts.synchronization.layouts.guidance: "{transition}에는 하위 리소스의 직전 사용 레이아웃을 전달합니다. 애플리케이션은 명령을 기록하고 렌더링 단계 사이에 텍스처를 전달하면서 이 상태를 추적합니다." -concepts.synchronization.layouts.title: "텍스처 레이아웃" -concepts.synchronization.readback.description: "{isCompleted}는 GPU 완료 여부를 알려 줍니다. 기록된 다운로드에는 내부 리드백 공간의 결과를 애플리케이션의 대상 메모리로 복사하는 단계가 하나 더 있습니다." -concepts.synchronization.readback.details: "{commandBufferDownload}는 내부 리드백 공간으로의 GPU 복사를 기록합니다. 제출이 끝나면 라이브러리는 완료된 명령 버퍼를 회수하면서 CPU 복사를 수행합니다. 다운로드를 제출해 받은 값에서 {wait}를 호출하면 GPU 완료를 기다리고 해당 큐의 완료된 버퍼도 처리하므로 두 단계가 모두 끝납니다. 호출이 반환할 때까지 대상 메모리의 할당을 유지하고, 관리형 메모리라면 고정 상태도 유지합니다." -concepts.synchronization.readback.guidance: "{isCompleted}만 조회해서는 마지막 CPU 복사가 수행되지 않습니다. 다른 큐를 기다리는 것 역시 다운로드 큐의 완료된 버퍼를 회수하지 않습니다. 업로드와 다운로드가 직접 메모리 접근이나 스테이징 공간을 사용하는 조건은 {link} 문서에서 설명합니다." +concepts.synchronization.dependencies.title: '접근 의존 관계' +concepts.synchronization.description: '동기화는 공유 데이터에 접근하는 순서를 정하고, 뒤의 작업이 필요한 결과를 볼 수 있게 합니다. 쓰기에서 읽기로 이어지는 의존성에서 쓰는 작업을 생산자, 읽는 작업을 소비자라고 합니다. 배리어와 텍스처 전환은 GPU 접근을 조율하며, 타임라인은 제출 간 의존성을 연결하고 CPU가 GPU 완료를 기다릴 수 있게 합니다.' +concepts.synchronization.layouts.context: '새 이미지나 전체를 지울 어태치먼트처럼 기존 내용을 버려도 되는 경우 이전 레이아웃에 {undefined}를 사용합니다. 로드, 샘플링, 누적에 기존 내용이 필요하다면 직전 접근의 레이아웃을 지정합니다.' +concepts.synchronization.layouts.description: '용도 플래그는 텍스처에 허용된 역할을 선언합니다. {textureLayout}은 밉 레벨과 배열 레이어로 식별한 하위 리소스를 명령 시퀀스의 특정 지점에서 어떻게 접근하는지 나타냅니다. 접근 방식이 바뀌면 전환을 기록합니다. 예를 들어 컴퓨트 예제는 출력 텍스처를 {storage} 레이아웃에서 쓴 뒤 그래픽스 패스에서 샘플링할 수 있도록 준비합니다.' +concepts.synchronization.layouts.details: '여기서는 {outputTexture}를 {sampledStorage} 용도로 만들었고 선택한 하위 리소스는 {storage} 상태입니다. {default}는 mip 레벨 0과 배열 레이어 0을 선택합니다. 다른 레벨이나 레이어에는 영향을 주지 않습니다.' +concepts.synchronization.layouts.guidance: '{transition}에는 하위 리소스의 직전 사용 레이아웃을 전달합니다. 애플리케이션은 명령을 기록하고 렌더링 단계 사이에 텍스처를 전달하면서 이 상태를 추적합니다.' +concepts.synchronization.layouts.title: '텍스처 레이아웃' +concepts.synchronization.readback.description: '{isCompleted}는 GPU 완료 여부를 알려 줍니다. 기록된 다운로드에는 내부 리드백 공간의 결과를 애플리케이션의 대상 메모리로 복사하는 단계가 하나 더 있습니다.' +concepts.synchronization.readback.details: '{commandBufferDownload}는 내부 리드백 공간으로의 GPU 복사를 기록합니다. 제출이 끝나면 라이브러리는 완료된 명령 버퍼를 회수하면서 CPU 복사를 수행합니다. 다운로드를 제출해 받은 값에서 {wait}를 호출하면 GPU 완료를 기다리고 해당 큐의 완료된 버퍼도 처리하므로 두 단계가 모두 끝납니다. 호출이 반환할 때까지 대상 메모리의 할당을 유지하고, 관리형 메모리라면 고정 상태도 유지합니다.' +concepts.synchronization.readback.guidance: '{isCompleted}만 조회해서는 마지막 CPU 복사가 수행되지 않습니다. 다른 큐를 기다리는 것 역시 다운로드 큐의 완료된 버퍼를 회수하지 않습니다. 업로드와 다운로드가 직접 메모리 접근이나 스테이징 공간을 사용하는 조건은 {link} 문서에서 설명합니다.' concepts.synchronization.readback.guidance.link: 리소스 관리 -concepts.synchronization.readback.title: "리드백 완료" -concepts.synchronization.reuse.description: "삼각형은 각 프레임이 끝난 뒤 데이터를 재사용합니다. 프레임을 겹쳐 실행하려면 진행 중인 프레임마다 별도의 수정 가능한 저장 공간을 두고 언제 다시 사용할 수 있는지 추적합니다. 데이터를 변경하기 전에는 해당 바이트에 아직 접근하는 GPU 작업을 기다리고, 리소스를 해제하기 전에는 그 리소스의 모든 사용이 끝날 때까지 기다립니다." -concepts.synchronization.reuse.details: "크기 변경과 종료에도 같은 원칙이 적용됩니다. 새 사용을 막고 기존 사용이 끝날 때까지 기다린 뒤 리소스를 교체하거나 해제합니다. {swapChainResize}를 호출하거나 리소스 또는 컨텍스트를 해제하기 전에 이 순서를 지켜야 합니다. 삼각형은 매 프레임 기다리므로 콜백 호출 사이에서 크기를 바꿀 수 있습니다." -concepts.synchronization.reuse.guidance: "{swapChainPresent}는 이미지를 표시한 뒤 그래픽스 큐에 신호를 보내고 완료를 기다립니다. 따라서 명시적인 제출 대기를 제거해도 삼각형은 화면 표시 단계에서 여전히 기다립니다. 다른 큐에 독립적으로 제출한 작업은 별도로 완료를 추적해야 합니다." -concepts.synchronization.reuse.title: "리소스 재사용" -concepts.synchronization.timelines.context: "소비자가 끝난 뒤 CPU에서 결과를 읽거나 공유 데이터를 덮어쓰거나 리소스를 해제하려면 해당 제출을 기다립니다." -concepts.synchronization.timelines.description: "타임라인은 증가하는 값으로 큐의 완료를 나타냅니다. {submit}은 타임라인과 제출 값을 담은 {timelineValue}를 반환합니다. 서로 다른 타임라인의 숫자 {value}를 직접 비교할 수는 없습니다." -concepts.synchronization.timelines.details: "같은 컨텍스트의 두 큐에서 기록한 {producer}와 {consumer}가 있고, 소비자가 생산자가 쓴 데이터를 사용한다고 하겠습니다. 다음 의존 관계로 제출합니다." -concepts.synchronization.timelines.guidance: "소비자 큐는 전달받은 완료 값에 도달할 때까지 기다린 뒤 명령을 실행합니다. CPU는 {producedWait}를 호출하지 않고 계속 진행할 수 있습니다. {consumed}가 완료될 때까지 공유 리소스를 유지하고, 소비자의 접근에 필요한 텍스처 전환을 기록합니다." -concepts.synchronization.timelines.notes: "{queueTimelineSignal}이 반환한 값도 {wait}로 기다리거나 다른 큐의 의존성에 사용할 수 있습니다. {signal}은 이미 제출된 작업 뒤에 완료 지점을 넣으며, GPU는 그 작업을 끝낸 뒤 해당 지점에 도달합니다." -concepts.synchronization.timelines.title: "타임라인과 큐 간 의존 관계" +concepts.synchronization.readback.title: '리드백 완료' +concepts.synchronization.reuse.description: '삼각형은 각 프레임이 끝난 뒤 데이터를 재사용합니다. 프레임을 겹쳐 실행하려면 진행 중인 프레임마다 별도의 수정 가능한 저장 공간을 두고 언제 다시 사용할 수 있는지 추적합니다. 데이터를 변경하기 전에는 해당 바이트에 아직 접근하는 GPU 작업을 기다리고, 리소스를 해제하기 전에는 그 리소스의 모든 사용이 끝날 때까지 기다립니다.' +concepts.synchronization.reuse.details: '크기 변경과 종료에도 같은 원칙이 적용됩니다. 새 사용을 막고 기존 사용이 끝날 때까지 기다린 뒤 리소스를 교체하거나 해제합니다. {swapChainResize}를 호출하거나 리소스 또는 컨텍스트를 해제하기 전에 이 순서를 지켜야 합니다. 삼각형은 매 프레임 기다리므로 콜백 호출 사이에서 크기를 바꿀 수 있습니다.' +concepts.synchronization.reuse.guidance: '{swapChainPresent}는 이미지를 표시한 뒤 그래픽스 큐에 신호를 보내고 완료를 기다립니다. 따라서 명시적인 제출 대기를 제거해도 삼각형은 화면 표시 단계에서 여전히 기다립니다. 다른 큐에 독립적으로 제출한 작업은 별도로 완료를 추적해야 합니다.' +concepts.synchronization.reuse.title: '리소스 재사용' +concepts.synchronization.timelines.context: '소비자가 끝난 뒤 CPU에서 결과를 읽거나 공유 데이터를 덮어쓰거나 리소스를 해제하려면 해당 제출을 기다립니다.' +concepts.synchronization.timelines.description: '타임라인은 증가하는 값으로 큐의 완료를 나타냅니다. {submit}은 타임라인과 제출 값을 담은 {timelineValue}를 반환합니다. 서로 다른 타임라인의 숫자 {value}를 직접 비교할 수는 없습니다.' +concepts.synchronization.timelines.details: '같은 컨텍스트의 두 큐에서 기록한 {producer}와 {consumer}가 있고, 소비자가 생산자가 쓴 데이터를 사용한다고 하겠습니다. 다음 의존 관계로 제출합니다.' +concepts.synchronization.timelines.guidance: '소비자 큐는 전달받은 완료 값에 도달할 때까지 기다린 뒤 명령을 실행합니다. CPU는 {producedWait}를 호출하지 않고 계속 진행할 수 있습니다. {consumed}가 완료될 때까지 공유 리소스를 유지하고, 소비자의 접근에 필요한 텍스처 전환을 기록합니다.' +concepts.synchronization.timelines.notes: '{queueTimelineSignal}이 반환한 값도 {wait}로 기다리거나 다른 큐의 의존성에 사용할 수 있습니다. {signal}은 이미 제출된 작업 뒤에 완료 지점을 넣으며, GPU는 그 작업을 끝낸 뒤 해당 지점에 도달합니다.' +concepts.synchronization.timelines.title: '타임라인과 큐 간 의존 관계' concepts.synchronization.title: 동기화 home.actions.reference: API 탐색 home.actions.tutorial: 삼각형으로 시작하기 -home.entries.description: "튜토리얼, 예제, API 참조" -home.entries.label: "문서 구성" +home.entries.description: '튜토리얼, 예제, API 참조' +home.entries.label: '문서 구성' home.entries.reference.action: API 탐색 home.entries.reference.category: 참조 -home.entries.reference.description: "API 형식, 멤버, 선언 찾아보기" +home.entries.reference.description: 'API 형식, 멤버, 선언 찾아보기' home.entries.reference.title: API 참조 home.entries.samples.action: 예제 탐색 home.entries.samples.category: 예제 -home.entries.samples.description: "직접 실행하며 살펴보는 그래픽스와 컴퓨트 예제" +home.entries.samples.description: '직접 실행하며 살펴보는 그래픽스와 컴퓨트 예제' home.entries.samples.title: 예제 -home.entries.title: "문서" +home.entries.title: '문서' home.entries.tutorial.action: 튜토리얼 시작 home.entries.tutorial.category: 튜토리얼 -home.entries.tutorial.description: "빈 프로젝트에서 첫 삼각형을 그리기까지" +home.entries.tutorial.description: '빈 프로젝트에서 첫 삼각형을 그리기까지' home.entries.tutorial.title: 첫 번째 삼각형 -home.introduction.accent: "크로스 플랫폼 그래픽스" -home.introduction.description: "Zenith.NET은 DirectX, Metal, Vulkan의 그래픽스와 컴퓨트 기능을 하나의 API로 제공합니다" -home.introduction.title: ".NET으로 만드는{lineBreak}{accent}" -home.meta.description: "DirectX, Metal, Vulkan의 공통 API로 개발하는 .NET 크로스 플랫폼 그래픽스·컴퓨트 애플리케이션" -home.scene.description: "회전하는 도형을 조작할 수 있습니다. 드래그하거나 방향키를 눌러 시점을 바꾸세요." +home.introduction.accent: '크로스 플랫폼 그래픽스' +home.introduction.description: 'Zenith.NET은 DirectX, Metal, Vulkan의 그래픽스와 컴퓨트 기능을 하나의 API로 제공합니다' +home.introduction.title: '.NET으로 만드는{lineBreak}{accent}' +home.meta.description: 'DirectX, Metal, Vulkan의 공통 API로 개발하는 .NET 크로스 플랫폼 그래픽스·컴퓨트 애플리케이션' +home.scene.description: '회전하는 도형을 조작할 수 있습니다. 드래그하거나 방향키를 눌러 시점을 바꾸세요.' home.scene.label: 지오메트리 표시 home.scene.surface: 서피스 home.scene.wireframe: 와이어프레임 -home.title: ".NET을 위한 현대적인 RHI" -learning.concepts.description: "리소스 용도를 선택하고 셰이더 데이터를 기술하며 GPU 실행을 조율하는 방법" -learning.concepts.execution.description: "명령 기록과 제출, 리소스 수명" -learning.concepts.platforms.description: "네이티브 화면 표시와 UI 렌더링 컨트롤" -learning.concepts.resources.description: "리소스 용도, 메모리 배치, 뷰" -learning.concepts.shaders.description: "C#과 Slang의 데이터 배치 및 바인딩 규약" -learning.concepts.synchronization.description: "의존 관계, 가시성, 완료" +home.title: '.NET을 위한 현대적인 RHI' +learning.concepts.description: '리소스 용도를 선택하고 셰이더 데이터를 기술하며 GPU 실행을 조율하는 방법' +learning.concepts.execution.description: '명령 기록과 제출, 리소스 수명' +learning.concepts.platforms.description: '네이티브 화면 표시와 UI 렌더링 컨트롤' +learning.concepts.resources.description: '리소스 용도, 메모리 배치, 뷰' +learning.concepts.shaders.description: 'C#과 Slang의 데이터 배치 및 바인딩 규약' +learning.concepts.synchronization.description: '의존 관계, 가시성, 완료' learning.concepts.title: 핵심 개념 -learning.description: "삼각형 튜토리얼로 첫 애플리케이션을 만들어 보세요. 이후 리소스 관리, 셰이더 데이터, 동기화 개념을 필요한 순서대로 읽거나 구현하려는 기법의 예제를 살펴볼 수 있습니다." +learning.description: '삼각형 튜토리얼로 첫 애플리케이션을 만들어 보세요. 이후 리소스 관리, 셰이더 데이터, 동기화 개념을 필요한 순서대로 읽거나 구현하려는 기법의 예제를 살펴볼 수 있습니다.' learning.entries.samples.action: 예제 탐색 -learning.entries.samples.description: "지오메트리, 컴퓨트, 레이 쿼리, 메시 셰이딩의 C# 및 Slang 구현" +learning.entries.samples.description: '지오메트리, 컴퓨트, 레이 쿼리, 메시 셰이딩의 C# 및 Slang 구현' learning.entries.tutorial.action: 튜토리얼 열기 -learning.entries.tutorial.description: "창을 열고 삼각형을 그리는 콘솔 애플리케이션" -learning.meta.description: "Zenith.NET 프로그래밍 모델을 위한 튜토리얼과 개념 설명" +learning.entries.tutorial.description: '창을 열고 삼각형을 그리는 콘솔 애플리케이션' +learning.meta.description: 'Zenith.NET 프로그래밍 모델을 위한 튜토리얼과 개념 설명' learning.title: 학습 -reference.description: "리소스, 명령, 플랫폼 통합 참조" -reference.entries.commands.description: "그래픽스, 컴퓨트, 전송 명령" -reference.entries.commands.label: "명령 기록" -reference.entries.context.description: "선택한 백엔드의 GPU 리소스 생성" +reference.description: '리소스, 명령, 플랫폼 통합 참조' +reference.entries.commands.description: '그래픽스, 컴퓨트, 전송 명령' +reference.entries.commands.label: '명령 기록' +reference.entries.context.description: '선택한 백엔드의 GPU 리소스 생성' reference.entries.context.label: 여기서 시작 -reference.meta.description: "Zenith.NET 네임스페이스, 형식, 멤버" -reference.navigation.core: "핵심 API 참조" +reference.meta.description: 'Zenith.NET 네임스페이스, 형식, 멤버' +reference.navigation.core: '핵심 API 참조' reference.title: API 참조 -samples.computeShader.description: "이 예제는 {assetsTexturesShokoPng}를 읽고 컴퓨트 디스패치에서 회색조로 변환한 뒤 결과 텍스처를 표시합니다. 변환은 한 번만 실행하고 이후 프레임은 같은 결과를 표시합니다. 렌더러는 샘플링용 텍스처와 쓰기 가능한 텍스처를 바인딩하고, 스레드 그룹 수를 올림해 이미지 전체를 처리하며, 셰이더에서 이미지 범위를 확인하는 방법을 보여 줍니다." -samples.computeShader.details: "{computeShaderRendererCs} · {computeShaderSlang}" -samples.computeShader.title: "컴퓨트 셰이더" -samples.cube.description: "큐브는 인덱스 그리기, 상수 버퍼의 모델·뷰·투영 행렬, 깊이 테스트를 추가합니다. {d32FloatS8UInt} 깊이·스텐실 텍스처는 크기를 바꿀 때 다시 생성합니다." -samples.cube.details: "{spinningCubeRendererCs} · {spinningCubeSlang}" +samples.computeShader.description: '이 예제는 {assetsTexturesShokoPng}를 읽고 컴퓨트 디스패치에서 회색조로 변환한 뒤 결과 텍스처를 표시합니다. 변환은 한 번만 실행하고 이후 프레임은 같은 결과를 표시합니다. 렌더러는 샘플링용 텍스처와 쓰기 가능한 텍스처를 바인딩하고, 스레드 그룹 수를 올림해 이미지 전체를 처리하며, 셰이더에서 이미지 범위를 확인하는 방법을 보여 줍니다.' +samples.computeShader.details: '{computeShaderRendererCs} · {computeShaderSlang}' +samples.computeShader.title: '컴퓨트 셰이더' +samples.cube.description: '큐브는 인덱스 그리기, 상수 버퍼의 모델·뷰·투영 행렬, 깊이 테스트를 추가합니다. {d32FloatS8UInt} 깊이·스텐실 텍스처는 크기를 바꿀 때 다시 생성합니다.' +samples.cube.details: '{spinningCubeRendererCs} · {spinningCubeSlang}' samples.cube.title: 회전하는 큐브 -samples.description: "각 예제는 C# 렌더러와 Slang 셰이더를 함께 제공하며 한 가지 기법을 다룹니다. 애플리케이션 구성부터 렌더링까지의 전체 과정은 {link}에서 설명합니다." +samples.description: '각 예제는 C# 렌더러와 Slang 셰이더를 함께 제공하며 한 가지 기법을 다룹니다. 애플리케이션 구성부터 렌더링까지의 전체 과정은 {link}에서 설명합니다.' samples.description.link: 첫 번째 삼각형 -samples.execution.description: "{link} 프로젝트를 실행하고 콘솔 메뉴에서 예제를 선택합니다." +samples.execution.description: '{link} 프로젝트를 실행하고 콘솔 메뉴에서 예제를 선택합니다.' samples.execution.description.link: ZenithTutorials -samples.execution.title: "예제 실행" -samples.host.description: "{appCs}는 컨텍스트, 창, 스왑 체인을 초기화합니다. 매 프레임 명령 버퍼를 얻고 선택한 렌더러를 호출한 다음 명령을 제출하고 결과를 표시합니다. {iRendererCs}는 갱신, 렌더링, 크기 변경, 해제 작업을 정의합니다." -samples.host.details: "컴퓨트 렌더러와 레이 트레이싱 렌더러는 오프스크린 텍스처를 만듭니다. {texturePresenterCs}와 {presentTextureSlang}이 이 텍스처를 현재 출력 텍스처에 그리면, 공통 호스트가 명령을 제출하고 프레임을 화면에 표시합니다." -samples.host.title: "호스트와 화면 표시" -samples.indirectDrawing.description: "간접 그리기는 인덱스 그리기 인수 버퍼와 인스턴스별 구조화 데이터 버퍼로 여러 큐브를 그립니다. CPU가 인수를 제공하고 변환을 갱신합니다." -samples.indirectDrawing.details: "{indirectDrawingRendererCs} · {indirectDrawingSlang}" -samples.indirectDrawing.title: "간접 그리기" -samples.meshShading.description: "태스크 셰이더가 구 인스턴스를 컬링하고 남은 인덱스를 메시 셰이더에 전달하면 메시 셰이더가 지오메트리를 생성합니다. 파이프라인 생성 전에 {contextCapabilitiesMeshShadingSupported}를 확인합니다." -samples.meshShading.details: "{meshShadingRendererCs} · {meshShadingSlang}" +samples.execution.title: '예제 실행' +samples.host.description: '{appCs}는 컨텍스트, 창, 스왑 체인을 초기화합니다. 매 프레임 명령 버퍼를 얻고 선택한 렌더러를 호출한 다음 명령을 제출하고 결과를 표시합니다. {iRendererCs}는 갱신, 렌더링, 크기 변경, 해제 작업을 정의합니다.' +samples.host.details: '컴퓨트 렌더러와 레이 트레이싱 렌더러는 오프스크린 텍스처를 만듭니다. {texturePresenterCs}와 {presentTextureSlang}이 이 텍스처를 현재 출력 텍스처에 그리면, 공통 호스트가 명령을 제출하고 프레임을 화면에 표시합니다.' +samples.host.title: '호스트와 화면 표시' +samples.indirectDrawing.description: '간접 그리기는 인덱스 그리기 인수 버퍼와 인스턴스별 구조화 데이터 버퍼로 여러 큐브를 그립니다. CPU가 인수를 제공하고 변환을 갱신합니다.' +samples.indirectDrawing.details: '{indirectDrawingRendererCs} · {indirectDrawingSlang}' +samples.indirectDrawing.title: '간접 그리기' +samples.meshShading.description: '태스크 셰이더가 구 인스턴스를 컬링하고 남은 인덱스를 메시 셰이더에 전달하면 메시 셰이더가 지오메트리를 생성합니다. 파이프라인 생성 전에 {contextCapabilitiesMeshShadingSupported}를 확인합니다.' +samples.meshShading.details: '{meshShadingRendererCs} · {meshShadingSlang}' samples.meshShading.title: 메시 셰이딩 -samples.rayTracing.description: "바닥과 절차적 구의 하위·상위 가속 구조를 만들고 컴퓨트 셰이더에서 인라인 레이 쿼리를 수행합니다. 초기화 전에 {contextCapabilitiesRayTracingSupported}를 확인합니다." -samples.rayTracing.details: "{rayTracingRendererCs} · {rayTracingSlang}" +samples.rayTracing.description: '바닥과 절차적 구의 하위·상위 가속 구조를 만들고 컴퓨트 셰이더에서 인라인 레이 쿼리를 수행합니다. 초기화 전에 {contextCapabilitiesRayTracingSupported}를 확인합니다.' +samples.rayTracing.details: '{rayTracingRendererCs} · {rayTracingSlang}' samples.rayTracing.title: 레이 트레이싱 samples.title: 예제 -samples.triangle.description: "정점 버퍼와 대응하는 입력 레이아웃을 연결하고 그래픽스 파이프라인으로 정점 세 개를 그립니다." -samples.triangle.details: "{helloTriangleRendererCs} · {helloTriangleSlang} · {link}" +samples.triangle.description: '정점 버퍼와 대응하는 입력 레이아웃을 연결하고 그래픽스 파이프라인으로 정점 세 개를 그립니다.' +samples.triangle.details: '{helloTriangleRendererCs} · {helloTriangleSlang} · {link}' samples.triangle.details.link: 전체 튜토리얼 samples.triangle.title: Hello Triangle -samples.workloads.description: "주 저장소의 {link}에는 라이브러리 소스를 참조하는 더 큰 규모의 애플리케이션이 있습니다." +samples.workloads.description: '주 저장소의 {link}에는 라이브러리 소스를 참조하는 더 큰 규모의 애플리케이션이 있습니다.' samples.workloads.description.link: Experiments 디렉터리 -samples.workloads.details: "창을 사용하는 실험은 동일한 Windows, macOS, Linux/X11 표시 경로를 사용합니다. Avalonia, WinForms, WPF, WinUI/Uno, MAUI 컨트롤의 프레임 흐름과 구현 소스는 {link}에서 설명합니다." +samples.workloads.details: '창을 사용하는 실험은 동일한 Windows, macOS, Linux/X11 표시 경로를 사용합니다. Avalonia, WinForms, WPF, WinUI/Uno, MAUI 컨트롤의 프레임 흐름과 구현 소스는 {link}에서 설명합니다.' samples.workloads.details.link: 플랫폼 통합 -samples.workloads.table.cornellBox.example: "{link}" +samples.workloads.table.cornellBox.example: '{link}' samples.workloads.table.cornellBox.example.link: CornellBox -samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: "패스 트레이싱, 디노이징, 톤 매핑, 업스케일링, ImGui 컨트롤을 다룹니다. 레이 트레이싱 지원이 필요합니다." -samples.workloads.table.fluidTank.example: "{link}" +samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: '패스 트레이싱, 디노이징, 톤 매핑, 업스케일링, ImGui 컨트롤을 다룹니다. 레이 트레이싱 지원이 필요합니다.' +samples.workloads.table.fluidTank.example: '{link}' samples.workloads.table.fluidTank.example.link: FluidTank -samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: "컴퓨트 유체 시뮬레이션, 시뮬레이션 단계 사이의 의존 관계, 다중 패스 표면 렌더링을 다룹니다." +samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: '컴퓨트 유체 시뮬레이션, 시뮬레이션 단계 사이의 의존 관계, 다중 패스 표면 렌더링을 다룹니다.' samples.workloads.table.headings.example: 예제 -samples.workloads.table.headings.whatItDemonstratesAndRequires: "기법과 요구 사항" -samples.workloads.table.inkCanvas.example: "{link}" +samples.workloads.table.headings.whatItDemonstratesAndRequires: '기법과 요구 사항' +samples.workloads.table.inkCanvas.example: '{link}' samples.workloads.table.inkCanvas.example.link: InkCanvas -samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: "네이티브 창에서의 Skia 그리기 및 입력 처리를 보여줍니다. 대상 플랫폼용 백엔드 및 네이티브 Skia 라이브러리가 필요합니다." -samples.workloads.table.platformDetection.example: "{link}" +samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: '네이티브 창에서의 Skia 그리기 및 입력 처리를 보여줍니다. 대상 플랫폼용 백엔드 및 네이티브 Skia 라이브러리가 필요합니다.' +samples.workloads.table.platformDetection.example: '{link}' samples.workloads.table.platformDetection.example.link: PlatformDetection -samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: "각 백엔드의 컨텍스트 생성을 시도하고 장치 기능을 보고합니다. 생성에 실패하면 지원되지 않는 것으로 표시하지만, 원인은 장치나 드라이버 또는 누락된 런타임 의존성일 수 있습니다." -samples.workloads.title: "복합 렌더링 애플리케이션" -tutorial.context.description: "{graphicsContext}는 백엔드를 통해 애플리케이션을 GPU에 연결하고 렌더링 리소스를 만드는 메서드를 제공합니다." -tutorial.context.details: "컨텍스트 초기화를 {emphasis}에 추가합니다." +samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: '각 백엔드의 컨텍스트 생성을 시도하고 장치 기능을 보고합니다. 생성에 실패하면 지원되지 않는 것으로 표시하지만, 원인은 장치나 드라이버 또는 누락된 런타임 의존성일 수 있습니다.' +samples.workloads.title: '복합 렌더링 애플리케이션' +tutorial.context.description: '{graphicsContext}는 백엔드를 통해 애플리케이션을 GPU에 연결하고 렌더링 리소스를 만드는 메서드를 제공합니다.' +tutorial.context.details: '컨텍스트 초기화를 {emphasis}에 추가합니다.' tutorial.context.details.emphasis: using 지시문 뒤, {iWindowWindow} 앞 -tutorial.context.guidance: "각 분기에서 플랫폼에 맞는 백엔드를 선택하고 검증을 요청합니다. {validationMessage} 메시지는 콘솔에 출력합니다." -tutorial.context.imports: "{programCs} 맨 위에 다음 using 지시문을 추가합니다." -tutorial.context.title: "그래픽스 컨텍스트" -tutorial.description: "이 튜토리얼에서는 빈 .NET 콘솔 프로젝트에서 시작해 창을 열고 색상이 있는 삼각형을 그리는 애플리케이션을 만듭니다." -tutorial.details: "튜토리얼에는 세 번의 확인 단계가 있습니다. 먼저 빈 창을 열고, 단색 배경을 표시한 다음, 색상이 있는 삼각형을 그립니다. 각 단계에서 애플리케이션을 실행해 결과를 확인한 뒤 다음 부분을 추가합니다." -tutorial.draw.context: "{draw}의 인수는 다음과 같습니다." -tutorial.draw.description: "{windowRender} 콜백의 {addTheTriangleDrawCommandsHereLater}를 다음 명령으로 바꿉니다. 위치는 {beginRenderPass}와 {endRenderPass} 사이입니다." -tutorial.draw.details: "{setPipeline}은 셰이더와 렌더링 상태를 선택합니다. 정점 바인딩은 파이프라인의 입력 레이아웃으로 해석되므로, 그 전에 호출해야 합니다." -tutorial.draw.guidance: "{setVertexBufferVertexBuffer}는 업로드한 정점 데이터를 바이트 오프셋 0부터 입력 슬롯 0에 바인딩합니다. 이 슬롯은 {inputLayouts}의 유일한 항목과 대응합니다." -tutorial.draw.notes: "이 호출들은 그리기 명령을 기록합니다. 기존의 {submitWait}가 명령을 제출하고 GPU 완료를 기다리면, {present}가 완성된 이미지의 표시를 요청합니다. 삼각형 바깥 영역에도 배경색이 정해지도록 패스 시작 부분의 지우기 작업을 유지합니다." +tutorial.context.guidance: '각 분기에서 플랫폼에 맞는 백엔드를 선택하고 검증을 요청합니다. {validationMessage} 메시지는 콘솔에 출력합니다.' +tutorial.context.imports: '{programCs} 맨 위에 다음 using 지시문을 추가합니다.' +tutorial.context.title: '그래픽스 컨텍스트' +tutorial.description: '이 튜토리얼에서는 빈 .NET 콘솔 프로젝트에서 시작해 창을 열고 색상이 있는 삼각형을 그리는 애플리케이션을 만듭니다.' +tutorial.details: '튜토리얼에는 세 번의 확인 단계가 있습니다. 먼저 빈 창을 열고, 단색 배경을 표시한 다음, 색상이 있는 삼각형을 그립니다. 각 단계에서 애플리케이션을 실행해 결과를 확인한 뒤 다음 부분을 추가합니다.' +tutorial.draw.context: '{draw}의 인수는 다음과 같습니다.' +tutorial.draw.description: '{windowRender} 콜백의 {addTheTriangleDrawCommandsHereLater}를 다음 명령으로 바꿉니다. 위치는 {beginRenderPass}와 {endRenderPass} 사이입니다.' +tutorial.draw.details: '{setPipeline}은 셰이더와 렌더링 상태를 선택합니다. 정점 바인딩은 파이프라인의 입력 레이아웃으로 해석되므로, 그 전에 호출해야 합니다.' +tutorial.draw.guidance: '{setVertexBufferVertexBuffer}는 업로드한 정점 데이터를 바이트 오프셋 0부터 입력 슬롯 0에 바인딩합니다. 이 슬롯은 {inputLayouts}의 유일한 항목과 대응합니다.' +tutorial.draw.notes: '이 호출들은 그리기 명령을 기록합니다. 기존의 {submitWait}가 명령을 제출하고 GPU 완료를 기다리면, {present}가 완성된 이미지의 표시를 요청합니다. 삼각형 바깥 영역에도 배경색이 정해지도록 패스 시작 부분의 지우기 작업을 유지합니다.' tutorial.draw.table.firstInstance.meaning: 인스턴스 번호 매기기를 0부터 시작합니다. tutorial.draw.table.firstVertex.meaning: 버퍼의 첫 번째 정점부터 시작합니다. tutorial.draw.table.headings.argument: 인수 @@ -362,152 +362,152 @@ tutorial.draw.table.headings.description: 값 tutorial.draw.table.headings.meaning: 의미 tutorial.draw.table.instanceCount.meaning: 삼각형 한 개를 그립니다. tutorial.draw.table.vertexCount.meaning: 세 개의 정점을 읽습니다. -tutorial.draw.title: "그리기 명령" -tutorial.execution.description: "{firstTriangle} 프로젝트를 빌드하고 실행합니다." -tutorial.execution.details: "어두운 배경 위에 위쪽은 빨강, 오른쪽 아래는 초록, 왼쪽 아래는 파랑인 삼각형이 나타나야 합니다. 내부 색상은 정점 색상을 보간한 결과로, 부드럽게 이어집니다." -tutorial.execution.guidance: "창 크기를 바꾸면 이미지의 픽셀 크기가 달라지지만 정점 좌표는 그대로입니다. 뷰포트는 이 좌표를 새로운 너비와 높이에 맞추므로 창의 가로세로 비율이 바뀌면 삼각형도 늘어나거나 줄어듭니다." -tutorial.execution.title: "애플리케이션 실행" -tutorial.frame.commands.context: "{endRenderPass} 뒤의 두 번째 전환은 출력 텍스처를 화면에 표시할 수 있도록 준비합니다. {submit}은 기록을 끝내고 명령 버퍼를 제출하며, {wait}는 해당 제출이 완료될 때까지 CPU 스레드를 대기시킵니다. 이어서 {present}가 렌더링한 이미지의 표시를 요청합니다." -tutorial.frame.commands.description: "렌더 패스는 같은 어태치먼트에 쓰는 그리기 작업을 묶습니다. 이 패스에서는 스왑 체인의 출력 텍스처가 색상 결과를 받습니다. {colorAttachmentClear}는 해당 어태치먼트를 RGBA 색상으로 초기화하고 패스가 끝난 뒤에도 내용을 보존하도록 지정합니다. {beginRenderPass}는 이 설정으로 패스를 시작하는 명령을 기록합니다." -tutorial.frame.commands.details: "컬렉션에는 색상 어태치먼트 하나가 있습니다. {null}은 이 패스에 깊이·스텐실 어태치먼트가 없다는 뜻입니다." -tutorial.frame.commands.guidance: "{beginRenderPass}는 어태치먼트 전체를 덮도록 뷰포트와 시저를 설정합니다. 뷰포트는 렌더링 좌표를 픽셀 위치로 바꾸고 시저는 쓸 수 있는 영역을 제한합니다." -tutorial.frame.commands.title: "지우기, 제출, 표시" -tutorial.frame.description: "먼저 창을 하나의 배경색으로 채웁니다. 이 작업을 지우기라고 합니다. 배경색이 보이면 서피스, 명령 제출, 표시 과정이 연결된 것입니다. 이제 삼각형의 정점과 셰이더를 추가할 수 있습니다." -tutorial.frame.details: "Silk.NET은 프레임을 그릴 시점에 콜백을 호출합니다. 이 예제는 경과 시간 인수를 쓰지 않으므로 매개변수 이름을 {value}로 둡니다. 콜백을 {emphasis}에 등록합니다." -tutorial.frame.details.emphasis: "{windowRun} 앞" -tutorial.frame.target.description: "{graphicsQueueCommandBuffer}는 기록할 준비가 된 명령 버퍼를 반환합니다. 기록은 GPU 작업을 정의하는 단계이며 실행은 제출 후 시작됩니다." -tutorial.frame.target.details: "텍스처 레이아웃은 작업에 필요한 접근 방식을 나타냅니다. 첫 번째 {transition} 호출은 출력 텍스처를 색상 어태치먼트로 사용할 수 있도록 준비합니다. 여기서 {default}는 출력 텍스처의 기본 이미지인 밉 레벨 0과 배열 레이어 0을 선택합니다. 이 패스는 이미지 전체를 지우므로 {undefined}를 지정해 이전 내용을 버릴 수 있습니다." -tutorial.frame.target.guidance: "화면에 표시한 뒤에는 다른 이미지로 넘어갈 수 있으므로 매 프레임 현재 출력 텍스처를 가져옵니다." -tutorial.frame.target.title: "출력 텍스처 준비" -tutorial.frame.title: "첫 프레임" -tutorial.geometry.data.description: "정점 배열을 {emphasis}에 추가합니다. 이후 리소스 초기화도 설명한 순서대로 이 콜백 앞에 둡니다." -tutorial.geometry.data.description.emphasis: "{windowRender} 앞" -tutorial.geometry.data.details: "각 항목은 {vertex}를 생성하고, 안쪽의 두 {new} 표현식은 {vector3} 위치와 {vector4} 색상을 제공합니다. 위치는 위, 오른쪽 아래, 왼쪽 아래 꼭짓점입니다. 정점 셰이더는 네 번째 좌표를 {w}로 설정합니다. w가 1이므로 x와 y는 정규화 장치 좌표이기도 하며, -1과 +1은 이미지 경계, 0은 중앙을 뜻합니다. 이 해석은 픽셀 크기와 무관합니다." -tutorial.geometry.data.guidance: "각 색상은 빨강, 초록, 파랑, 알파 성분을 가지며 알파는 1입니다. 세 정점 모두 z = 0인 같은 평면에 있습니다." -tutorial.geometry.data.title: "정점 위치와 색상" -tutorial.geometry.description: "세 정점은 각각 위치와 색상을 가집니다. GPU는 위치로 삼각형 모양을 정하고 정점 색상을 보간해 내부의 색상을 계산합니다." -tutorial.geometry.format.description: "정점 선언을 {emphasis}에 추가합니다." -tutorial.geometry.format.description.emphasis: "{programCs} 끝부분, 정리 문 뒤" -tutorial.geometry.format.details: "{file}은 형식의 사용 범위를 {programCs}로 제한하고, {layoutKindSequential}은 필드를 선언 순서대로 배치합니다. {position}은 32비트 부동소수점 값 세 개로 구성되며 바이트 오프셋 0에서 시작합니다. {color}는 네 개로 구성되며 바이트 오프셋 12에서 시작합니다. 따라서 정점 하나는 28바이트입니다. GPU가 각 필드를 올바르게 읽을 수 있도록 입력 레이아웃에 이 배치를 기술합니다." -tutorial.geometry.format.imports: "벡터 형식과 구조체 레이아웃 특성을 사용하도록 {programCs} 맨 위에 다음 using 지시문을 추가합니다." -tutorial.geometry.format.title: "정점 표현" -tutorial.geometry.title: "정점 데이터" -tutorial.geometry.upload.context: "{fixed}는 배열의 주소를 사용하는 동안 가비지 수집기가 배열을 옮기지 못하게 고정합니다. 이 버퍼는 CPU 쓰기가 가능하므로 {upload}는 메모리를 매핑하고 바이트를 복사한 뒤 매핑을 해제하고 반환합니다. 배열은 이 호출이 끝날 때까지만 고정하면 됩니다. 정점은 초기화 중에 한 번 업로드하고, 버퍼는 렌더링이 끝날 때까지 유지합니다." -tutorial.geometry.upload.description: "GPU가 그리기 중에 읽을 수 있도록 정점 데이터를 {buffer}에 저장합니다. 배열 바로 뒤에 버퍼 할당과 업로드 코드를 추가합니다." -tutorial.geometry.upload.details: "할당 크기는 {sizeofVertexVerticesLength}로, 28바이트 정점 세 개인 84바이트입니다. {bufferUsagesVertex}는 정점 입력 접근을 선언하고 {cpuWriteOnly}는 CPU 직접 초기화를 허용합니다. 설명의 스트라이드는 요소 크기이며, 뒤에서 정의할 입력 레이아웃이 각 속성을 읽는 방법을 정합니다." -tutorial.geometry.upload.guidance: "할당만으로 버퍼 내용이 초기화되지는 않습니다. {upload}는 데이터 설명의 원본 포인터와 바이트 수를 사용해 배열을 목적지 오프셋 0에 복사합니다." -tutorial.geometry.upload.imports: "Zenith.NET 버퍼 형식을 {systemBuffer}와 구분하기 위해 {programCs}의 using 지시문에 {bufferAlias} 구문을 추가합니다." -tutorial.geometry.upload.notes: "{programCs} 끝의 해제 코드에서 {swapChainDispose} 바로 앞에 {vertexBufferDispose}를 추가합니다. 큰 정적 지오메트리를 위한 GPU 전용 저장과 전송은 {link}에서 설명합니다." +tutorial.draw.title: '그리기 명령' +tutorial.execution.description: '{firstTriangle} 프로젝트를 빌드하고 실행합니다.' +tutorial.execution.details: '어두운 배경 위에 위쪽은 빨강, 오른쪽 아래는 초록, 왼쪽 아래는 파랑인 삼각형이 나타나야 합니다. 내부 색상은 정점 색상을 보간한 결과로, 부드럽게 이어집니다.' +tutorial.execution.guidance: '창 크기를 바꾸면 이미지의 픽셀 크기가 달라지지만 정점 좌표는 그대로입니다. 뷰포트는 이 좌표를 새로운 너비와 높이에 맞추므로 창의 가로세로 비율이 바뀌면 삼각형도 늘어나거나 줄어듭니다.' +tutorial.execution.title: '애플리케이션 실행' +tutorial.frame.commands.context: '{endRenderPass} 뒤의 두 번째 전환은 출력 텍스처를 화면에 표시할 수 있도록 준비합니다. {submit}은 기록을 끝내고 명령 버퍼를 제출하며, {wait}는 해당 제출이 완료될 때까지 CPU 스레드를 대기시킵니다. 이어서 {present}가 렌더링한 이미지의 표시를 요청합니다.' +tutorial.frame.commands.description: '렌더 패스는 같은 어태치먼트에 쓰는 그리기 작업을 묶습니다. 이 패스에서는 스왑 체인의 출력 텍스처가 색상 결과를 받습니다. {colorAttachmentClear}는 해당 어태치먼트를 RGBA 색상으로 초기화하고 패스가 끝난 뒤에도 내용을 보존하도록 지정합니다. {beginRenderPass}는 이 설정으로 패스를 시작하는 명령을 기록합니다.' +tutorial.frame.commands.details: '컬렉션에는 색상 어태치먼트 하나가 있습니다. {null}은 이 패스에 깊이·스텐실 어태치먼트가 없다는 뜻입니다.' +tutorial.frame.commands.guidance: '{beginRenderPass}는 어태치먼트 전체를 덮도록 뷰포트와 시저를 설정합니다. 뷰포트는 렌더링 좌표를 픽셀 위치로 바꾸고 시저는 쓸 수 있는 영역을 제한합니다.' +tutorial.frame.commands.title: '지우기, 제출, 표시' +tutorial.frame.description: '먼저 창을 하나의 배경색으로 채웁니다. 이 작업을 지우기라고 합니다. 배경색이 보이면 서피스, 명령 제출, 표시 과정이 연결된 것입니다. 이제 삼각형의 정점과 셰이더를 추가할 수 있습니다.' +tutorial.frame.details: 'Silk.NET은 프레임을 그릴 시점에 콜백을 호출합니다. 이 예제는 경과 시간 인수를 쓰지 않으므로 매개변수 이름을 {value}로 둡니다. 콜백을 {emphasis}에 등록합니다.' +tutorial.frame.details.emphasis: '{windowRun} 앞' +tutorial.frame.target.description: '{graphicsQueueCommandBuffer}는 기록할 준비가 된 명령 버퍼를 반환합니다. 기록은 GPU 작업을 정의하는 단계이며 실행은 제출 후 시작됩니다.' +tutorial.frame.target.details: '텍스처 레이아웃은 작업에 필요한 접근 방식을 나타냅니다. 첫 번째 {transition} 호출은 출력 텍스처를 색상 어태치먼트로 사용할 수 있도록 준비합니다. 여기서 {default}는 출력 텍스처의 기본 이미지인 밉 레벨 0과 배열 레이어 0을 선택합니다. 이 패스는 이미지 전체를 지우므로 {undefined}를 지정해 이전 내용을 버릴 수 있습니다.' +tutorial.frame.target.guidance: '화면에 표시한 뒤에는 다른 이미지로 넘어갈 수 있으므로 매 프레임 현재 출력 텍스처를 가져옵니다.' +tutorial.frame.target.title: '출력 텍스처 준비' +tutorial.frame.title: '첫 프레임' +tutorial.geometry.data.description: '정점 배열을 {emphasis}에 추가합니다. 이후 리소스 초기화도 설명한 순서대로 이 콜백 앞에 둡니다.' +tutorial.geometry.data.description.emphasis: '{windowRender} 앞' +tutorial.geometry.data.details: '각 항목은 {vertex}를 생성하고, 안쪽의 두 {new} 표현식은 {vector3} 위치와 {vector4} 색상을 제공합니다. 위치는 위, 오른쪽 아래, 왼쪽 아래 꼭짓점입니다. 정점 셰이더는 네 번째 좌표를 {w}로 설정합니다. w가 1이므로 x와 y는 정규화 장치 좌표이기도 하며, -1과 +1은 이미지 경계, 0은 중앙을 뜻합니다. 이 해석은 픽셀 크기와 무관합니다.' +tutorial.geometry.data.guidance: '각 색상은 빨강, 초록, 파랑, 알파 성분을 가지며 알파는 1입니다. 세 정점 모두 z = 0인 같은 평면에 있습니다.' +tutorial.geometry.data.title: '정점 위치와 색상' +tutorial.geometry.description: '세 정점은 각각 위치와 색상을 가집니다. GPU는 위치로 삼각형 모양을 정하고 정점 색상을 보간해 내부의 색상을 계산합니다.' +tutorial.geometry.format.description: '정점 선언을 {emphasis}에 추가합니다.' +tutorial.geometry.format.description.emphasis: '{programCs} 끝부분, 정리 문 뒤' +tutorial.geometry.format.details: '{file}은 형식의 사용 범위를 {programCs}로 제한하고, {layoutKindSequential}은 필드를 선언 순서대로 배치합니다. {position}은 32비트 부동소수점 값 세 개로 구성되며 바이트 오프셋 0에서 시작합니다. {color}는 네 개로 구성되며 바이트 오프셋 12에서 시작합니다. 따라서 정점 하나는 28바이트입니다. GPU가 각 필드를 올바르게 읽을 수 있도록 입력 레이아웃에 이 배치를 기술합니다.' +tutorial.geometry.format.imports: '벡터 형식과 구조체 레이아웃 특성을 사용하도록 {programCs} 맨 위에 다음 using 지시문을 추가합니다.' +tutorial.geometry.format.title: '정점 표현' +tutorial.geometry.title: '정점 데이터' +tutorial.geometry.upload.context: '{fixed}는 배열의 주소를 사용하는 동안 가비지 수집기가 배열을 옮기지 못하게 고정합니다. 이 버퍼는 CPU 쓰기가 가능하므로 {upload}는 메모리를 매핑하고 바이트를 복사한 뒤 매핑을 해제하고 반환합니다. 배열은 이 호출이 끝날 때까지만 고정하면 됩니다. 정점은 초기화 중에 한 번 업로드하고, 버퍼는 렌더링이 끝날 때까지 유지합니다.' +tutorial.geometry.upload.description: 'GPU가 그리기 중에 읽을 수 있도록 정점 데이터를 {buffer}에 저장합니다. 배열 바로 뒤에 버퍼 할당과 업로드 코드를 추가합니다.' +tutorial.geometry.upload.details: '할당 크기는 {sizeofVertexVerticesLength}로, 28바이트 정점 세 개인 84바이트입니다. {bufferUsagesVertex}는 정점 입력 접근을 선언하고 {cpuWriteOnly}는 CPU 직접 초기화를 허용합니다. 설명의 스트라이드는 요소 크기이며, 뒤에서 정의할 입력 레이아웃이 각 속성을 읽는 방법을 정합니다.' +tutorial.geometry.upload.guidance: '할당만으로 버퍼 내용이 초기화되지는 않습니다. {upload}는 데이터 설명의 원본 포인터와 바이트 수를 사용해 배열을 목적지 오프셋 0에 복사합니다.' +tutorial.geometry.upload.imports: 'Zenith.NET 버퍼 형식을 {systemBuffer}와 구분하기 위해 {programCs}의 using 지시문에 {bufferAlias} 구문을 추가합니다.' +tutorial.geometry.upload.notes: '{programCs} 끝의 해제 코드에서 {swapChainDispose} 바로 앞에 {vertexBufferDispose}를 추가합니다. 큰 정적 지오메트리를 위한 GPU 전용 저장과 전송은 {link}에서 설명합니다.' tutorial.geometry.upload.notes.link: 리소스 관리 -tutorial.geometry.upload.title: "버퍼 할당과 업로드" -tutorial.input.description: "GPU는 위치와 색상 같은 정점 속성이 어디에 있는지 알아야 합니다. 입력 레이아웃은 각 속성의 포맷과 바이트 오프셋을 지정합니다. 스트라이드는 다음 정점까지의 바이트 거리입니다. 셰이더를 생성한 뒤 다음 코드를 추가합니다." -tutorial.input.details: "{inputLayoutAdd}는 각 속성을 이전 속성 바로 뒤에 배치하고 그 크기를 정점 간 스트라이드에 더합니다. 오프셋은 C# 구조체를 조사하는 대신 여기서 지정한 형식으로 계산합니다. 두 필드의 배치는 다음과 같습니다." -tutorial.input.guidance: "{semanticIndex}의 기본값은 0이며 셰이더의 {pOSITION0}, {cOLOR0}과 일치합니다. 위치와 색상이 하나의 정점 버퍼에 함께 저장되므로 파이프라인은 슬롯 0에 입력 레이아웃 하나를 사용합니다. C# 구조체의 필드 순서나 패딩을 바꾸면 입력 레이아웃도 맞춰 수정합니다." +tutorial.geometry.upload.title: '버퍼 할당과 업로드' +tutorial.input.description: 'GPU는 위치와 색상 같은 정점 속성이 어디에 있는지 알아야 합니다. 입력 레이아웃은 각 속성의 포맷과 바이트 오프셋을 지정합니다. 스트라이드는 다음 정점까지의 바이트 거리입니다. 셰이더를 생성한 뒤 다음 코드를 추가합니다.' +tutorial.input.details: '{inputLayoutAdd}는 각 속성을 이전 속성 바로 뒤에 배치하고 그 크기를 정점 간 스트라이드에 더합니다. 오프셋은 C# 구조체를 조사하는 대신 여기서 지정한 형식으로 계산합니다. 두 필드의 배치는 다음과 같습니다.' +tutorial.input.guidance: '{semanticIndex}의 기본값은 0이며 셰이더의 {pOSITION0}, {cOLOR0}과 일치합니다. 위치와 색상이 하나의 정점 버퍼에 함께 저장되므로 파이프라인은 슬롯 0에 입력 레이아웃 하나를 사용합니다. C# 구조체의 필드 순서나 패딩을 바꾸면 입력 레이아웃도 맞춰 수정합니다.' tutorial.input.table.headings.byteOffset: 바이트 오프셋 -tutorial.input.table.headings.cField: "C# 필드" +tutorial.input.table.headings.cField: 'C# 필드' tutorial.input.table.headings.format: 형식 tutorial.input.table.headings.shaderInput: 셰이더 입력 tutorial.input.table.nextVertex.cField: 다음 정점 -tutorial.input.table.nextVertex.format: "총 스트라이드: 28바이트" +tutorial.input.table.nextVertex.format: '총 스트라이드: 28바이트' tutorial.input.table.nextVertex.shaderInput: 다음 입력 레코드 -tutorial.input.table.vertexColor.format: "{float4} (16바이트)" -tutorial.input.table.vertexPosition.format: "{float3} (12바이트)" -tutorial.input.title: "정점 입력 레이아웃" -tutorial.lifecycle.description: "각 프레임은 다음 순서를 따릅니다." -tutorial.lifecycle.details: "창을 닫으면 {run}이 반환하고 정리 코드가 이어서 실행됩니다. 각 프레임에서 제출한 작업이 끝날 때까지 이미 기다렸으므로 명령에 사용한 리소스를 해제할 수 있습니다. {windowRun} 뒤에 들어갈 전체 정리 코드는 다음과 같습니다." -tutorial.lifecycle.guidance: "네이티브 창을 파괴하기 전에 스왑 체인을 해제하고, 컨텍스트는 그 리소스들을 해제한 뒤 정리합니다. 제출한 명령 버퍼는 큐가 재사용하고 출력 텍스처는 스왑 체인이 관리하므로 각각 {dispose}를 호출할 필요가 없습니다." -tutorial.lifecycle.title: "프레임 흐름과 해제" -tutorial.pipeline.behavior: "입력 레이아웃 다음에 파이프라인을 생성합니다." -tutorial.pipeline.context: "{cullNone}은 면 컬링을 끕니다. 따라서 정점이 시계 방향으로 보이든 반시계 방향으로 보이든 삼각형을 그립니다." -tutorial.pipeline.description: "{graphicsPipeline}은 정점 레이아웃, 두 셰이더, 프리미티브 조립과 어태치먼트 출력 설정을 하나로 묶습니다." -tutorial.pipeline.details: "셰이더는 정점과 프래그먼트를 처리합니다. 나머지 파이프라인 설정은 프리미티브 조립, 면 컬링, 깊이 테스트, 색상 블렌딩을 제어합니다." -tutorial.pipeline.guidance: "파이프라인의 색상 포맷은 렌더 패스의 어태치먼트와 같아야 하므로 {swapChainDescFormat}에서 가져옵니다. {count1}은 픽셀당 샘플 하나를 지정합니다." -tutorial.pipeline.item: "{triangleList}는 연속된 정점 세 개를 한 삼각형으로 조립합니다." -tutorial.pipeline.notes: "{depthNone}은 깊이 테스트와 쓰기를 끕니다. 깊이 어태치먼트가 없는 패스와 일치하는 설정입니다." -tutorial.pipeline.reference: "{opaque}는 블렌딩을 끕니다. 따라서 프래그먼트 셰이더 출력이 삼각형 내부의 배경색을 대체합니다." -tutorial.pipeline.title: "그래픽스 파이프라인" -tutorial.pipeline.usage: "셰이더 객체는 파이프라인을 생성한 뒤 해제할 수 있습니다. 파이프라인은 렌더링 동안 유지하고, 해제 코드에서 {vertexBufferDispose} 앞에 {pipelineDispose}를 추가합니다." -tutorial.presentation.title: "그래픽스 컨텍스트와 표시" -tutorial.project.context: "프로젝트 빌드 설정에서 {emphasis}({allowUnsafeBlocks})를 켭니다. 창 보조 코드의 네이티브 호출과 정점 업로드에는 unsafe 코드가 필요합니다." +tutorial.input.table.vertexColor.format: '{float4} (16바이트)' +tutorial.input.table.vertexPosition.format: '{float3} (12바이트)' +tutorial.input.title: '정점 입력 레이아웃' +tutorial.lifecycle.description: '각 프레임은 다음 순서를 따릅니다.' +tutorial.lifecycle.details: '창을 닫으면 {run}이 반환하고 정리 코드가 이어서 실행됩니다. 각 프레임에서 제출한 작업이 끝날 때까지 이미 기다렸으므로 명령에 사용한 리소스를 해제할 수 있습니다. {windowRun} 뒤에 들어갈 전체 정리 코드는 다음과 같습니다.' +tutorial.lifecycle.guidance: '네이티브 창을 파괴하기 전에 스왑 체인을 해제하고, 컨텍스트는 그 리소스들을 해제한 뒤 정리합니다. 제출한 명령 버퍼는 큐가 재사용하고 출력 텍스처는 스왑 체인이 관리하므로 각각 {dispose}를 호출할 필요가 없습니다.' +tutorial.lifecycle.title: '프레임 흐름과 해제' +tutorial.pipeline.behavior: '입력 레이아웃 다음에 파이프라인을 생성합니다.' +tutorial.pipeline.context: '{cullNone}은 면 컬링을 끕니다. 따라서 정점이 시계 방향으로 보이든 반시계 방향으로 보이든 삼각형을 그립니다.' +tutorial.pipeline.description: '{graphicsPipeline}은 정점 레이아웃, 두 셰이더, 프리미티브 조립과 어태치먼트 출력 설정을 하나로 묶습니다.' +tutorial.pipeline.details: '셰이더는 정점과 프래그먼트를 처리합니다. 나머지 파이프라인 설정은 프리미티브 조립, 면 컬링, 깊이 테스트, 색상 블렌딩을 제어합니다.' +tutorial.pipeline.guidance: '파이프라인의 색상 포맷은 렌더 패스의 어태치먼트와 같아야 하므로 {swapChainDescFormat}에서 가져옵니다. {count1}은 픽셀당 샘플 하나를 지정합니다.' +tutorial.pipeline.item: '{triangleList}는 연속된 정점 세 개를 한 삼각형으로 조립합니다.' +tutorial.pipeline.notes: '{depthNone}은 깊이 테스트와 쓰기를 끕니다. 깊이 어태치먼트가 없는 패스와 일치하는 설정입니다.' +tutorial.pipeline.reference: '{opaque}는 블렌딩을 끕니다. 따라서 프래그먼트 셰이더 출력이 삼각형 내부의 배경색을 대체합니다.' +tutorial.pipeline.title: '그래픽스 파이프라인' +tutorial.pipeline.usage: '셰이더 객체는 파이프라인을 생성한 뒤 해제할 수 있습니다. 파이프라인은 렌더링 동안 유지하고, 해제 코드에서 {vertexBufferDispose} 앞에 {pipelineDispose}를 추가합니다.' +tutorial.presentation.title: '그래픽스 컨텍스트와 표시' +tutorial.project.context: '프로젝트 빌드 설정에서 {emphasis}({allowUnsafeBlocks})를 켭니다. 창 보조 코드의 네이티브 호출과 정점 업로드에는 unsafe 코드가 필요합니다.' tutorial.project.context.emphasis: 안전하지 않은 코드 허용 -tutorial.project.description: ".NET 10을 대상으로 하는 {firstTriangle} C# 콘솔 프로젝트를 만듭니다." -tutorial.project.details: "다음 NuGet 패키지를 프로젝트에 추가합니다." -tutorial.project.guidance: "{zenithNET}은 공통 렌더링 API를, 백엔드 패키지 세 개는 플랫폼 구현을 제공합니다. {zenithNETCompiler}는 뒤에서 작성할 Slang 셰이더를 선택한 백엔드에 맞게 컴파일합니다. Silk.NET은 창 생성과 이벤트 처리를 담당합니다." -tutorial.project.title: "프로젝트 준비" -tutorial.requirements.context: "{link}와 해당 {detail}에서 이 튜토리얼의 참조 구현을 확인할 수 있습니다." +tutorial.project.description: '.NET 10을 대상으로 하는 {firstTriangle} C# 콘솔 프로젝트를 만듭니다.' +tutorial.project.details: '다음 NuGet 패키지를 프로젝트에 추가합니다.' +tutorial.project.guidance: '{zenithNET}은 공통 렌더링 API를, 백엔드 패키지 세 개는 플랫폼 구현을 제공합니다. {zenithNETCompiler}는 뒤에서 작성할 Slang 셰이더를 선택한 백엔드에 맞게 컴파일합니다. Silk.NET은 창 생성과 이벤트 처리를 담당합니다.' +tutorial.project.title: '프로젝트 준비' +tutorial.requirements.context: '{link}와 해당 {detail}에서 이 튜토리얼의 참조 구현을 확인할 수 있습니다.' tutorial.requirements.context.detail: 공유 호스트 -tutorial.requirements.context.link: "Hello Triangle 예제" -tutorial.requirements.description: "{emphasis}와 기본 C# 지식이 필요합니다. 애플리케이션의 대상 프레임워크는 {net10}입니다. GPU와 드라이버는 사용 중인 플랫폼에 맞춰 선택한 다음 백엔드를 지원해야 합니다." +tutorial.requirements.context.link: 'Hello Triangle 예제' +tutorial.requirements.description: '{emphasis}와 기본 C# 지식이 필요합니다. 애플리케이션의 대상 프레임워크는 {net10}입니다. GPU와 드라이버는 사용 중인 플랫폼에 맞춰 선택한 다음 백엔드를 지원해야 합니다.' tutorial.requirements.description.emphasis: .NET 10 SDK -tutorial.requirements.guidance: "Zenith.NET은 애플리케이션이 제공하는 네이티브 서피스에 렌더링합니다. Silk.NET.Windowing은 창을 만들고 이벤트를 처리합니다. macOS에서는 {cAMetalLayerCs}로 표현되는 Metal 레이어로 표시하며, 창 보조 코드가 이 레이어를 창에 연결합니다." +tutorial.requirements.guidance: 'Zenith.NET은 애플리케이션이 제공하는 네이티브 서피스에 렌더링합니다. Silk.NET.Windowing은 창을 만들고 이벤트를 처리합니다. macOS에서는 {cAMetalLayerCs}로 표현되는 Metal 레이어로 표시하며, 창 보조 코드가 이 레이어를 창에 연결합니다.' tutorial.requirements.table.headings.graphicsBackend: 그래픽 백엔드 tutorial.requirements.table.headings.platform: 플랫폼 tutorial.requirements.table.linux.graphicsBackend: Vulkan 1.4 -tutorial.requirements.table.linux.platform: "Linux(X11 또는 XWayland)" +tutorial.requirements.table.linux.platform: 'Linux(X11 또는 XWayland)' tutorial.requirements.table.macOS.graphicsBackend: Metal 4 tutorial.requirements.table.macOS.platform: macOS tutorial.requirements.table.windows.graphicsBackend: DirectX 12 tutorial.requirements.table.windows.platform: Windows -tutorial.requirements.title: "준비 사항" -tutorial.resize.context: "애플리케이션을 다시 빌드하고 실행합니다. 창 크기를 바꿔도 배경이 창 전체를 채워야 합니다. 새 렌더 패스를 시작할 때마다 변경된 어태치먼트 크기로 뷰포트와 시저가 설정되기 때문입니다. 렌더링 콜백은 그대로 둡니다. 이후 이 패스 안에서 삼각형을 그립니다." -tutorial.resize.description: "프레임버퍼 크기가 바뀌면 스왑 체인도 그에 맞춰야 합니다. 렌더링 콜백 뒤, {windowRun} 앞에 {framebufferResize} 콜백을 등록합니다." -tutorial.resize.details: "창의 논리적 크기 대신 픽셀 단위의 {link}을 처리합니다. 창을 최소화하면서 너비나 높이가 0이 되면 크기 변경 콜백은 스왑 체인을 그대로 둡니다. 렌더링 콜백도 어느 한쪽이 0인 동안에는 바로 반환하므로, 프레임버퍼가 다시 유효한 크기가 될 때까지 렌더링이 중단됩니다." +tutorial.requirements.title: '준비 사항' +tutorial.resize.context: '애플리케이션을 다시 빌드하고 실행합니다. 창 크기를 바꿔도 배경이 창 전체를 채워야 합니다. 새 렌더 패스를 시작할 때마다 변경된 어태치먼트 크기로 뷰포트와 시저가 설정되기 때문입니다. 렌더링 콜백은 그대로 둡니다. 이후 이 패스 안에서 삼각형을 그립니다.' +tutorial.resize.description: '프레임버퍼 크기가 바뀌면 스왑 체인도 그에 맞춰야 합니다. 렌더링 콜백 뒤, {windowRun} 앞에 {framebufferResize} 콜백을 등록합니다.' +tutorial.resize.details: '창의 논리적 크기 대신 픽셀 단위의 {link}을 처리합니다. 창을 최소화하면서 너비나 높이가 0이 되면 크기 변경 콜백은 스왑 체인을 그대로 둡니다. 렌더링 콜백도 어느 한쪽이 0인 동안에는 바로 반환하므로, 프레임버퍼가 다시 유효한 크기가 될 때까지 렌더링이 중단됩니다.' tutorial.resize.details.link: 프레임버퍼 크기 변경 -tutorial.resize.guidance: "렌더링 콜백은 제출한 프레임이 끝날 때까지 기다린 뒤 {present}를 호출합니다. 따라서 크기 변경 콜백은 이전 프레임의 작업을 방해하지 않고 스왑 체인 이미지를 교체할 수 있습니다. 작업 완료와 리소스 수명의 관계는 {link} 문서에서 자세히 설명합니다." +tutorial.resize.guidance: '렌더링 콜백은 제출한 프레임이 끝날 때까지 기다린 뒤 {present}를 호출합니다. 따라서 크기 변경 콜백은 이전 프레임의 작업을 방해하지 않고 스왑 체인 이미지를 교체할 수 있습니다. 작업 완료와 리소스 수명의 관계는 {link} 문서에서 자세히 설명합니다.' tutorial.resize.guidance.link: 동기화 -tutorial.resize.title: "크기 변경" -tutorial.shaders.compilation.context: "{appContextBaseDirectory}를 사용하면 애플리케이션 출력 디렉터리에 복사한 셰이더를 불러옵니다. 다른 작업 디렉터리에서 애플리케이션을 실행하더라도 셰이더를 찾는 위치는 바뀌지 않습니다." -tutorial.shaders.compilation.description: "{triangleSlang}의 파일 속성에서 {emphasis}를 {detail}로 설정합니다. 빌드하면 셰이더가 실행 파일 옆으로 복사됩니다." +tutorial.resize.title: '크기 변경' +tutorial.shaders.compilation.context: '{appContextBaseDirectory}를 사용하면 애플리케이션 출력 디렉터리에 복사한 셰이더를 불러옵니다. 다른 작업 디렉터리에서 애플리케이션을 실행하더라도 셰이더를 찾는 위치는 바뀌지 않습니다.' +tutorial.shaders.compilation.description: '{triangleSlang}의 파일 속성에서 {emphasis}를 {detail}로 설정합니다. 빌드하면 셰이더가 실행 파일 옆으로 복사됩니다.' tutorial.shaders.compilation.description.detail: 변경된 내용만 복사 tutorial.shaders.compilation.description.emphasis: 출력 디렉터리에 복사 -tutorial.shaders.compilation.details: "{programCs}로 돌아와 정점 업로드 뒤, 렌더 콜백 앞에 셰이더 초기화를 추가합니다." -tutorial.shaders.compilation.guidance: "{zenithCompiler}는 {contextGraphicsApi}에 맞게 소스를 컴파일하고, {createShader}는 컴파일 결과의 설명으로 셰이더 객체를 만듭니다. 진입점 이름 {vSMain}과 {fSMain}은 Slang 파일에 정의한 두 함수를 선택합니다." -tutorial.shaders.compilation.title: "셰이더 컴파일" -tutorial.shaders.context: "{fSInput}은 두 셰이더 단계를 연결합니다. 정점 셰이더는 {sVPOSITION}에 클립 공간 위치를 기록하며, GPU는 이 위치를 이용해 삼각형에서 보이는 부분을 결정합니다. {cOLOR0} 필드는 정점 색상을 전달합니다. 이 색상은 삼각형 내부에서 보간된 뒤 프래그먼트 셰이더에 전달되므로 두 단계의 필드 형식과 시맨틱이 일치해야 합니다." -tutorial.shaders.description: "셰이더는 GPU에서 실행하는 프로그램입니다. 정점 셰이더는 각 정점의 위치를 정하고, 프래그먼트 셰이더는 이미지에서 도형이 덮는 각 위치의 색상을 정합니다. 두 단계를 하나의 Slang 파일에 작성하되, 실행을 시작하는 함수인 진입점은 단계별로 따로 둡니다." -tutorial.shaders.details: "{triangleSlang}을 만들고 다음 입력·출력 구조체를 작성합니다." -tutorial.shaders.fragment.description: "같은 파일에 프래그먼트 진입점을 추가합니다." -tutorial.shaders.fragment.details: "래스터화는 삼각형이 이미지의 어느 위치를 덮는지 결정하고 해당 위치에 프래그먼트를 생성합니다. 각 프래그먼트는 세 정점의 색상으로부터 보간된 색상을 받습니다. {fSMain}은 이 색상을 반환하고, {sVTARGET}은 결과를 첫 번째 색상 어태치먼트로 보냅니다." -tutorial.shaders.fragment.title: "프래그먼트 셰이더" -tutorial.shaders.guidance: "{vSInput}은 정점 셰이더의 입력을 정의합니다. {pOSITION0}과 {cOLOR0}이 시맨틱으로 속성을 식별하며, C# 필드 이름만으로는 이 대응 관계가 정해지지 않습니다." -tutorial.shaders.title: "셰이더 단계" -tutorial.shaders.vertex.description: "{triangleSlang}에 정점 진입점을 추가합니다." -tutorial.shaders.vertex.details: "GPU는 입력 정점마다 이 함수를 실행합니다. 함수는 네 번째 동차 좌표를 {w}로 설정하고 색상을 그대로 전달합니다. 정점 처리 후 위치를 w로 나누는데, 여기서는 1이므로 x, y, z가 그대로 유지되어 정규화 장치 좌표로 해석됩니다." -tutorial.shaders.vertex.title: "정점 셰이더" -tutorial.surface.description: "네이티브 표시 대상을 {emphasis}에 지정합니다." -tutorial.surface.description.emphasis: "{windowCenter} 뒤, {windowRun} 앞" -tutorial.surface.details: "프레임버퍼는 창에 표시할 픽셀 이미지입니다. {surface}는 네이티브 표시 대상과 크기를 설명하고 {framebufferSize}는 픽셀 단위 크기를 제공합니다. 화면 배율에 따라 창의 논리 크기와 다를 수 있습니다." -tutorial.surface.guidance: "서피스는 백엔드가 요구하는 네이티브 핸들을 제공합니다. Windows에서는 Win32 창, Linux에서는 X11 디스플레이와 창, macOS에서는 연결한 Metal 레이어를 사용합니다." -tutorial.surface.title: "네이티브 서피스" -tutorial.swapChain.context: "스왑 체인은 컨텍스트와 창 모두에 의존합니다. {programCs} 끝의 {windowDispose}를 다음 해제 순서로 바꿉니다." -tutorial.swapChain.description: "서피스 설명 바로 다음에 스왑 체인을 생성합니다." -tutorial.swapChain.details: "{swapChain}은 창에 표시할 이미지를 관리합니다. {drawable}은 현재 이미지를 API의 이미지 리소스인 {texture}로 제공합니다. 렌더링 후 {present}가 이미지 표시를 요청하고 다음 출력 텍스처로 넘어갑니다." -tutorial.swapChain.guidance: "{b8G8R8A8UNorm}은 파랑, 초록, 빨강, 알파 순서로 8비트 채널 네 개를 저장합니다. {uNorm}은 정수 0–255를 0–1에 대응시킵니다. 셰이더 출력은 논리적인 RGBA 값이며, 포맷은 메모리에 저장하는 방식을 정합니다. 파이프라인의 색상 포맷은 {swapChainDescFormat}을 사용해 어태치먼트와 맞춥니다." -tutorial.swapChain.title: "스왑 체인" +tutorial.shaders.compilation.details: '{programCs}로 돌아와 정점 업로드 뒤, 렌더 콜백 앞에 셰이더 초기화를 추가합니다.' +tutorial.shaders.compilation.guidance: '{zenithCompiler}는 {contextGraphicsApi}에 맞게 소스를 컴파일하고, {createShader}는 컴파일 결과의 설명으로 셰이더 객체를 만듭니다. 진입점 이름 {vSMain}과 {fSMain}은 Slang 파일에 정의한 두 함수를 선택합니다.' +tutorial.shaders.compilation.title: '셰이더 컴파일' +tutorial.shaders.context: '{fSInput}은 두 셰이더 단계를 연결합니다. 정점 셰이더는 {sVPOSITION}에 클립 공간 위치를 기록하며, GPU는 이 위치를 이용해 삼각형에서 보이는 부분을 결정합니다. {cOLOR0} 필드는 정점 색상을 전달합니다. 이 색상은 삼각형 내부에서 보간된 뒤 프래그먼트 셰이더에 전달되므로 두 단계의 필드 형식과 시맨틱이 일치해야 합니다.' +tutorial.shaders.description: '셰이더는 GPU에서 실행하는 프로그램입니다. 정점 셰이더는 각 정점의 위치를 정하고, 프래그먼트 셰이더는 이미지에서 도형이 덮는 각 위치의 색상을 정합니다. 두 단계를 하나의 Slang 파일에 작성하되, 실행을 시작하는 함수인 진입점은 단계별로 따로 둡니다.' +tutorial.shaders.details: '{triangleSlang}을 만들고 다음 입력·출력 구조체를 작성합니다.' +tutorial.shaders.fragment.description: '같은 파일에 프래그먼트 진입점을 추가합니다.' +tutorial.shaders.fragment.details: '래스터화는 삼각형이 이미지의 어느 위치를 덮는지 결정하고 해당 위치에 프래그먼트를 생성합니다. 각 프래그먼트는 세 정점의 색상으로부터 보간된 색상을 받습니다. {fSMain}은 이 색상을 반환하고, {sVTARGET}은 결과를 첫 번째 색상 어태치먼트로 보냅니다.' +tutorial.shaders.fragment.title: '프래그먼트 셰이더' +tutorial.shaders.guidance: '{vSInput}은 정점 셰이더의 입력을 정의합니다. {pOSITION0}과 {cOLOR0}이 시맨틱으로 속성을 식별하며, C# 필드 이름만으로는 이 대응 관계가 정해지지 않습니다.' +tutorial.shaders.title: '셰이더 단계' +tutorial.shaders.vertex.description: '{triangleSlang}에 정점 진입점을 추가합니다.' +tutorial.shaders.vertex.details: 'GPU는 입력 정점마다 이 함수를 실행합니다. 함수는 네 번째 동차 좌표를 {w}로 설정하고 색상을 그대로 전달합니다. 정점 처리 후 위치를 w로 나누는데, 여기서는 1이므로 x, y, z가 그대로 유지되어 정규화 장치 좌표로 해석됩니다.' +tutorial.shaders.vertex.title: '정점 셰이더' +tutorial.surface.description: '네이티브 표시 대상을 {emphasis}에 지정합니다.' +tutorial.surface.description.emphasis: '{windowCenter} 뒤, {windowRun} 앞' +tutorial.surface.details: '프레임버퍼는 창에 표시할 픽셀 이미지입니다. {surface}는 네이티브 표시 대상과 크기를 설명하고 {framebufferSize}는 픽셀 단위 크기를 제공합니다. 화면 배율에 따라 창의 논리 크기와 다를 수 있습니다.' +tutorial.surface.guidance: '서피스는 백엔드가 요구하는 네이티브 핸들을 제공합니다. Windows에서는 Win32 창, Linux에서는 X11 디스플레이와 창, macOS에서는 연결한 Metal 레이어를 사용합니다.' +tutorial.surface.title: '네이티브 서피스' +tutorial.swapChain.context: '스왑 체인은 컨텍스트와 창 모두에 의존합니다. {programCs} 끝의 {windowDispose}를 다음 해제 순서로 바꿉니다.' +tutorial.swapChain.description: '서피스 설명 바로 다음에 스왑 체인을 생성합니다.' +tutorial.swapChain.details: '{swapChain}은 창에 표시할 이미지를 관리합니다. {drawable}은 현재 이미지를 API의 이미지 리소스인 {texture}로 제공합니다. 렌더링 후 {present}가 이미지 표시를 요청하고 다음 출력 텍스처로 넘어갑니다.' +tutorial.swapChain.guidance: '{b8G8R8A8UNorm}은 파랑, 초록, 빨강, 알파 순서로 8비트 채널 네 개를 저장합니다. {uNorm}은 정수 0–255를 0–1에 대응시킵니다. 셰이더 출력은 논리적인 RGBA 값이며, 포맷은 메모리에 저장하는 방식을 정합니다. 파이프라인의 색상 포맷은 {swapChainDescFormat}을 사용해 어태치먼트와 맞춥니다.' +tutorial.swapChain.title: '스왑 체인' tutorial.title: 첫 번째 삼각형 -tutorial.troubleshooting.description: "콘솔 진단과 세 단계의 결과를 이용해 문제가 생긴 지점을 찾습니다." -tutorial.troubleshooting.details: "{link}와 {detail}에서 정점 데이터, 입력 레이아웃, 그리기를 확인할 수 있습니다. 예제는 창과 제출을 공통 호스트로 분리하지만, 이 튜토리얼은 전체 흐름을 {programCs}에 둡니다. {context}에서는 인덱스 그리기, 변환, 깊이 테스트를 소개합니다." +tutorial.troubleshooting.description: '콘솔 진단과 세 단계의 결과를 이용해 문제가 생긴 지점을 찾습니다.' +tutorial.troubleshooting.details: '{link}와 {detail}에서 정점 데이터, 입력 레이아웃, 그리기를 확인할 수 있습니다. 예제는 창과 제출을 공통 호스트로 분리하지만, 이 튜토리얼은 전체 흐름을 {programCs}에 둡니다. {context}에서는 인덱스 그리기, 변환, 깊이 테스트를 소개합니다.' tutorial.troubleshooting.details.context: 회전하는 큐브 tutorial.troubleshooting.details.detail: Slang 셰이더 -tutorial.troubleshooting.details.link: "예제 렌더러" +tutorial.troubleshooting.details.link: '예제 렌더러' tutorial.troubleshooting.table.backend.check: 선택한 백엔드가 장치 및 설치된 그래픽 드라이버에서 지원되는지 확인합니다. tutorial.troubleshooting.table.backend.symptom: 백엔드 생성 실패 -tutorial.troubleshooting.table.drawing.check: "업로드 크기, 입력 레이아웃, 파이프라인 선택 및 렌더 패스 내부의 그리기 명령 배치를 확인합니다." +tutorial.troubleshooting.table.drawing.check: '업로드 크기, 입력 레이아웃, 파이프라인 선택 및 렌더 패스 내부의 그리기 명령 배치를 확인합니다.' tutorial.troubleshooting.table.drawing.symptom: 배경은 나타나지만 삼각형은 나타나지 않음 tutorial.troubleshooting.table.headings.check: 확인 사항 tutorial.troubleshooting.table.headings.symptom: 증상 -tutorial.troubleshooting.table.input.check: "스트라이드가 28바이트이고 위치와 색상의 오프셋이 각각 0과 12바이트인지 확인합니다." +tutorial.troubleshooting.table.input.check: '스트라이드가 28바이트이고 위치와 색상의 오프셋이 각각 0과 12바이트인지 확인합니다.' tutorial.troubleshooting.table.input.symptom: 정점 위치 또는 색상이 손상됨 tutorial.troubleshooting.table.shaders.check: 복사된 {triangleSlang}, 진입점 철자 및 컴파일러에서 보고된 진단을 확인합니다. -tutorial.troubleshooting.table.shaders.symptom: "배경색은 표시되지만 셰이더를 불러오지 못함" -tutorial.troubleshooting.table.window.check: ".NET 프로젝트가 빌드되고 창 전용 단계가 데스크톱 세션에서 실행되는지 확인합니다. Linux의 경우 X11 또는 XWayland를 사용할 수 있는지 확인합니다." -tutorial.troubleshooting.table.window.symptom: "창이 열리지 않음" -tutorial.troubleshooting.title: "문제 진단" -tutorial.window.description: "{cocoaHelperCs}를 다운로드해 프로젝트에 추가합니다. 이 보조 클래스는 macOS 창에 Metal 레이어를 연결합니다." -tutorial.window.details: "자동 생성된 {programCs} 내용을 다음 코드로 바꿉니다. 최상위 문을 사용하므로 {main} 메서드를 직접 작성하지 않아도 위에서 아래로 실행됩니다. 이후 각 절에서 새 코드를 넣을 위치를 안내합니다." -tutorial.window.guidance: "{graphicsAPINone}은 그래픽스 컨텍스트 생성을 Zenith.NET에 맡깁니다. {initialize}는 네이티브 창을 만들고 창 시스템 핸들을 사용할 수 있게 합니다. {center}는 창을 화면 가운데 놓습니다. {run}이 창을 닫을 때까지 이벤트를 처리한 뒤 {dispose}가 실행되어 창을 해제합니다." -tutorial.window.notes: "애플리케이션을 빌드하고 실행합니다. 창을 열고 닫을 수 있는지, 이동하거나 크기를 바꿀 수 있는지 확인합니다. 아직 렌더링 명령을 제출하지 않아 창 내부의 내용은 정의되지 않았습니다. 다음 단계로 넘어가기 전에 창을 닫습니다." -tutorial.window.title: "창 생성" +tutorial.troubleshooting.table.shaders.symptom: '배경색은 표시되지만 셰이더를 불러오지 못함' +tutorial.troubleshooting.table.window.check: '.NET 프로젝트가 빌드되고 창 전용 단계가 데스크톱 세션에서 실행되는지 확인합니다. Linux의 경우 X11 또는 XWayland를 사용할 수 있는지 확인합니다.' +tutorial.troubleshooting.table.window.symptom: '창이 열리지 않음' +tutorial.troubleshooting.title: '문제 진단' +tutorial.window.description: '{cocoaHelperCs}를 다운로드해 프로젝트에 추가합니다. 이 보조 클래스는 macOS 창에 Metal 레이어를 연결합니다.' +tutorial.window.details: '자동 생성된 {programCs} 내용을 다음 코드로 바꿉니다. 최상위 문을 사용하므로 {main} 메서드를 직접 작성하지 않아도 위에서 아래로 실행됩니다. 이후 각 절에서 새 코드를 넣을 위치를 안내합니다.' +tutorial.window.guidance: '{graphicsAPINone}은 그래픽스 컨텍스트 생성을 Zenith.NET에 맡깁니다. {initialize}는 네이티브 창을 만들고 창 시스템 핸들을 사용할 수 있게 합니다. {center}는 창을 화면 가운데 놓습니다. {run}이 창을 닫을 때까지 이벤트를 처리한 뒤 {dispose}가 실행되어 창을 해제합니다.' +tutorial.window.notes: '애플리케이션을 빌드하고 실행합니다. 창을 열고 닫을 수 있는지, 이동하거나 크기를 바꿀 수 있는지 확인합니다. 아직 렌더링 명령을 제출하지 않아 창 내부의 내용은 정의되지 않았습니다. 다음 단계로 넘어가기 전에 창을 닫습니다.' +tutorial.window.title: '창 생성' ui.action.copy: 복사 ui.action.navigate: 탐색 ui.action.open: 열기 @@ -530,7 +530,7 @@ ui.content.tutorial: 튜토리얼 ui.contents.close: 목차 닫기 ui.contents.open: 목차 열기 ui.contents.title: 목차 -ui.footer.caption: ".NET을 위한 현대적인 RHI" +ui.footer.caption: '.NET을 위한 현대적인 RHI' ui.footer.label: 바닥글 ui.language.label: 언어 ui.language.unavailable: 번역되지 않음 @@ -552,7 +552,7 @@ ui.outline.title: 이 페이지의 내용 ui.reference.assembly: 어셈블리 ui.reference.classes: 클래스 ui.reference.constructors: 생성자 -ui.reference.declaration: "C# 형식 선언" +ui.reference.declaration: 'C# 형식 선언' ui.reference.delegates: 대리자 ui.reference.derived: 파생 형식 ui.reference.enums: 열거형 @@ -569,7 +569,7 @@ ui.reference.interfaces: 인터페이스 ui.reference.metadata: 형식 메타데이터 ui.reference.methods: 메서드 ui.reference.namespace: 네임스페이스 -ui.reference.open: "{name} 참조 열기" +ui.reference.open: '{name} 참조 열기' ui.reference.operators: 연산자 ui.reference.parameters: 매개 변수 ui.reference.properties: 속성 @@ -588,6 +588,6 @@ ui.search.loading: 검색 로드 중… ui.search.more: 결과 더 보기 ui.search.pending: 검색 중… ui.search.placeholder: 무엇을 찾으시나요? -ui.search.resultCount: "결과: {count}개" +ui.search.resultCount: '결과: {count}개' ui.search.title: 문서 검색 ui.search.unavailable: 검색을 사용할 수 없습니다. 아래 페이지를 계속 열 수 있습니다. diff --git a/documents/locales/ko-KR/translation.md b/documents/locales/ko-KR/translation.md index 4c550407..d1fd58e3 100644 --- a/documents/locales/ko-KR/translation.md +++ b/documents/locales/ko-KR/translation.md @@ -2,7 +2,7 @@ ## 리소스와 구조 -[영문 리소스 사전](../en-US/strings.yml)을 유일한 원문으로 사용합니다. 프로젝트 규칙은 [문서 유지 관리 지침](../../authoring.md)을 참고합니다. 새 번역을 시작할 때는 영문 파일 전체를 이 디렉터리의 `strings.yml`로 복사하고, 첫 줄의 `### YamlMime:Resources`와 UTF-8 인코딩을 유지합니다. 이후에는 영문 변경 사항을 기존 번역에 반영하며, 번역 파일 전체를 원문으로 덮어쓰지 않습니다. 이 `translation.md`는 번역 후에도 보존하며 사이트에는 게시하지 않습니다. +[영문 리소스 사전](../en-US/strings.yml)을 유일한 원문으로 사용합니다. 프로젝트 규칙은 [문서 유지 관리 지침](../../maintenance.md)을 참고합니다. 새 번역을 시작할 때는 영문 파일 전체를 이 디렉터리의 `strings.yml`로 복사하고, 첫 줄의 `### YamlMime:Resources`와 UTF-8 인코딩을 유지합니다. 이후에는 영문 변경 사항을 기존 번역에 반영하며, 번역 파일 전체를 원문으로 덮어쓰지 않습니다. 이 `translation.md`는 번역 후에도 보존하며 사이트에는 게시하지 않습니다. 탐색 구조, 장 순서, 앵커, 링크, 서식, 코드 및 이미지는 `locales/` 밖에서 공통으로 관리합니다. 이 디렉터리에 문서, TOC, 템플릿, 스크립트 또는 설정을 추가하지 않습니다. @@ -65,21 +65,21 @@ docfx serve documents/_site --hostname 127.0.0.1 --port 8080 ## 용어 -| 영어 | 사용할 표현 | -| --- | --- | -| API / GPU / RHI | 약어를 유지하고 원문에 따라 설명 | -| barrier | 배리어 | -| buffer | 버퍼. `Buffer`는 유지 | -| command buffer | 명령 버퍼 | -| command queue | 명령 큐 | -| drawable | 현재 프레임의 출력 텍스처. `Drawable`은 유지하며 항상 스왑 체인 이미지로 해석하지 않음 | -| graphics context | 그래픽스 컨텍스트 | -| pipeline | 파이프라인 | -| readback | 리드백 | -| render pass | 렌더 패스 | -| resource | 리소스 | -| shader | 셰이더 | -| swap chain | 스왑 체인 | -| texture | 텍스처 | -| timeline | 타임라인 | -| upload | 업로드 | +| 영어 | 사용할 표현 | +| ---------------- | -------------------------------------------------------------------------------------- | +| API / GPU / RHI | 약어를 유지하고 원문에 따라 설명 | +| barrier | 배리어 | +| buffer | 버퍼. `Buffer`는 유지 | +| command buffer | 명령 버퍼 | +| command queue | 명령 큐 | +| drawable | 현재 프레임의 출력 텍스처. `Drawable`은 유지하며 항상 스왑 체인 이미지로 해석하지 않음 | +| graphics context | 그래픽스 컨텍스트 | +| pipeline | 파이프라인 | +| readback | 리드백 | +| render pass | 렌더 패스 | +| resource | 리소스 | +| shader | 셰이더 | +| swap chain | 스왑 체인 | +| texture | 텍스처 | +| timeline | 타임라인 | +| upload | 업로드 | diff --git a/documents/locales/pt-BR/strings.yml b/documents/locales/pt-BR/strings.yml index d519decb..065cd8fa 100644 --- a/documents/locales/pt-BR/strings.yml +++ b/documents/locales/pt-BR/strings.yml @@ -1,593 +1,593 @@ ### YamlMime:Resources -concepts.execution.context.description: "Um {graphicsContext} conecta a aplicação a um dispositivo GPU por meio de um backend específico e fornece suas filas gráfica, de computação e de transferência. Recursos usados em conjunto devem pertencer ao mesmo contexto; buffers, texturas, shaders, pipelines e seus identificadores não podem ser vinculados entre contextos diferentes." -concepts.execution.context.details: "{capabilities} informa o nome do dispositivo e as funcionalidades disponíveis. Consulte {rayTracingSupported} e {meshShadingSupported} antes de criar os recursos necessários a essas operações. Os exemplos de {link} e {detail} fazem essas verificações durante a inicialização." -concepts.execution.context.details.detail: "sombreamento de malha" -concepts.execution.context.details.link: "traçado de raios" -concepts.execution.context.title: "Contexto gráfico" -concepts.execution.description: "O trabalho da GPU é preparado na CPU: a aplicação cria recursos, registra comandos que os utilizam e envia esses comandos a uma fila. Após o envio, a CPU pode continuar enquanto a GPU executa o trabalho. Os recursos precisam permanecer disponíveis até o fim dessa execução." -concepts.execution.ownership.description: "A propriedade define quem libera um objeto; a conclusão do trabalho na GPU determina quando isso pode ocorrer. Chamar {dispose} libera os recursos nativos mesmo que ainda existam referências C# ao objeto. Enviar comandos não transfere à fila a propriedade dos recursos utilizados." -concepts.execution.ownership.details: "Ao encerrar a aplicação, pare de enviar trabalho e espere o último uso dos recursos em cada fila envolvida. Depois, libere os recursos da aplicação e o contexto. O contexto libera suas filas e estruturas auxiliares internas, portanto essa última etapa deve ocorrer após a conclusão de todo o trabalho da aplicação." -concepts.execution.ownership.guidance: "Durante a renderização, acompanhe a conclusão do trabalho que utiliza dados a serem sobrescritos ou recursos a serem substituídos. Espere esses usos terminarem antes de modificar ou liberar o armazenamento afetado. {link} explica como esse modelo de tempo de vida se aplica às visualizações e aos recursos que as sustentam." -concepts.execution.ownership.guidance.link: "Gerenciamento de recursos" -concepts.execution.ownership.table.applicationResources.object: "Recursos criados pela aplicação" -concepts.execution.ownership.table.applicationResources.ownership: "A aplicação os libera após o último uso na GPU." -concepts.execution.ownership.table.commandBuffers.object: "Buffers de comandos emprestados" -concepts.execution.ownership.table.commandBuffers.ownership: "A fila os gerencia e recicla." -concepts.execution.ownership.table.headings.object: "Objeto" -concepts.execution.ownership.table.headings.ownership: "Responsabilidade pela liberação" -concepts.execution.ownership.table.queues.object: "Filas do contexto e suas linhas do tempo" -concepts.execution.ownership.table.queues.ownership: "O contexto e as filas as gerenciam." -concepts.execution.ownership.table.swapChainDrawable.ownership: "A cadeia de troca o gerencia." -concepts.execution.ownership.title: "Responsabilidade e tempo de vida" -concepts.execution.pipelines.description: "Um pipeline gráfico define os shaders, a disposição dos atributos de vértice, a montagem de primitivas, os formatos dos anexos e o estado usado nas operações de desenho. Selecione o pipeline antes de vincular dados de vértices, índices ou constantes. Os formatos dos anexos e a quantidade de amostras devem corresponder aos da passagem de renderização." -concepts.execution.pipelines.details: "Um pipeline de computação seleciona o ponto de entrada do shader executado por um despacho. Vincule o pipeline e suas constantes antes do despacho, fora de uma passagem de renderização gráfica." -concepts.execution.pipelines.guidance: "O {link} apresenta a sequência gráfica. O {detail} acrescenta um despacho de computação antes da passagem que exibe seu resultado." -concepts.execution.pipelines.guidance.detail: "exemplo de computação" -concepts.execution.pipelines.guidance.link: "callback de renderização do triângulo" -concepts.execution.pipelines.title: "Estado do pipeline" -concepts.execution.queues.description: "A {graphicsQueue} costuma ser o ponto de partida para um quadro com desenho, computação e cópias. Manter operações dependentes na mesma fila simplifica a ordenação." -concepts.execution.queues.details: "Filas distintas permitem enviar cargas de trabalho independentes separadamente, mas nem sempre correspondem a mecanismos de hardware independentes. Use filas adicionais quando houver benefício em sobrepor a execução. Se uma fila utilizar dados produzidos por outra, estabeleça uma dependência explícita entre seus envios." -concepts.execution.queues.guidance: "Dentro de uma fila, operações dependentes também podem precisar de barreiras ou transições de textura para que os acessos posteriores vejam as escritas anteriores. Essas dependências de memória são diferentes da ordem de envio; {link} explica como expressá-las." -concepts.execution.queues.guidance.link: "Sincronização" -concepts.execution.queues.table.computeQueue.workToRecord: "Despachos de computação e trabalho de transferência compatível, sem passagens de renderização gráfica." -concepts.execution.queues.table.graphicsQueue.workToRecord: "Passagens de renderização, desenho, computação e transferências." -concepts.execution.queues.table.headings.queue: "Fila" -concepts.execution.queues.table.headings.workToRecord: "Operações aceitas" -concepts.execution.queues.table.transferQueue.workToRecord: "Uploads, downloads e cópias, sem desenho ou despachos de computação." -concepts.execution.queues.title: "Seleção de filas" -concepts.execution.recording.context: "A fila recupera os buffers de comandos concluídos para reutilizá-los. Obtenha um com {queueCommandBuffer} para cada registro de comandos, use uma thread por vez e envie-o uma única vez. Após o envio, deixe seu gerenciamento com a fila: não o modifique, envie novamente ou libere." -concepts.execution.recording.description: "{queueCommandBuffer} retorna um {commandBuffer} já em gravação. Registre as operações e suas dependências e chame {submit} uma vez. O envio encerra a gravação e retorna um {timelineValue}, que identifica o ponto de conclusão naquela fila." -concepts.execution.recording.details: "Após registrar o quadro em {commandBuffer}, o tutorial do triângulo envia os comandos e aguarda a conclusão:" -concepts.execution.recording.guidance: "O registro monta a sequência de comandos; {submit} agenda sua execução. A chamada seguinte a {wait} bloqueia a thread da CPU até esse envio terminar. Isso facilita a compreensão do loop do tutorial, pois cada quadro termina antes do início do próximo." -concepts.execution.recording.title: "Gravação e envio" -concepts.execution.title: "Modelo de execução" -concepts.platforms.description: "A apresentação pode ser gerenciada pela aplicação ou por um controle de interface. Essa escolha define quem obtém a textura de saída do quadro, registra e envia os comandos e apresenta o resultado. Essa textura de saída é o drawable." -concepts.platforms.frame.context: "Registre as vinculações de pipeline e os comandos de desenho dentro da passagem e encerre-a antes de o manipulador retornar. O controle envia os comandos e apresenta o resultado. O manipulador não deve enviar o buffer de comandos nem liberar qualquer um dos objetos recebidos. Se alterar o layout da textura de saída, restaure {colorAttachment} antes de retornar para que o controle realize a transição final." -concepts.platforms.frame.description: "Os controles implementam {iZenithView}. A aplicação atribui {graphicsContext}, atualiza a cena em {updateRequested} e registra comandos em {renderRequested} usando o {renderEventArgs} recebido." -concepts.platforms.frame.details: "A cada quadro, o controle obtém uma textura de saída e um buffer de comandos, faz a transição da textura para {colorAttachment} e chama os manipuladores de atualização e renderização. Depois, envia o trabalho registrado e apresenta a imagem pelo mecanismo do framework." -concepts.platforms.frame.guidance: "Adicione {usingZenithNET} ao arquivo. Para uma instância de {iZenithView} chamada {view}, já inicializada e com um contexto gráfico atribuído, registre este manipulador para limpar sua textura de saída:" -concepts.platforms.frame.notes: "A transição inicial usa {undefined}, que permite descartar o conteúdo anterior da imagem. Desenhe ou limpe a imagem inteira a cada quadro. Mantenha resultados acumulados ou em cache em uma textura da aplicação e depois a desenhe na textura de saída do controle." -concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat} fornece o formato de cor padrão dessas integrações." -concepts.platforms.frame.title: "Renderização em controles de interface" -concepts.platforms.integration.context: "WinForms, WPF e a integração Windows do WinUI executam no Windows. Para MAUI, instale a carga de trabalho da plataforma de destino e registre o manipulador do controle com {useZenithView}, como mostra {extensionsCs}." -concepts.platforms.integration.description: "A interface de eventos é comum, mas o mecanismo de apresentação depende do framework:" -concepts.platforms.integration.details: "Essas implementações diferem na forma de levar a imagem da GPU à interface. A leitura como bitmap copia os pixels para a memória da CPU antes da exibição. A interoperabilidade por texturas compartilhadas evita essa cópia, mas ainda pode exigir cópias na GPU e sincronização. Ao escolher uma integração, considere esse caminho de apresentação além do evento comum {renderRequested}." -concepts.platforms.integration.guidance: "Adicione pelo NuGet o pacote de integração correspondente ao seu framework de interface. Para Avalonia, use {avaloniaPackage}." -concepts.platforms.integration.table.avalonia.integration: "Avalonia" -concepts.platforms.integration.table.avalonia.presentation: "Renderiza em uma textura e copia os pixels para a memória da CPU em {writeableBitmap}. Implementação: {zenithViewCs} e {surfaceCs}." -concepts.platforms.integration.table.headings.integration: "Integração" -concepts.platforms.integration.table.headings.presentation: "Mecanismo de apresentação" -concepts.platforms.integration.table.maui.integration: ".NET MAUI" -concepts.platforms.integration.table.maui.presentation: "Usa superfícies nativas no Android, iOS e Mac Catalyst, e composição de textura compartilhada no Windows. Consulte as {link}." -concepts.platforms.integration.table.maui.presentation.link: "implementações de plataforma" -concepts.platforms.integration.table.uno.integration: "Caminho Uno" -concepts.platforms.integration.table.uno.presentation: "Copia os pixels para a memória da CPU em {writeableBitmap}. Implementação: {zenithViewUnoCs}." -concepts.platforms.integration.table.winForms.integration: "WinForms" -concepts.platforms.integration.table.winForms.presentation: "Cria uma cadeia de troca do Zenith.NET para o {hWND} do controle. Consulte {zenithViewCs}." -concepts.platforms.integration.table.winUI.integration: "WinUI no Windows" -concepts.platforms.integration.table.winUI.presentation: "Renderiza em uma textura Direct3D 11 compartilhada importada e copia o resultado para uma cadeia de troca de composição conectada a {swapChainPanel}. Consulte {zenithViewWinUICs}." -concepts.platforms.integration.table.wpf.integration: "WPF" -concepts.platforms.integration.table.wpf.presentation: "Importa uma textura Direct3D 11 compartilhada e copia seu conteúdo, por meio da interoperabilidade com Direct3D, para uma superfície exibida por {d3DImage}. Consulte {surfaceCs}." -concepts.platforms.integration.title: "Framework e apresentação" -concepts.platforms.lifecycle.context: "Ao criar anexos compatíveis, use {descWidth}, {descHeight}, {descFormat} e {descSampleCount} da textura de saída fornecida pelo evento de renderização. Essa textura informa as dimensões reais do destino; elas não devem ser deduzidas do tamanho de layout do controle nem da escala de exibição." -concepts.platforms.lifecycle.description: "A cadeia de troca usa a largura e a altura do framebuffer em pixels, que podem diferir das dimensões lógicas da janela quando há escala de exibição. Adie a renderização e o redimensionamento da cadeia enquanto alguma dimensão for zero. Obtenha {swapChainDrawable} a cada quadro: a textura pertence à cadeia de troca, que pode substituí-la após apresentar ou redimensionar." -concepts.platforms.lifecycle.details: "Quando o tamanho do framebuffer mudar, espere os usos pendentes das imagens antigas na GPU antes de chamar {swapChainResize}. Para substituir o destino nativo de apresentação, aguarde esses usos da mesma forma e passe a nova descrição da superfície e seus identificadores a {swapChainRefresh}. No encerramento, libere a cadeia de troca antes de destruir seu destino nativo." -concepts.platforms.lifecycle.guidance: "Se a aplicação tiver texturas de profundidade ou fora da tela que acompanham o tamanho da janela, recrie-as quando esse tamanho mudar e atualize as constantes que contêm seus identificadores. O pipeline pode ser reutilizado enquanto os formatos e as quantidades de amostras dos anexos continuarem correspondentes. O {link} mostra essa separação entre as texturas redimensionadas e o pipeline reutilizável." -concepts.platforms.lifecycle.guidance.link: "renderizador de cubo giratório" -concepts.platforms.lifecycle.title: "Dimensões e tempo de vida da cadeia de troca" -concepts.platforms.ownership.description: "O contexto atribuído e os recursos de renderização pertencem à aplicação; os recursos de apresentação pertencem ao controle. Quando {graphicsContext} muda na visualização, o agendador recria os recursos do controle para o novo contexto. Recrie também os pipelines, buffers e texturas da aplicação para esse contexto." -concepts.platforms.ownership.details: "Antes de substituir recursos de renderização, interrompa o processamento de quadros da visualização e espere o trabalho da GPU que os utiliza. Só então libere os recursos ou o contexto antigos. Ao remover a visualização, a aplicação continua responsável por liberar o contexto atribuído a ela." -concepts.platforms.ownership.guidance: "O componente compartilhado {frameSchedulerCs} executa os manipuladores de quadro pelo dispatcher da interface. Concentre esses manipuladores na atualização da cena e no registro de comandos: um processamento prolongado na CPU também atrasa a resposta da interface." -concepts.platforms.ownership.title: "Responsabilidades da aplicação e do controle" -concepts.platforms.surface.description: "O {link} usa Silk.NET para criar a janela e processar seus eventos. O Zenith.NET recebe os identificadores nativos e as dimensões em uma descrição {surface}, usada para criar uma {swapChain}. A aplicação continua responsável pela janela do sistema operacional." -concepts.platforms.surface.description.link: "tutorial do triângulo" -concepts.platforms.surface.details: "Os identificadores da superfície devem corresponder ao backend:" -concepts.platforms.surface.guidance: "O programa hospedeiro em {appCs} oferece suporte a Windows, macOS e X11. Sua janela Linux fornece identificadores Xlib, portanto uma sessão Wayland precisa de XWayland para executá-lo. Uma aplicação nativa de Wayland fornece os identificadores de display e superfície por meio de {surfaceWayland}." -concepts.platforms.surface.table.android.backend: "Vulkan no Android." -concepts.platforms.surface.table.apple.backend: "Metal nas plataformas Apple." -concepts.platforms.surface.table.headings.backend: "Backend e plataforma" -concepts.platforms.surface.table.headings.factory: "Fábrica de superfícies" -concepts.platforms.surface.table.headings.handles: "Identificadores fornecidos pelo programa hospedeiro" -concepts.platforms.surface.table.wayland.backend: "Vulkan com um host nativo Wayland." -concepts.platforms.surface.table.wayland.handles: "Display e superfície Wayland" -concepts.platforms.surface.table.win32.backend: "DirectX 12 ou Vulkan no Windows." -concepts.platforms.surface.table.xlib.backend: "Vulkan no Linux com X11 ou XWayland." -concepts.platforms.surface.table.xlib.handles: "Display e janela X11" -concepts.platforms.surface.title: "Superfícies nativas de apresentação" -concepts.platforms.title: "Integração de plataforma" -concepts.resources.allocation.context: "Os recursos colocados em um heap dependem de seu armazenamento durante todo o tempo de vida. Depois do último uso na GPU, libere os recursos antes de liberar o heap." -concepts.resources.allocation.description: "Use um {heap} quando a aplicação precisar gerenciar as alocações por conta própria. Um heap fornece armazenamento no qual os recursos são colocados em deslocamentos explícitos em bytes; a aplicação escolhe esses deslocamentos e acompanha as regiões ocupadas." -concepts.resources.allocation.details: "Para cada recurso, chame {contextGetSizeAndAlignment} com a descrição de buffer ou textura que será usada na criação. Reserve o tamanho retornado em um deslocamento múltiplo do alinhamento informado, dentro dos limites do heap e sem sobrepor outra alocação ainda em uso. Texturas podem incluir preenchimento específico do backend; por isso, a quantidade de pixels e os bytes por pixel não bastam para calcular o tamanho da alocação." -concepts.resources.allocation.guidance: "Um buffer colocado em um heap deve declarar a mesma residência desse heap. Para armazenar texturas, use um heap exclusivo da GPU." -concepts.resources.allocation.title: "Alocação em heaps" -concepts.resources.bufferUsages.table.constant.role: "Parâmetros de shader lidos por meio de uma vinculação de buffer de constantes." -concepts.resources.bufferUsages.table.headings.role: "Função" -concepts.resources.bufferUsages.table.headings.usage: "Uso" -concepts.resources.bufferUsages.table.index.role: "Índices usados pelo desenho indexado." -concepts.resources.bufferUsages.table.indirect.role: "Argumentos lidos por comandos de desenho ou despacho indiretos." -concepts.resources.bufferUsages.table.none.role: "Nenhum indicador de uso de buffer é declarado." -concepts.resources.bufferUsages.table.storageReadOnly.role: "Dados de buffer acessados por uma vinculação de shader somente leitura." -concepts.resources.bufferUsages.table.storageReadWrite.role: "Dados de buffer acessados por uma vinculação de shader de leitura e gravação." -concepts.resources.bufferUsages.table.transferDst.role: "Armazenamento de destino para uma cópia de GPU." -concepts.resources.bufferUsages.table.transferSrc.role: "Dados de origem para uma cópia de GPU." -concepts.resources.bufferUsages.table.vertex.role: "Atributos de vértice buscados para desenho." -concepts.resources.bufferUsages.title: "Usos de buffer" -concepts.resources.description: "A descrição de um recurso define como a aplicação pode usar seu armazenamento. Por exemplo, uma textura usada como destino de renderização, amostrada por um shader e copiada de volta à CPU precisa dos indicadores de uso das três operações. A localização da memória determina o acesso da CPU; a sincronização e o gerenciamento do tempo de vida determinam quando os dados podem ser acessados ou o armazenamento liberado." -concepts.resources.memory.context: "Nos buffers acessíveis pela CPU, {map} fornece o endereço pelo qual os dados são lidos ou escritos. Nem o mapeamento nem {unmap} esperam o trabalho da GPU: antes de ler um resultado, a aplicação precisa esperar a escrita que o produz; antes de modificar os mesmos bytes, precisa esperar os acessos pendentes da GPU." -concepts.resources.memory.description: "O campo {residency} de {bufferDesc} especifica o acesso pretendido pela CPU:" -concepts.resources.memory.details: "A residência expressa os requisitos de acesso da CPU, inclusive em sistemas em que CPU e GPU compartilham memória física. O triângulo utiliza {cpuWriteOnly} para inicializar diretamente seu pequeno buffer de vértices. Para geometrias estáticas maiores, pode ser mais adequado enviar os dados para armazenamento exclusivo da GPU." -concepts.resources.memory.guidance: "Texturas criadas diretamente pelo contexto usam armazenamento da GPU. Por isso, {textureDesc} não possui um campo de residência; a aplicação troca seus dados com a memória da CPU por meio de uploads e downloads." -concepts.resources.memory.table.cpuReadOnly.cPUAccess: "Somente leitura" -concepts.resources.memory.table.cpuReadOnly.typicalRole: "Dados produzidos pela GPU para leitura na CPU" -concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "Somente escrita" -concepts.resources.memory.table.cpuWriteOnly.typicalRole: "Dados fornecidos ou atualizados pela CPU" -concepts.resources.memory.table.gpuOnly.cPUAccess: "Nenhum" -concepts.resources.memory.table.gpuOnly.typicalRole: "Geometria estática e dados de trabalho da GPU" -concepts.resources.memory.table.headings.cPUAccess: "Acesso previsto da CPU" -concepts.resources.memory.table.headings.residency: "Residência" -concepts.resources.memory.table.headings.typicalRole: "Função típica" -concepts.resources.memory.title: "Acesso pela CPU e localização na memória" -concepts.resources.textureUsages.description: "Os indicadores de transferência descrevem se o recurso é a origem ou o destino de uma cópia na GPU. A possibilidade de acesso direto pela CPU é uma decisão separada, tomada ao escolher a localização da memória." -concepts.resources.textureUsages.details: "Os indicadores de uso declaram as funções que uma textura pode desempenhar. Alternar entre elas exige os cuidados de {link} correspondentes, e o dispositivo escolhido deve oferecer suporte a esses usos para o formato da textura." -concepts.resources.textureUsages.details.link: "layout e sincronização" -concepts.resources.textureUsages.table.colorAttachment.role: "Um anexo de cor em uma passagem de renderização." -concepts.resources.textureUsages.table.depthStencilAttachment.role: "Um anexo de profundidade e estêncil em uma passagem de renderização." -concepts.resources.textureUsages.table.headings.role: "Função" -concepts.resources.textureUsages.table.headings.usage: "Uso" -concepts.resources.textureUsages.table.none.role: "Nenhum indicador de uso de textura é declarado." -concepts.resources.textureUsages.table.sampled.role: "Dados de textura lidos por uma vinculação de textura amostrada." -concepts.resources.textureUsages.table.storage.role: "Dados de textura acessados por uma vinculação de textura de armazenamento para leituras ou gravações de shaders." -concepts.resources.textureUsages.table.transferDst.role: "Armazenamento da imagem de destino para uma cópia de GPU." -concepts.resources.textureUsages.table.transferSrc.role: "Dados da imagem de origem para uma cópia de GPU." -concepts.resources.textureUsages.title: "Usos de textura" -concepts.resources.title: "Gerenciamento de recursos" -concepts.resources.transfers.context: "Um download copia primeiro os dados da GPU para uma área interna de leitura. A biblioteca os copia para o destino de CPU fornecido quando recupera o buffer de comandos concluído. Chamar {wait} no valor de envio do download completa as duas etapas. Mantenha o destino alocado e a memória gerenciada fixada até o retorno dessa chamada." -concepts.resources.transfers.description: "Uploads copiam dados da CPU para um recurso da GPU; downloads copiam dados do recurso para a memória da CPU. Os métodos de buffers e texturas concluem essa transferência antes de retornar:" -concepts.resources.transfers.details: "Antes de chamar esses métodos, resolva os acessos conflitantes em outras filas. A espera interna do método abrange sua própria transferência; ela não estabelece uma dependência de outra fila. Nas cópias diretas por memória mapeada, cabe inteiramente a quem chama esperar os acessos conflitantes da GPU." -concepts.resources.transfers.guidance: "Para enviar transferências junto com outro trabalho da GPU, registre-as com {commandBufferUpload} ou {commandBufferDownload}. A memória de origem de um upload e a de destino de um download precisam permanecer válidas por períodos diferentes:" -concepts.resources.transfers.item: "Durante uma chamada de upload, a biblioteca copia os dados de origem para uma área temporária de transferência. A GPU lê dessa área posteriormente, portanto o ponteiro de origem da aplicação só é necessário até o retorno da chamada." -concepts.resources.transfers.notes: "Nas transferências de textura, o passo de linha é a distância em bytes entre linhas consecutivas dos dados da CPU; o passo de fatia é a distância entre fatias de profundidade consecutivas. Esses valores permitem copiar os dados entre sua organização na CPU e o armazenamento da textura na GPU. {link} explica por que concluir a cópia na GPU e entregar os dados ao destino de um download são etapas distintas." -concepts.resources.transfers.notes.link: "Sincronização" -concepts.resources.transfers.table.bufferDownload.transfer: "Para {cpuReadOnly}, copia diretamente da memória mapeada. Nos demais casos, envia o download à fila de transferência e espera sua conclusão." -concepts.resources.transfers.table.bufferUpload.transfer: "Para {cpuWriteOnly}, copia diretamente para a memória mapeada. Nos demais casos, envia o upload à fila de transferência e espera sua conclusão." -concepts.resources.transfers.table.headings.method: "Método" -concepts.resources.transfers.table.headings.transfer: "Comportamento da transferência" -concepts.resources.transfers.table.textureTransfers.method: "{textureUpload} / {textureDownload}" -concepts.resources.transfers.table.textureTransfers.transfer: "Envia a cópia e as transições de textura à fila gráfica e espera sua conclusão. O sub-recurso selecionado fica no layout final solicitado." -concepts.resources.transfers.title: "Transferências imediatas e registradas" -concepts.resources.usages.description: "{bufferUsages} e {textureUsages} são enumerações de indicadores que declaram os usos de um recurso. Seus valores são atribuídos a {bufferDescUsages} e {textureDescUsages}, respectivamente. Para vários usos, combine os membros necessários com {value}." -concepts.resources.usages.title: "Usos de recursos" -concepts.resources.views.description: "Uma {bufferView} descreve uma região de um buffer e a interpretação de seus dados. Uma {textureView} seleciona um intervalo de sub-recursos, com um tipo e formato de textura compatíveis. Ambas se referem ao armazenamento existente, com os usos declarados na criação. Os intervalos das visualizações descrevem o acesso, mas não garantem uma verificação de limites uniforme nos shaders de todos os backends." -concepts.resources.views.details: "O identificador do próprio recurso fornece sua visualização padrão. Crie uma visualização separada para escolher outra região ou uma interpretação compatível diferente. Mantenha vivos tanto a visualização quanto o recurso que a sustenta até a GPU terminar de utilizá-los; um identificador não mantém nenhum desses objetos vivo. Ao substituir qualquer um deles, atualize as constantes que contêm o {link} anterior." -concepts.resources.views.details.link: "identificador de recurso" -concepts.resources.views.title: "Visualizações e recursos subjacentes" -concepts.shaders.binding.context: "O exemplo de computação atribui {inputTextureSampledHandle} a {input} e {outputTextureStorageHandle} a {output}. Em Slang, o parâmetro de tipo de {descriptorHandle} define como o shader acessa cada recurso:" -concepts.shaders.binding.description: "{setConstantBuffer} seleciona um buffer existente e o deslocamento de byte a partir do qual o pipeline atual lê suas constantes. Envie os parâmetros para esse armazenamento antes de serem usados pelo shader. Se um trabalho anterior da GPU ainda estiver lendo os mesmos bytes, espere sua conclusão antes de atualizá-los." -concepts.shaders.binding.details: "Com o buffer de comandos, o pipeline de computação, o buffer de constantes preenchido e as quantidades de grupos de threads prontos, registre o despacho nesta ordem. Selecione primeiro o pipeline, pois a vinculação do buffer de constantes se aplica a ele:" -concepts.shaders.binding.guidance: "Aqui, {commandBuffer} registra um despacho com {computePipeline} e os parâmetros armazenados em {constantBuffer}. O buffer precisa do uso {bufferUsagesConstant}, e o deslocamento 0 seleciona seu início. Se vários registros de constantes compartilharem um buffer, o deslocamento inicial de cada registro também deve atender ao alinhamento de vinculação do backend, independentemente do layout de seus campos internos." -concepts.shaders.binding.notes: "{resourceHandle} contém dois campos de 32 bits cuja interpretação depende do backend. Seus valores são válidos apenas no contexto em que o recurso foi criado." -concepts.shaders.binding.reference: "Mantenha o recurso e a visualização usada para obter seu identificador até o último acesso do shader. A substituição exige atualizar constantes que ainda contenham o identificador antigo. {link} apresenta as regras de responsabilidade." -concepts.shaders.binding.reference.link: "Gerenciamento de recursos" -concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: "Leitura de elementos estruturados do tipo {t} do shader" -concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: "Leitura e escrita de elementos estruturados do tipo {t} do shader" -concepts.shaders.binding.table.headings.access: "Acesso pretendido" -concepts.shaders.binding.table.headings.cHandle: "Identificador C#" -concepts.shaders.binding.table.headings.slangFieldType: "Tipo de campo Slang" -concepts.shaders.binding.table.samplerHandle.access: "Estado de amostragem de texturas" -concepts.shaders.binding.table.textureSampledHandle.access: "Leitura de texturas" -concepts.shaders.binding.table.textureStorageHandle.access: "Leitura e escrita de texturas de armazenamento" -concepts.shaders.binding.title: "Buffers de constantes e identificadores de recursos" -concepts.shaders.compilation.description: "{zenithCompiler} compila um ponto de entrada Slang em uma {shaderDesc}. O {graphicsApi} do contexto define o destino: DXIL para DirectX 12, biblioteca Metal para Metal ou SPIR-V para Vulkan." -concepts.shaders.compilation.details: "Com um contexto gráfico já criado e chamado {context}, compile o shader do triângulo a partir da cópia ao lado do executável:" -concepts.shaders.compilation.guidance: "O nome do ponto de entrada {vSMain} deve corresponder à declaração no arquivo de shader. Compile os shaders e crie os pipelines na inicialização; depois, reutilize os pipelines durante a renderização. Após a criação dos pipelines, os objetos shader podem ser liberados, como mostra {link}." -concepts.shaders.compilation.guidance.link: "Primeiro triângulo" -concepts.shaders.compilation.title: "Compilação de shaders" -concepts.shaders.description: "As declarações em C# e Slang precisam concordar quanto à posição de cada valor e ao acesso feito pelo shader. Layouts de entrada descrevem os atributos dos vértices; declarações de buffers do shader descrevem parâmetros e arrays; identificadores apontam para os recursos usados pelo shader." -concepts.shaders.dispatch.description: "{dispatch} especifica quantos grupos de threads serão executados. O exemplo de computação declara {numthreads}, portanto cada grupo contém 16 × 16 threads. Para cobrir uma imagem, divida a largura e a altura por 16 e arredonde cada resultado para cima: uma imagem de 17 × 19 precisa de 2 × 2 grupos. O shader verifica as coordenadas de cada thread e ignora as que ficam fora da imagem." -concepts.shaders.dispatch.details: "O tamanho de grupo declarado está disponível em {shaderDescThreadGroupSize} e permite calcular as quantidades de grupos passadas a {dispatch}. {computeShaderRendererCs} mostra o cálculo completo. Depois do despacho, o acesso à imagem resultante deve seguir os requisitos descritos em {link}." -concepts.shaders.dispatch.details.link: "Sincronização" -concepts.shaders.dispatch.title: "Grupos de threads" -concepts.shaders.layout.context: "As {link} ilustram essa organização com as dimensões de uma imagem e dois identificadores de textura. Deslocamentos explícitos indicam onde cada campo começa. A declaração usa {systemRuntimeInteropServices} e {zenithNET}:" -concepts.shaders.layout.context.link: "constantes C# do exemplo de computação" -concepts.shaders.layout.description: "Para a entrada de vértices, {inputLayout} descreve o formato, o deslocamento e a semântica de cada atributo, além do passo entre vértices. O triângulo coloca uma posição {float3} antes de uma cor {float4}: a cor começa no deslocamento de byte 12 e cada vértice ocupa 28 bytes. {inputLayoutAdd} calcula essa organização compacta a partir dos formatos. Se a estrutura C# contiver preenchimento, informe deslocamentos e um passo que o considerem." -concepts.shaders.layout.details: "Buffers de constantes contêm parâmetros do shader, e buffers estruturados contêm arrays de elementos tipados. Seus layouts seguem as declarações de Slang, e não {inputLayout}. Ajuste os deslocamentos dos campos, tamanhos dos elementos e preenchimento em C# ao layout do shader compilado. Um tipo não gerenciado de C# pode ser copiado byte a byte, mas seu layout na memória não corresponde necessariamente ao do shader; um {float3} armazenado sem preenchimento em um vértice pode exigir outro alinhamento em um buffer do shader." -concepts.shaders.layout.guidance: "Os parâmetros do shader podem incluir identificadores de recursos além de valores comuns. Um identificador aponta para armazenamento já existente, portanto copiá-lo para um buffer de constantes não copia o conteúdo do recurso." -concepts.shaders.layout.notes: "A declaração correspondente em {computeShaderSlang} é:" -concepts.shaders.layout.reference: "As duas dimensões ocupam os primeiros oito bytes, seguidas de dois identificadores de oito bytes cada. O exemplo C# reserva 256 bytes para o registro completo. Para outros registros, determine o tamanho a partir de seus próprios campos e requisitos de layout e alinhamento." -concepts.shaders.layout.title: "Layout de dados" -concepts.shaders.matrices.description: "O compilador usa armazenamento de matrizes por linhas, mantendo cada linha contígua. O {link} armazena três valores {matrix4x4} nos deslocamentos 0, 64 e 128. Seu {detail} aplica {mulVectorMatrix} na ordem modelo, visão e projeção." -concepts.shaders.matrices.description.detail: "shader" -concepts.shaders.matrices.description.link: "renderizador de cubo giratório" -concepts.shaders.matrices.details: "A ordem de armazenamento determina a disposição dos elementos da matriz na memória; a ordem de multiplicação determina a transformação. C# e Slang devem adotar convenções compatíveis." -concepts.shaders.matrices.title: "Convenções de matrizes" -concepts.shaders.title: "Dados de shaders e vinculação" -concepts.synchronization.backends.description: "DirectX 12 e Vulkan codificam as transições de textura como mudanças de layout e acesso. Em Metal, a implementação de {transition} do Zenith.NET não executa uma operação equivalente. O backend de Metal reúne os comandos em codificadores de renderização e computação e insere barreiras de visibilidade ao encerrar cada codificador. Operações dependentes no mesmo codificador, como despachos de computação sucessivos, usam chamadas explícitas a {barrier}." -concepts.synchronization.backends.details: "No {link}, iniciar a passagem gráfica encerra o codificador de computação e torna sua saída visível ao trabalho gráfico. Dois despachos consecutivos permanecem no mesmo codificador, portanto sua dependência exige uma barreira mesmo que haja uma transição de textura entre eles. Por isso, uma sequência de comandos portável deve considerar as dependências de acesso além dos layouts de textura." -concepts.synchronization.backends.details.link: "exemplo de computação" -concepts.synchronization.backends.title: "Comportamento dos backends" -concepts.synchronization.barriers.context: "Escolha etapas que incluam os acessos envolvidos e sejam compatíveis com a fila. {barrierStagesAll} inclui todas as etapas compatíveis; selecione um conjunto menor quando a dependência envolver apenas essas etapas." -concepts.synchronization.barriers.description: "Considere dois despachos de computação registrados no mesmo buffer de comandos: o primeiro escreve dados de simulação e o segundo os lê. Coloque uma barreira entre eles para que o segundo veja as escritas concluídas. Em um buffer de armazenamento, isso ordena os acessos sem uma transição de layout de textura:" -concepts.synchronization.barriers.details: "O primeiro argumento identifica as etapas que produzem os dados; o segundo, as etapas que os consomem. Juntos, eles descrevem a ordem de execução e a visibilidade de memória necessárias entre os dois despachos." -concepts.synchronization.barriers.guidance: "A {link} usa esse padrão entre etapas da simulação. Cada barreira fica depois do despacho que produz os dados e antes daquele que os utiliza." -concepts.synchronization.barriers.guidance.link: "simulação FluidTank" -concepts.synchronization.barriers.title: "Barreiras do pipeline" -concepts.synchronization.dependencies.description: "Para cada recurso, identifique os acessos aos mesmos dados. Se algum deles escrever, preserve a ordem necessária entre as operações. Duas leituras não entram em conflito, embora os requisitos de layout de textura e apresentação continuem válidos. Atualizações pela CPU e a liberação de recursos também precisam esperar a GPU terminar de usar o armazenamento afetado." -concepts.synchronization.dependencies.details: "O mecanismo adequado depende de onde as operações são executadas:" -concepts.synchronization.dependencies.guidance: "Uma carga de trabalho pode precisar de mais de um mecanismo. Por exemplo, uma textura produzida em outra fila precisa de uma dependência entre envios e do layout adequado para o próximo uso. Nenhuma dessas operações exige bloquear a CPU, a menos que ela própria precise acessar ou liberar os dados." -concepts.synchronization.dependencies.table.cpuAccess.mechanism: "Chamar {wait} no valor de conclusão relevante." -concepts.synchronization.dependencies.table.cpuAccess.situation: "O acesso da CPU ou a liberação de recursos depende da conclusão na GPU" -concepts.synchronization.dependencies.table.crossQueue.mechanism: "Passe o {timelineValue} do produtor para o {submit} do consumidor." -concepts.synchronization.dependencies.table.crossQueue.situation: "Uma fila consome dados produzidos em outra" -concepts.synchronization.dependencies.table.headings.mechanism: "Mecanismo" -concepts.synchronization.dependencies.table.headings.situation: "Situação" -concepts.synchronization.dependencies.table.layoutChange.mechanism: "{commandBufferTransition} com seus layouts anterior e seguinte." -concepts.synchronization.dependencies.table.layoutChange.situation: "Um sub-recurso de textura altera como é usado" -concepts.synchronization.dependencies.table.pipelineStages.mechanism: "{commandBufferBarrier} com os estágios produtor e consumidor." -concepts.synchronization.dependencies.table.pipelineStages.situation: "Estágios dependentes da GPU em um fluxo de comandos" -concepts.synchronization.dependencies.title: "Dependências de acesso" -concepts.synchronization.description: "A sincronização estabelece a ordem de acesso aos dados compartilhados e garante que operações posteriores vejam os resultados necessários. Em uma dependência de escrita para leitura, quem escreve é o produtor e quem lê é o consumidor. Barreiras e transições de textura coordenam os acessos da GPU; linhas do tempo conectam envios e permitem que a CPU espere a conclusão do trabalho na GPU." -concepts.synchronization.layouts.context: "Use {undefined} como layout anterior quando o conteúdo existente puder ser descartado, como em uma imagem nova ou em um anexo que será limpo por completo. Para preservar o conteúdo para carregamento, amostragem ou acumulação, informe o layout do acesso anterior." -concepts.synchronization.layouts.description: "Os indicadores de uso declaram as funções permitidas da textura. {textureLayout} descreve o acesso a um sub-recurso, identificado pelo nível de mip e pela camada do array de texturas, em determinado ponto da sequência de comandos. Quando esse acesso mudar, registre uma transição. No exemplo de computação, a textura de saída é escrita em layout {storage} e depois preparada para amostragem em uma passagem gráfica:" -concepts.synchronization.layouts.details: "Aqui, {outputTexture} foi criada com uso {sampledStorage}, e o sub-recurso selecionado está em {storage}. {default} seleciona o nível de mip 0 e a camada 0. A transição não afeta outros níveis ou camadas." -concepts.synchronization.layouts.guidance: "Em {transition}, informe o layout do uso anterior do sub-recurso. A aplicação acompanha esse estado ao registrar comandos e passar texturas entre as etapas de renderização." -concepts.synchronization.layouts.title: "Layouts de textura" -concepts.synchronization.readback.description: "{isCompleted} informa a conclusão na GPU. Um download registrado tem uma etapa adicional: copiar o resultado da área interna de leitura para a memória de destino da aplicação." -concepts.synchronization.readback.details: "{commandBufferDownload} registra a cópia da GPU para essa área interna. Quando o envio termina, a biblioteca realiza a cópia na CPU ao recuperar o buffer de comandos concluído. Chamar {wait} no valor de envio do download espera a GPU e processa os buffers concluídos daquela fila, completando as duas etapas. Mantenha o destino alocado e a memória gerenciada fixada até o retorno da chamada." -concepts.synchronization.readback.guidance: "Consultar apenas {isCompleted} não executa a cópia final na CPU. Esperar em outra fila também não recupera os buffers concluídos da fila do download. {link} descreve quando uploads e downloads usam acesso direto à memória ou armazenamento temporário de transferência." -concepts.synchronization.readback.guidance.link: "Gerenciamento de recursos" -concepts.synchronization.readback.title: "Conclusão da leitura de dados" -concepts.synchronization.reuse.description: "O triângulo espera cada quadro terminar antes de reutilizar seus dados. Para sobrepor quadros, reserve armazenamento mutável próprio para cada quadro em andamento e acompanhe quando ele volta a estar disponível. Antes de modificar dados, espere o trabalho da GPU que ainda acessa os bytes afetados; antes de liberar um recurso, espere todos os seus usos pendentes." -concepts.synchronization.reuse.details: "Redimensionamento e encerramento seguem a mesma regra: impedir novos usos, esperar os existentes terminarem e então substituir ou liberar os recursos. Respeite essa ordem antes de chamar {swapChainResize} ou liberar recursos ou o contexto. Como o triângulo já espera a cada quadro, ele pode redimensionar entre as chamadas dos callbacks." -concepts.synchronization.reuse.guidance: "{swapChainPresent} sinaliza um ponto da fila gráfica e espera por ele após a apresentação. Assim, o triângulo continua esperando ao apresentar, mesmo sem a espera explícita do envio. O trabalho independente em outras filas precisa de seu próprio acompanhamento de conclusão." -concepts.synchronization.reuse.title: "Reutilização de recursos" -concepts.synchronization.timelines.context: "Se a CPU precisar ler o resultado, sobrescrever os dados compartilhados ou liberar os recursos após o consumidor terminar, espere esse envio:" -concepts.synchronization.timelines.description: "Uma linha do tempo identifica a conclusão na fila por valores crescentes. {submit} retorna um {timelineValue} contendo a linha do tempo e o valor do envio. Campos {value} de linhas do tempo distintas não são diretamente comparáveis." -concepts.synchronization.timelines.details: "Considere {producer} e {consumer}, buffers já gravados em duas filas do mesmo contexto, com o consumidor usando dados escritos pelo produtor. Envie-os com esta dependência:" -concepts.synchronization.timelines.guidance: "A fila consumidora espera o valor de conclusão recebido antes de executar seus comandos. A CPU pode continuar sem chamar {producedWait}. Mantenha os recursos compartilhados vivos até a conclusão de {consumed} e registre as transições de textura necessárias ao acesso do consumidor." -concepts.synchronization.timelines.notes: "O valor retornado por {queueTimelineSignal} também pode ser usado para esperar com {wait} ou estabelecer uma dependência para outra fila. {signal} coloca esse ponto de conclusão depois do trabalho já enviado; a GPU o alcança quando esse trabalho termina." -concepts.synchronization.timelines.title: "Linhas do tempo e dependências entre filas" -concepts.synchronization.title: "Sincronização" -home.actions.reference: "Navegar na API" -home.actions.tutorial: "Começar com um triângulo" -home.entries.description: "Tutoriais, exemplos e referência da API" -home.entries.label: "Seções da documentação" -home.entries.reference.action: "Explorar a API" -home.entries.reference.category: "Referência" -home.entries.reference.description: "Consulte tipos, membros e declarações da API" -home.entries.reference.title: "Referência da API" -home.entries.samples.action: "Procurar exemplos" -home.entries.samples.category: "Exemplos" -home.entries.samples.description: "Exemplos executáveis de técnicas gráficas e de computação" -home.entries.samples.title: "Exemplos" -home.entries.title: "Documentação" -home.entries.tutorial.action: "Iniciar tutorial" -home.entries.tutorial.category: "Tutorial" -home.entries.tutorial.description: "De um projeto vazio ao primeiro triângulo na tela" -home.entries.tutorial.title: "Primeiro triângulo" -home.introduction.accent: "com .NET" -home.introduction.description: "Zenith.NET oferece uma API comum de gráficos e computação para DirectX, Metal e Vulkan" -home.introduction.title: "Gráficos multiplataforma{lineBreak}{accent}" -home.meta.description: "Gráficos e computação multiplataforma em .NET com uma API comum para DirectX, Metal e Vulkan" -home.scene.description: "Geometria interativa em rotação. Arraste ou use as teclas de direção para ajustar a visualização." -home.scene.label: "Exibição de geometria" -home.scene.surface: "Superfície" -home.scene.wireframe: "Wireframe" -home.title: "RHI moderna para .NET" -learning.concepts.description: "Critérios para escolher usos de recursos, descrever dados de shaders e coordenar a execução na GPU" -learning.concepts.execution.description: "Gravação de comandos, envio e tempo de vida dos recursos" -learning.concepts.platforms.description: "Apresentação nativa e controles de renderização" -learning.concepts.resources.description: "Usos de recursos, localização na memória e visualizações" -learning.concepts.shaders.description: "Convenções de layout e vinculação entre C# e Slang" -learning.concepts.synchronization.description: "Dependências, visibilidade e conclusão" -learning.concepts.title: "Conceitos fundamentais" -learning.description: "Comece pelo tutorial do triângulo para criar sua primeira aplicação. Depois, consulte os artigos sobre recursos, dados de shaders e sincronização, ou escolha um exemplo da técnica que deseja implementar." -learning.entries.samples.action: "Procurar exemplos" -learning.entries.samples.description: "Implementações em C# e Slang de geometria, computação, consultas de raios e sombreamento de malha" -learning.entries.tutorial.action: "Abrir tutorial" -learning.entries.tutorial.description: "Uma aplicação de console que abre uma janela e renderiza um triângulo" -learning.meta.description: "Tutoriais e fundamentos do modelo de programação de Zenith.NET" -learning.title: "Aprender" -reference.description: "Referência de recursos, comandos e integrações de plataforma" -reference.entries.commands.description: "Comandos gráficos, de computação e de transferência" -reference.entries.commands.label: "Registrar comandos" -reference.entries.context.description: "Criação de recursos da GPU no backend selecionado" -reference.entries.context.label: "Comece aqui" -reference.meta.description: "Namespaces, tipos e membros de Zenith.NET" -reference.navigation.core: "Referência da API principal" -reference.title: "Referência da API" -samples.computeShader.description: "O exemplo carrega {assetsTexturesShokoPng}, converte a imagem para tons de cinza em um despacho de computação e exibe a textura resultante. A conversão ocorre uma vez; os quadros seguintes exibem o mesmo resultado. O renderizador mostra como vincular texturas para amostragem e escrita, arredondar para cima as quantidades de grupos de threads para cobrir a imagem e verificar seus limites no shader." -samples.computeShader.details: "{computeShaderRendererCs} · {computeShaderSlang}" -samples.computeShader.title: "Shader de computação" -samples.cube.description: "O cubo acrescenta desenho indexado, matrizes de modelo, visão e projeção em um buffer de constantes e teste de profundidade. Sua textura de profundidade e estêncil {d32FloatS8UInt} é recriada no redimensionamento." -samples.cube.details: "{spinningCubeRendererCs} · {spinningCubeSlang}" -samples.cube.title: "Cubo giratório" -samples.description: "Cada exemplo reúne um renderizador C# e seu shader Slang em torno de uma técnica. Para a configuração completa da aplicação e a sequência de renderização, comece por {link}." -samples.description.link: "Primeiro triângulo" -samples.execution.description: "Execute o projeto {link} e escolha um exemplo no menu do console." -samples.execution.description.link: "ZenithTutorials" -samples.execution.title: "Execução dos exemplos" -samples.host.description: "{appCs} inicializa contexto, janela e cadeia de troca. A cada quadro, obtém um buffer de comandos, chama o renderizador selecionado, envia os comandos e apresenta o resultado. {iRendererCs} define as operações de atualização, renderização, redimensionamento e liberação." -samples.host.details: "Os renderizadores de computação e traçado de raios produzem texturas fora da tela. {texturePresenterCs} e {presentTextureSlang} desenham essas texturas na saída do quadro atual; em seguida, o programa hospedeiro compartilhado envia os comandos e apresenta o quadro." -samples.host.title: "Programa hospedeiro e apresentação" -samples.indirectDrawing.description: "O desenho indireto renderiza várias instâncias de cubos a partir de um buffer de argumentos de desenho indexado e de um buffer estruturado de dados por instância. A CPU fornece os argumentos e atualiza as transformações." -samples.indirectDrawing.details: "{indirectDrawingRendererCs} · {indirectDrawingSlang}" -samples.indirectDrawing.title: "Desenho indireto" -samples.meshShading.description: "Um shader de tarefa descarta as instâncias de esferas não visíveis e passa os índices restantes ao shader de malha, que gera a geometria. O renderizador verifica {contextCapabilitiesMeshShadingSupported} antes de criar o pipeline." -samples.meshShading.details: "{meshShadingRendererCs} · {meshShadingSlang}" -samples.meshShading.title: "Sombreamento de malha" -samples.rayTracing.description: "O exemplo cria estruturas de aceleração de nível inferior e superior para um piso e esferas procedurais e realiza consultas de raios em um shader de computação. Verifica {contextCapabilitiesRayTracingSupported} antes da inicialização." -samples.rayTracing.details: "{rayTracingRendererCs} · {rayTracingSlang}" -samples.rayTracing.title: "Traçado de raios" -samples.title: "Exemplos" -samples.triangle.description: "O triângulo associa um buffer de vértices ao layout de entrada correspondente e desenha três vértices por um pipeline gráfico." -samples.triangle.details: "{helloTriangleRendererCs} · {helloTriangleSlang} · {link}" -samples.triangle.details.link: "Tutorial completo" -samples.triangle.title: "Olá triângulo" -samples.workloads.description: "O {link} do repositório principal contém aplicações de maior porte que referenciam o código-fonte da biblioteca." -samples.workloads.description.link: "diretório Experiments" -samples.workloads.details: "Os experimentos com janela usam os mesmos mecanismos de apresentação em Windows, macOS e Linux/X11. {link} trata dos controles para Avalonia, WinForms, WPF, WinUI/Uno e MAUI, incluindo o ciclo dos quadros e as implementações." -samples.workloads.details.link: "Integração de plataforma" -samples.workloads.table.cornellBox.example: "{link}" -samples.workloads.table.cornellBox.example.link: "CornellBox" -samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: "Traçado de caminhos, redução de ruído, mapeamento de tons, ampliação de resolução e controles ImGui. Requer suporte a traçado de raios." -samples.workloads.table.fluidTank.example: "{link}" -samples.workloads.table.fluidTank.example.link: "FluidTank" -samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: "Simulação de fluidos por computação, dependências entre estágios de simulação e renderização de superfície em várias passagens." -samples.workloads.table.headings.example: "Exemplo" -samples.workloads.table.headings.whatItDemonstratesAndRequires: "Técnicas e requisitos" -samples.workloads.table.inkCanvas.example: "{link}" -samples.workloads.table.inkCanvas.example.link: "InkCanvas" -samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: "Desenho com Skia e tratamento de entrada em uma janela nativa. Requer o backend e a biblioteca nativa do Skia para a plataforma de destino." -samples.workloads.table.platformDetection.example: "{link}" -samples.workloads.table.platformDetection.example.link: "PlatformDetection" -samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: "Tenta criar um contexto para cada backend e informa as capacidades do dispositivo. Uma tentativa que falha é indicada como não compatível; a causa pode estar no dispositivo, no driver ou em uma dependência de execução ausente." -samples.workloads.title: "Aplicações de maior porte" -tutorial.context.description: "Um {graphicsContext} conecta a aplicação à GPU por meio de um backend e fornece os métodos para criar os recursos de renderização." -tutorial.context.details: "Insira a inicialização do contexto {emphasis}:" -tutorial.context.details.emphasis: "após as diretivas using, antes de {iWindowWindow}" -tutorial.context.guidance: "Cada ramo seleciona o backend da plataforma e solicita a validação. As mensagens de {validationMessage} são exibidas no console." -tutorial.context.imports: "Adicione as seguintes diretivas using no início de {programCs}:" -tutorial.context.title: "Contexto gráfico" -tutorial.description: "Neste tutorial, um projeto de console .NET vazio se torna uma aplicação que abre uma janela e desenha um triângulo colorido." -tutorial.details: "O tutorial tem três pontos de verificação: uma janela vazia, um fundo de cor uniforme e o triângulo colorido. Execute a aplicação em cada ponto antes de acrescentar a próxima parte." -tutorial.draw.context: "Os argumentos para {draw} são:" -tutorial.draw.description: "No callback {windowRender}, substitua {addTheTriangleDrawCommandsHereLater} pelos comandos abaixo, entre {beginRenderPass} e {endRenderPass}:" -tutorial.draw.details: "{setPipeline} seleciona shaders e estado de renderização. Deve preceder o vínculo dos vértices, pois o backend interpreta esse vínculo conforme o layout de entrada do pipeline." -tutorial.draw.guidance: "{setVertexBufferVertexBuffer} vincula os dados de vértices já transferidos, a partir do deslocamento de byte 0, ao slot de entrada 0, correspondente à única entrada de {inputLayouts}." -tutorial.draw.notes: "Essas chamadas registram os comandos de desenho. A chamada existente a {submitWait} os envia e espera a GPU terminar; em seguida, {present} solicita a exibição da imagem concluída. Mantenha a limpeza no início da passagem para definir a cor de fundo na área externa ao triângulo." -tutorial.draw.table.firstInstance.meaning: "Iniciar a numeração de instâncias em zero." -tutorial.draw.table.firstVertex.meaning: "Começar com o primeiro vértice no buffer." -tutorial.draw.table.headings.argument: "Argumento" -tutorial.draw.table.headings.description: "Valor" -tutorial.draw.table.headings.meaning: "Significado" -tutorial.draw.table.instanceCount.meaning: "Desenhar uma cópia do triângulo." -tutorial.draw.table.vertexCount.meaning: "Ler três vértices." -tutorial.draw.title: "Comandos de desenho" -tutorial.execution.description: "Compile e execute o projeto {firstTriangle}." -tutorial.execution.details: "A janela deve exibir um triângulo sobre fundo escuro, vermelho no alto, verde embaixo à direita e azul embaixo à esquerda. A interpolação das cores dos vértices forma um gradiente suave em seu interior." -tutorial.execution.guidance: "O redimensionamento muda as dimensões da imagem em pixels, mas mantém as coordenadas dos vértices. O viewport ajusta essas coordenadas à nova largura e altura, por isso o triângulo se deforma quando a proporção da janela muda." -tutorial.execution.title: "Execução da aplicação" -tutorial.frame.commands.context: "Após {endRenderPass}, a segunda transição prepara a textura de saída para apresentação. {submit} encerra o registro e envia o buffer de comandos; {wait} bloqueia a thread até a conclusão desse envio. Em seguida, {present} solicita a exibição da imagem renderizada." -tutorial.frame.commands.description: "Uma passagem de renderização reúne operações de desenho que escrevem nos mesmos anexos. Nesta passagem, a textura de saída da cadeia de troca recebe a cor. {colorAttachmentClear} descreve como inicializar esse anexo com uma cor RGBA e preservar seu conteúdo ao encerrar a passagem. {beginRenderPass} registra o início da passagem com essas configurações." -tutorial.frame.commands.details: "A coleção contém um anexo de cor. {null} indica que a passagem não possui anexo de profundidade e estêncil." -tutorial.frame.commands.guidance: "{beginRenderPass} ajusta o viewport e a região de recorte para todo o anexo. O viewport converte coordenadas de renderização em posições de pixels; o recorte limita a região em que se pode escrever." -tutorial.frame.commands.title: "Limpeza, envio e apresentação" -tutorial.frame.description: "Comece preenchendo a janela com uma cor de fundo. Essa operação é chamada de limpeza. Quando o fundo aparece, a superfície, o envio de comandos e a apresentação já funcionam juntos. A partir daí, acrescente os vértices e os shaders do triângulo." -tutorial.frame.details: "Silk.NET chama o callback quando há um quadro a renderizar. Como o exemplo não usa o argumento de tempo decorrido, o parâmetro se chama {value}. Registre o callback {emphasis}:" -tutorial.frame.details.emphasis: "antes de {windowRun}" -tutorial.frame.target.description: "{graphicsQueueCommandBuffer} retorna um buffer pronto para gravação. Gravar define o trabalho da GPU; sua execução só começa após o envio." -tutorial.frame.target.details: "O layout de uma textura descreve o acesso necessário a uma operação. A primeira chamada a {transition} prepara a textura de saída para uso como anexo de cor. Aqui, {default} seleciona o nível de mip 0 e a camada 0 do array, ou seja, a imagem base da textura. Como a passagem limpa a imagem inteira, {undefined} permite descartar o conteúdo anterior." -tutorial.frame.target.guidance: "Obtenha a textura de saída atual a cada quadro, pois a apresentação pode passar a usar outra imagem." -tutorial.frame.target.title: "Preparação da textura de saída" -tutorial.frame.title: "O primeiro quadro" -tutorial.geometry.data.description: "Adicione o array de vértices {emphasis}. Mantenha também as próximas inicializações de recursos antes desse callback, na ordem apresentada." -tutorial.geometry.data.description.emphasis: "antes de {windowRender}" -tutorial.geometry.data.details: "Cada entrada constrói um {vertex}; os dois {new} internos fornecem a posição {vector3} e a cor {vector4}. As posições formam os cantos superior, inferior direito e inferior esquerdo. O shader de vértices acrescenta {w} como quarta coordenada. Com w igual a 1, x e y também são coordenadas normalizadas de dispositivo: -1 e +1 marcam os limites da imagem, e 0, o centro. Sua interpretação independe da quantidade de pixels." -tutorial.geometry.data.guidance: "Cada cor tem componentes vermelho, verde, azul e alfa, com alfa igual a 1. Os três vértices têm z = 0 e estão no mesmo plano." -tutorial.geometry.data.title: "Posições e cores dos vértices" -tutorial.geometry.description: "Cada um dos três vértices tem posição e cor. A GPU determina a forma do triângulo a partir das posições e interpola as cores em sua superfície." -tutorial.geometry.format.description: "Acrescente a declaração do vértice {emphasis}:" -tutorial.geometry.format.description.emphasis: "no final de {programCs}, após as instruções de limpeza" -tutorial.geometry.format.details: "{file} restringe o tipo a {programCs}, e {layoutKindSequential} mantém os campos na ordem de declaração. {position} contém três valores de ponto flutuante de 32 bits e começa no deslocamento de byte 0; {color} contém quatro e começa no deslocamento de byte 12. Cada vértice ocupa, portanto, 28 bytes. O layout de entrada descreverá essa organização para que a GPU leia os campos corretamente." -tutorial.geometry.format.imports: "Adicione estas diretivas using no início de {programCs} para usar os tipos vetoriais e o atributo de layout da estrutura:" -tutorial.geometry.format.title: "Representação dos vértices" -tutorial.geometry.title: "Dados de vértices" -tutorial.geometry.upload.context: "{fixed} impede que o coletor de lixo mova o array enquanto seu endereço estiver em uso. Neste buffer gravável pela CPU, {upload} mapeia a memória, copia os bytes e desfaz o mapeamento antes de retornar. O array só precisa permanecer fixado durante a chamada. Envie os vértices uma vez na inicialização e mantenha o buffer vivo até o fim da renderização." -tutorial.geometry.upload.description: "Armazene os vértices em um {buffer} para que a GPU possa lê-los durante o desenho. Acrescente a alocação e o envio dos dados logo após o array:" -tutorial.geometry.upload.details: "O tamanho é {sizeofVertexVerticesLength}: três vértices de 28 bytes, ou 84 bytes. {bufferUsagesVertex} declara o uso como entrada de vértices, e {cpuWriteOnly} permite a inicialização direta pela CPU. O passo do descritor registra o tamanho do elemento. O layout definido adiante especifica como cada atributo será lido." -tutorial.geometry.upload.guidance: "A alocação não inicializa o conteúdo do buffer. {upload} copia o array para o deslocamento 0 do destino, usando o ponteiro de origem e a quantidade de bytes da descrição de dados." -tutorial.geometry.upload.imports: "Em {programCs}, adicione {bufferAlias} às diretivas using para distinguir o tipo de buffer do Zenith.NET de {systemBuffer}." -tutorial.geometry.upload.notes: "Na limpeza ao final de {programCs}, insira {vertexBufferDispose} imediatamente antes de {swapChainDispose}. {link} trata do armazenamento exclusivo da GPU e de transferências para geometria estática maior." -tutorial.geometry.upload.notes.link: "Gerenciamento de recursos" -tutorial.geometry.upload.title: "Alocação e transferência do buffer" -tutorial.input.description: "A GPU precisa saber onde estão os atributos de cada vértice, como posição e cor. O layout de entrada fornece o formato e o deslocamento de cada atributo, além do passo: a distância em bytes até o próximo vértice. Adicione este código após criar os shaders:" -tutorial.input.details: "{inputLayoutAdd} coloca cada atributo após o anterior e soma seu tamanho ao passo entre vértices. Os deslocamentos são calculados a partir dos formatos informados, sem inspecionar a estrutura C#. Para esses dois campos, o resultado é:" -tutorial.input.guidance: "O valor padrão de {semanticIndex} é zero, correspondente a {pOSITION0} e {cOLOR0} no shader. Posição e cor ficam juntas em um buffer de vértices, portanto o pipeline utiliza um único layout de entrada no slot 0. Se a ordem dos campos ou o preenchimento da estrutura C# mudar, ajuste também esse layout." -tutorial.input.table.headings.byteOffset: "Deslocamento de bytes" -tutorial.input.table.headings.cField: "Campo C#" -tutorial.input.table.headings.format: "Formato" -tutorial.input.table.headings.shaderInput: "Entrada do shader" -tutorial.input.table.nextVertex.cField: "Próximo vértice" -tutorial.input.table.nextVertex.format: "Passo total: 28 bytes" -tutorial.input.table.nextVertex.shaderInput: "Próximo registro de entrada" -tutorial.input.table.vertexColor.format: "{float4} (16 bytes)" -tutorial.input.table.vertexPosition.format: "{float3} (12 bytes)" -tutorial.input.title: "Layout de entrada dos vértices" -tutorial.lifecycle.description: "Cada quadro segue esta sequência:" -tutorial.lifecycle.details: "Quando a janela fecha, {run} retorna e a execução continua no código de limpeza. Como cada quadro já esperou seus comandos terminarem, os recursos usados por eles podem ser liberados. O bloco completo de limpeza após {windowRun} é:" -tutorial.lifecycle.guidance: "Libere a cadeia de troca antes de destruir sua janela nativa e o contexto depois de seus recursos. A fila recicla os buffers de comandos enviados, e a cadeia de troca gerencia a textura de saída; nenhum deles precisa de uma chamada separada a {dispose}." -tutorial.lifecycle.title: "Ciclo dos quadros e liberação" -tutorial.pipeline.behavior: "Após o layout de entrada, crie o pipeline:" -tutorial.pipeline.context: "{cullNone} desativa o descarte de faces, de modo que o triângulo seja desenhado tanto com os vértices em sentido horário quanto em sentido anti-horário." -tutorial.pipeline.description: "Um {graphicsPipeline} reúne o layout dos vértices, os dois shaders e as configurações de montagem de primitivas e escrita nos anexos." -tutorial.pipeline.details: "Os shaders processam vértices e fragmentos. As demais configurações do pipeline controlam a montagem de primitivas, o descarte de faces, o teste de profundidade e a mesclagem de cores:" -tutorial.pipeline.guidance: "O formato de cor do pipeline deve corresponder ao anexo da passagem, por isso é obtido de {swapChainDescFormat}. {count1} especifica uma amostra por pixel." -tutorial.pipeline.item: "{triangleList} monta um triângulo a cada grupo de três vértices consecutivos." -tutorial.pipeline.notes: "{depthNone} desativa teste e escrita de profundidade, de acordo com a ausência desse anexo." -tutorial.pipeline.reference: "{opaque} desativa a mesclagem. A saída do shader de fragmentos substitui, portanto, a cor de fundo dentro do triângulo." -tutorial.pipeline.title: "Pipeline gráfico" -tutorial.pipeline.usage: "Os objetos de shader podem ser liberados após a criação do pipeline. Mantenha o pipeline durante a renderização e adicione {pipelineDispose} antes de {vertexBufferDispose} na limpeza." -tutorial.presentation.title: "Contexto gráfico e apresentação" -tutorial.project.context: "Ative {emphasis} ({allowUnsafeBlocks}) nas opções de compilação do projeto. As chamadas nativas do auxiliar de janela e a transferência de vértices exigem código não seguro." -tutorial.project.context.emphasis: "Permitir código não seguro" -tutorial.project.description: "Crie um projeto de console C# chamado {firstTriangle}, com .NET 10 como framework de destino." -tutorial.project.details: "Adicione os seguintes pacotes NuGet ao projeto:" -tutorial.project.guidance: "{zenithNET} fornece a API comum de renderização; os três pacotes de backend, suas implementações. {zenithNETCompiler} compila os shaders Slang apresentados adiante para o backend selecionado. Silk.NET cria a janela e processa eventos." -tutorial.project.title: "Configuração do projeto" -tutorial.requirements.context: "O {link} e seu {detail} fornecem as implementações de referência deste tutorial." -tutorial.requirements.context.detail: "programa hospedeiro" -tutorial.requirements.context.link: "exemplo Olá triângulo" -tutorial.requirements.description: "São necessários o {emphasis} e conhecimentos básicos de C#. A aplicação tem {net10} como destino. A GPU e o driver devem oferecer suporte ao backend escolhido para sua plataforma:" -tutorial.requirements.description.emphasis: "SDK do .NET 10" -tutorial.requirements.guidance: "Zenith.NET renderiza em uma superfície nativa fornecida pela aplicação. Silk.NET.Windowing cria a janela e processa seus eventos. No macOS, a apresentação usa uma camada Metal, representada por {cAMetalLayerCs}, que o auxiliar associa à janela." -tutorial.requirements.table.headings.graphicsBackend: "Backend gráfico" -tutorial.requirements.table.headings.platform: "Plataforma" -tutorial.requirements.table.linux.graphicsBackend: "Vulkan 1.4" -tutorial.requirements.table.linux.platform: "Linux (X11 ou XWayland)" -tutorial.requirements.table.macOS.graphicsBackend: "Metal 4" -tutorial.requirements.table.macOS.platform: "macOS" -tutorial.requirements.table.windows.graphicsBackend: "DirectX 12" -tutorial.requirements.table.windows.platform: "Windows" -tutorial.requirements.title: "Pré-requisitos" -tutorial.resize.context: "Compile e execute a aplicação novamente. O fundo deve continuar preenchendo a janela quando ela for redimensionada: cada nova passagem ajusta o viewport e o retângulo de recorte às dimensões do anexo. Mantenha o callback de renderização; o triângulo será desenhado dentro dessa mesma passagem." -tutorial.resize.description: "A cadeia de troca precisa acompanhar as mudanças de tamanho do framebuffer. Registre um callback de {framebufferResize} depois do callback de renderização e antes de {windowRun}:" -tutorial.resize.details: "Responda às {link}, medidas em pixels, em vez de às mudanças no tamanho lógico da janela. Se minimizar a janela fizer alguma dimensão chegar a zero, o callback de redimensionamento mantém a cadeia de troca como está. O callback de renderização também retorna enquanto alguma dimensão for zero, interrompendo a renderização até que o framebuffer volte a ter um tamanho utilizável." -tutorial.resize.details.link: "alterações no tamanho do framebuffer" -tutorial.resize.guidance: "O callback de renderização espera cada quadro enviado terminar antes de chamar {present}. Assim, o callback de redimensionamento pode substituir as imagens da cadeia de troca sem interromper o trabalho de um quadro anterior. O artigo {link} detalha essa relação entre a conclusão do trabalho e o tempo de vida dos recursos." -tutorial.resize.guidance.link: "Sincronização" -tutorial.resize.title: "Redimensionamento" -tutorial.shaders.compilation.context: "{appContextBaseDirectory} permite carregar a cópia do shader no diretório de saída da aplicação. Assim, iniciar a aplicação a partir de outro diretório de trabalho não altera o local em que ela procura o arquivo." -tutorial.shaders.compilation.description: "Nas propriedades de {triangleSlang}, defina {emphasis} como {detail}. A compilação copiará o shader para o diretório do executável." -tutorial.shaders.compilation.description.detail: "Copiar se mais recente" -tutorial.shaders.compilation.description.emphasis: "Copiar para o Diretório de Saída" -tutorial.shaders.compilation.details: "Em {programCs}, acrescente a inicialização dos shaders após a transferência dos vértices e antes do callback de renderização:" -tutorial.shaders.compilation.guidance: "{zenithCompiler} compila o código-fonte para {contextGraphicsApi}, e {createShader} cria um objeto shader a partir da descrição compilada. Os nomes de ponto de entrada {vSMain} e {fSMain} selecionam as duas funções definidas no arquivo Slang." -tutorial.shaders.compilation.title: "Compilação dos shaders" -tutorial.shaders.context: "{fSInput} conecta as duas etapas do shader. O shader de vértices escreve em {sVPOSITION} uma posição no espaço de recorte, que a GPU usa para determinar a parte visível do triângulo. O campo {cOLOR0} leva a cor do vértice, interpolada ao longo do triângulo antes de chegar ao shader de fragmentos. Seu tipo e sua semântica devem corresponder nas duas etapas." -tutorial.shaders.description: "Shaders são programas executados na GPU. O shader de vértices determina a posição de cada vértice, e o shader de fragmentos determina a cor em cada posição coberta da imagem. As duas etapas serão escritas em um único arquivo Slang, cada uma com seu ponto de entrada: a função em que a execução começa." -tutorial.shaders.details: "Crie {triangleSlang} com estas estruturas de entrada e saída:" -tutorial.shaders.fragment.description: "Acrescente o ponto de entrada de fragmentos ao mesmo arquivo:" -tutorial.shaders.fragment.details: "A rasterização identifica as posições da imagem cobertas pelo triângulo e gera fragmentos para elas. Cada fragmento recebe uma cor interpolada a partir das cores dos três vértices. {fSMain} retorna essa cor, e {sVTARGET} direciona o resultado ao primeiro anexo de cor." -tutorial.shaders.fragment.title: "Sombreamento de fragmentos" -tutorial.shaders.guidance: "{vSInput} define as entradas do shader de vértices. {pOSITION0} e {cOLOR0} identificam os atributos por semântica; nomes de campos em C# não estabelecem sozinhos essa correspondência." -tutorial.shaders.title: "Estágios dos shaders" -tutorial.shaders.vertex.description: "Acrescente o ponto de entrada de vértices a {triangleSlang}:" -tutorial.shaders.vertex.details: "A GPU executa esse ponto de entrada para cada vértice. Ele acrescenta a coordenada homogênea {w} e repassa a cor. Após o processamento dos vértices, a posição é dividida por w. Como w vale 1, x, y e z permanecem iguais e podem ser interpretados como coordenadas normalizadas de dispositivo." -tutorial.shaders.vertex.title: "Sombreamento de vértices" -tutorial.surface.description: "Especifique o destino nativo de apresentação {emphasis}:" -tutorial.surface.description.emphasis: "após {windowCenter} e antes de {windowRun}" -tutorial.surface.details: "O framebuffer é a imagem da janela em pixels. {surface} descreve o destino nativo de apresentação e suas dimensões; {framebufferSize} fornece o tamanho em pixels. Com a escala da tela, esse tamanho pode diferir das dimensões lógicas da janela." -tutorial.surface.guidance: "A superfície fornece os identificadores nativos do backend: uma janela Win32 no Windows, display e janela X11 no Linux ou a camada Metal associada no macOS." -tutorial.surface.title: "Superfície nativa" -tutorial.swapChain.context: "A cadeia de troca depende do contexto e da janela. Substitua {windowDispose} no final de {programCs} por esta ordem de liberação:" -tutorial.swapChain.description: "Crie a cadeia de troca logo após a descrição da superfície:" -tutorial.swapChain.details: "A {swapChain} gerencia as imagens apresentadas pela janela. {drawable} fornece a imagem atual como uma {texture}, o recurso de imagem da API. Após a renderização, {present} solicita sua exibição e avança para a próxima textura de saída." -tutorial.swapChain.guidance: "{b8G8R8A8UNorm} armazena quatro canais de 8 bits na ordem azul, verde, vermelho e alfa. {uNorm} mapeia os inteiros de 0–255 para 0–1. A saída do shader continua sendo um valor RGBA lógico; o formato define sua representação no armazenamento. O pipeline usará {swapChainDescFormat} para corresponder a esse anexo." -tutorial.swapChain.title: "Cadeia de troca" -tutorial.title: "Primeiro triângulo" -tutorial.troubleshooting.description: "Use os diagnósticos do console e os três pontos de verificação para localizar a etapa com falha:" -tutorial.troubleshooting.details: "O {link} e o {detail} servem de referência para dados de vértices, layout e desenho. O exemplo separa janela e envio em um programa hospedeiro comum; este tutorial mantém o fluxo em {programCs}. O {context} introduz desenho indexado, transformações e teste de profundidade." -tutorial.troubleshooting.details.context: "Cubo giratório" -tutorial.troubleshooting.details.detail: "shader Slang" -tutorial.troubleshooting.details.link: "renderizador de exemplo" -tutorial.troubleshooting.table.backend.check: "Verifique se o backend selecionado é suportado pelo dispositivo e pelo driver gráfico instalado." -tutorial.troubleshooting.table.backend.symptom: "Falha na criação do backend" -tutorial.troubleshooting.table.drawing.check: "Verifique o tamanho do upload, o layout de entrada, a seleção de pipeline e o posicionamento dos comandos de desenho dentro da passagem de renderização." -tutorial.troubleshooting.table.drawing.symptom: "O fundo aparece, mas o triângulo não" -tutorial.troubleshooting.table.headings.check: "Verificação" -tutorial.troubleshooting.table.headings.symptom: "Sintoma" -tutorial.troubleshooting.table.input.check: "Verifique o passo de 28 bytes e os deslocamentos de posição/cor de 0 e 12." -tutorial.troubleshooting.table.input.symptom: "Posições ou cores dos vértices estão corrompidas" -tutorial.troubleshooting.table.shaders.check: "Verifique o {triangleSlang} copiado, a ortografia do ponto de entrada e o diagnóstico relatado pelo compilador." -tutorial.troubleshooting.table.shaders.symptom: "O fundo aparece, mas o carregamento dos shaders falha" -tutorial.troubleshooting.table.window.check: "Confirme se o projeto .NET compila e se a etapa somente de janela é executada em uma sessão de desktop. No Linux, verifique se o X11 ou XWayland está disponível." -tutorial.troubleshooting.table.window.symptom: "Nenhuma janela se abre" -tutorial.troubleshooting.title: "Diagnóstico de problemas" -tutorial.window.description: "Baixe {cocoaHelperCs} para o diretório do projeto. Essa classe auxiliar conecta a camada Metal à janela do macOS." -tutorial.window.details: "Substitua o conteúdo gerado de {programCs} pelo código abaixo. Ele usa instruções de nível superior, executadas em ordem sem um método {main} explícito. As próximas seções indicarão onde acrescentar cada trecho:" -tutorial.window.guidance: "{graphicsAPINone} deixa a criação do contexto gráfico a cargo de Zenith.NET. {initialize} cria a janela nativa e disponibiliza os identificadores do sistema de janelas. {center} a coloca no centro da tela. {run} processa eventos até seu fechamento; depois, {dispose} libera a janela." -tutorial.window.notes: "Compile e execute a aplicação. Verifique se a janela abre e fecha normalmente e se é possível movê-la e redimensioná-la. O conteúdo ainda não está definido, pois nenhum comando de renderização foi enviado. Feche a janela antes de continuar." -tutorial.window.title: "Criação da janela" -ui.action.copy: "Copiar" -ui.action.navigate: "Navegar" -ui.action.open: "Abrir" -ui.action.source: "Ver código-fonte" -ui.api.browse: "Navegar por namespaces e tipos." -ui.api.clearTypeSearch: "Limpar busca de tipos" -ui.api.findType: "Localizar um tipo" -ui.api.loadError: "Não foi possível carregar os tipos. Recarregue esta página para tentar novamente." -ui.api.loadingNamespaces: "Carregando namespaces…" -ui.api.loadingTypes: "Carregando tipos…" -ui.api.matchingTypes: "Tipos correspondentes" -ui.api.namespace: "Namespace" -ui.api.namespaces: "Namespaces" -ui.api.noNamespaceTypes: "Nenhum tipo neste namespace." -ui.api.noTypes: "Nenhum tipo correspondente." -ui.api.types: "Tipos" -ui.content.reference: "Referência" -ui.content.source: "Código-fonte" -ui.content.tutorial: "Tutorial" -ui.contents.close: "Fechar sumário" -ui.contents.open: "Abrir sumário" -ui.contents.title: "Sumário" -ui.footer.caption: "RHI moderna para .NET" -ui.footer.label: "Rodapé" -ui.language.label: "Idioma" -ui.language.unavailable: "Não traduzido" -ui.members.clear: "Limpar busca de membros" -ui.members.close: "Fechar localizador de membros" -ui.members.empty: "Nenhum membro correspondente." -ui.members.open: "Ir para o membro" -ui.members.placeholder: "Nome ou assinatura…" -ui.members.search: "Buscar membros" -ui.members.title: "Localizar um membro" -ui.members.undeclared: "Este tipo não possui membros declarados." -ui.navigation.api: "API" -ui.navigation.concepts: "Conceitos" -ui.navigation.home: "Início" -ui.navigation.label: "Navegação principal" +concepts.execution.context.description: 'Um {graphicsContext} conecta a aplicação a um dispositivo GPU por meio de um backend específico e fornece suas filas gráfica, de computação e de transferência. Recursos usados em conjunto devem pertencer ao mesmo contexto; buffers, texturas, shaders, pipelines e seus identificadores não podem ser vinculados entre contextos diferentes.' +concepts.execution.context.details: '{capabilities} informa o nome do dispositivo e as funcionalidades disponíveis. Consulte {rayTracingSupported} e {meshShadingSupported} antes de criar os recursos necessários a essas operações. Os exemplos de {link} e {detail} fazem essas verificações durante a inicialização.' +concepts.execution.context.details.detail: 'sombreamento de malha' +concepts.execution.context.details.link: 'traçado de raios' +concepts.execution.context.title: 'Contexto gráfico' +concepts.execution.description: 'O trabalho da GPU é preparado na CPU: a aplicação cria recursos, registra comandos que os utilizam e envia esses comandos a uma fila. Após o envio, a CPU pode continuar enquanto a GPU executa o trabalho. Os recursos precisam permanecer disponíveis até o fim dessa execução.' +concepts.execution.ownership.description: 'A propriedade define quem libera um objeto; a conclusão do trabalho na GPU determina quando isso pode ocorrer. Chamar {dispose} libera os recursos nativos mesmo que ainda existam referências C# ao objeto. Enviar comandos não transfere à fila a propriedade dos recursos utilizados.' +concepts.execution.ownership.details: 'Ao encerrar a aplicação, pare de enviar trabalho e espere o último uso dos recursos em cada fila envolvida. Depois, libere os recursos da aplicação e o contexto. O contexto libera suas filas e estruturas auxiliares internas, portanto essa última etapa deve ocorrer após a conclusão de todo o trabalho da aplicação.' +concepts.execution.ownership.guidance: 'Durante a renderização, acompanhe a conclusão do trabalho que utiliza dados a serem sobrescritos ou recursos a serem substituídos. Espere esses usos terminarem antes de modificar ou liberar o armazenamento afetado. {link} explica como esse modelo de tempo de vida se aplica às visualizações e aos recursos que as sustentam.' +concepts.execution.ownership.guidance.link: 'Gerenciamento de recursos' +concepts.execution.ownership.table.applicationResources.object: 'Recursos criados pela aplicação' +concepts.execution.ownership.table.applicationResources.ownership: 'A aplicação os libera após o último uso na GPU.' +concepts.execution.ownership.table.commandBuffers.object: 'Buffers de comandos emprestados' +concepts.execution.ownership.table.commandBuffers.ownership: 'A fila os gerencia e recicla.' +concepts.execution.ownership.table.headings.object: 'Objeto' +concepts.execution.ownership.table.headings.ownership: 'Responsabilidade pela liberação' +concepts.execution.ownership.table.queues.object: 'Filas do contexto e suas linhas do tempo' +concepts.execution.ownership.table.queues.ownership: 'O contexto e as filas as gerenciam.' +concepts.execution.ownership.table.swapChainDrawable.ownership: 'A cadeia de troca o gerencia.' +concepts.execution.ownership.title: 'Responsabilidade e tempo de vida' +concepts.execution.pipelines.description: 'Um pipeline gráfico define os shaders, a disposição dos atributos de vértice, a montagem de primitivas, os formatos dos anexos e o estado usado nas operações de desenho. Selecione o pipeline antes de vincular dados de vértices, índices ou constantes. Os formatos dos anexos e a quantidade de amostras devem corresponder aos da passagem de renderização.' +concepts.execution.pipelines.details: 'Um pipeline de computação seleciona o ponto de entrada do shader executado por um despacho. Vincule o pipeline e suas constantes antes do despacho, fora de uma passagem de renderização gráfica.' +concepts.execution.pipelines.guidance: 'O {link} apresenta a sequência gráfica. O {detail} acrescenta um despacho de computação antes da passagem que exibe seu resultado.' +concepts.execution.pipelines.guidance.detail: 'exemplo de computação' +concepts.execution.pipelines.guidance.link: 'callback de renderização do triângulo' +concepts.execution.pipelines.title: 'Estado do pipeline' +concepts.execution.queues.description: 'A {graphicsQueue} costuma ser o ponto de partida para um quadro com desenho, computação e cópias. Manter operações dependentes na mesma fila simplifica a ordenação.' +concepts.execution.queues.details: 'Filas distintas permitem enviar cargas de trabalho independentes separadamente, mas nem sempre correspondem a mecanismos de hardware independentes. Use filas adicionais quando houver benefício em sobrepor a execução. Se uma fila utilizar dados produzidos por outra, estabeleça uma dependência explícita entre seus envios.' +concepts.execution.queues.guidance: 'Dentro de uma fila, operações dependentes também podem precisar de barreiras ou transições de textura para que os acessos posteriores vejam as escritas anteriores. Essas dependências de memória são diferentes da ordem de envio; {link} explica como expressá-las.' +concepts.execution.queues.guidance.link: 'Sincronização' +concepts.execution.queues.table.computeQueue.workToRecord: 'Despachos de computação e trabalho de transferência compatível, sem passagens de renderização gráfica.' +concepts.execution.queues.table.graphicsQueue.workToRecord: 'Passagens de renderização, desenho, computação e transferências.' +concepts.execution.queues.table.headings.queue: 'Fila' +concepts.execution.queues.table.headings.workToRecord: 'Operações aceitas' +concepts.execution.queues.table.transferQueue.workToRecord: 'Uploads, downloads e cópias, sem desenho ou despachos de computação.' +concepts.execution.queues.title: 'Seleção de filas' +concepts.execution.recording.context: 'A fila recupera os buffers de comandos concluídos para reutilizá-los. Obtenha um com {queueCommandBuffer} para cada registro de comandos, use uma thread por vez e envie-o uma única vez. Após o envio, deixe seu gerenciamento com a fila: não o modifique, envie novamente ou libere.' +concepts.execution.recording.description: '{queueCommandBuffer} retorna um {commandBuffer} já em gravação. Registre as operações e suas dependências e chame {submit} uma vez. O envio encerra a gravação e retorna um {timelineValue}, que identifica o ponto de conclusão naquela fila.' +concepts.execution.recording.details: 'Após registrar o quadro em {commandBuffer}, o tutorial do triângulo envia os comandos e aguarda a conclusão:' +concepts.execution.recording.guidance: 'O registro monta a sequência de comandos; {submit} agenda sua execução. A chamada seguinte a {wait} bloqueia a thread da CPU até esse envio terminar. Isso facilita a compreensão do loop do tutorial, pois cada quadro termina antes do início do próximo.' +concepts.execution.recording.title: 'Gravação e envio' +concepts.execution.title: 'Modelo de execução' +concepts.platforms.description: 'A apresentação pode ser gerenciada pela aplicação ou por um controle de interface. Essa escolha define quem obtém a textura de saída do quadro, registra e envia os comandos e apresenta o resultado. Essa textura de saída é o drawable.' +concepts.platforms.frame.context: 'Registre as vinculações de pipeline e os comandos de desenho dentro da passagem e encerre-a antes de o manipulador retornar. O controle envia os comandos e apresenta o resultado. O manipulador não deve enviar o buffer de comandos nem liberar qualquer um dos objetos recebidos. Se alterar o layout da textura de saída, restaure {colorAttachment} antes de retornar para que o controle realize a transição final.' +concepts.platforms.frame.description: 'Os controles implementam {iZenithView}. A aplicação atribui {graphicsContext}, atualiza a cena em {updateRequested} e registra comandos em {renderRequested} usando o {renderEventArgs} recebido.' +concepts.platforms.frame.details: 'A cada quadro, o controle obtém uma textura de saída e um buffer de comandos, faz a transição da textura para {colorAttachment} e chama os manipuladores de atualização e renderização. Depois, envia o trabalho registrado e apresenta a imagem pelo mecanismo do framework.' +concepts.platforms.frame.guidance: 'Adicione {usingZenithNET} ao arquivo. Para uma instância de {iZenithView} chamada {view}, já inicializada e com um contexto gráfico atribuído, registre este manipulador para limpar sua textura de saída:' +concepts.platforms.frame.notes: 'A transição inicial usa {undefined}, que permite descartar o conteúdo anterior da imagem. Desenhe ou limpe a imagem inteira a cada quadro. Mantenha resultados acumulados ou em cache em uma textura da aplicação e depois a desenhe na textura de saída do controle.' +concepts.platforms.frame.reference: '{zenithViewHelperDrawableFormat} fornece o formato de cor padrão dessas integrações.' +concepts.platforms.frame.title: 'Renderização em controles de interface' +concepts.platforms.integration.context: 'WinForms, WPF e a integração Windows do WinUI executam no Windows. Para MAUI, instale a carga de trabalho da plataforma de destino e registre o manipulador do controle com {useZenithView}, como mostra {extensionsCs}.' +concepts.platforms.integration.description: 'A interface de eventos é comum, mas o mecanismo de apresentação depende do framework:' +concepts.platforms.integration.details: 'Essas implementações diferem na forma de levar a imagem da GPU à interface. A leitura como bitmap copia os pixels para a memória da CPU antes da exibição. A interoperabilidade por texturas compartilhadas evita essa cópia, mas ainda pode exigir cópias na GPU e sincronização. Ao escolher uma integração, considere esse caminho de apresentação além do evento comum {renderRequested}.' +concepts.platforms.integration.guidance: 'Adicione pelo NuGet o pacote de integração correspondente ao seu framework de interface. Para Avalonia, use {avaloniaPackage}.' +concepts.platforms.integration.table.avalonia.integration: 'Avalonia' +concepts.platforms.integration.table.avalonia.presentation: 'Renderiza em uma textura e copia os pixels para a memória da CPU em {writeableBitmap}. Implementação: {zenithViewCs} e {surfaceCs}.' +concepts.platforms.integration.table.headings.integration: 'Integração' +concepts.platforms.integration.table.headings.presentation: 'Mecanismo de apresentação' +concepts.platforms.integration.table.maui.integration: '.NET MAUI' +concepts.platforms.integration.table.maui.presentation: 'Usa superfícies nativas no Android, iOS e Mac Catalyst, e composição de textura compartilhada no Windows. Consulte as {link}.' +concepts.platforms.integration.table.maui.presentation.link: 'implementações de plataforma' +concepts.platforms.integration.table.uno.integration: 'Caminho Uno' +concepts.platforms.integration.table.uno.presentation: 'Copia os pixels para a memória da CPU em {writeableBitmap}. Implementação: {zenithViewUnoCs}.' +concepts.platforms.integration.table.winForms.integration: 'WinForms' +concepts.platforms.integration.table.winForms.presentation: 'Cria uma cadeia de troca do Zenith.NET para o {hWND} do controle. Consulte {zenithViewCs}.' +concepts.platforms.integration.table.winUI.integration: 'WinUI no Windows' +concepts.platforms.integration.table.winUI.presentation: 'Renderiza em uma textura Direct3D 11 compartilhada importada e copia o resultado para uma cadeia de troca de composição conectada a {swapChainPanel}. Consulte {zenithViewWinUICs}.' +concepts.platforms.integration.table.wpf.integration: 'WPF' +concepts.platforms.integration.table.wpf.presentation: 'Importa uma textura Direct3D 11 compartilhada e copia seu conteúdo, por meio da interoperabilidade com Direct3D, para uma superfície exibida por {d3DImage}. Consulte {surfaceCs}.' +concepts.platforms.integration.title: 'Framework e apresentação' +concepts.platforms.lifecycle.context: 'Ao criar anexos compatíveis, use {descWidth}, {descHeight}, {descFormat} e {descSampleCount} da textura de saída fornecida pelo evento de renderização. Essa textura informa as dimensões reais do destino; elas não devem ser deduzidas do tamanho de layout do controle nem da escala de exibição.' +concepts.platforms.lifecycle.description: 'A cadeia de troca usa a largura e a altura do framebuffer em pixels, que podem diferir das dimensões lógicas da janela quando há escala de exibição. Adie a renderização e o redimensionamento da cadeia enquanto alguma dimensão for zero. Obtenha {swapChainDrawable} a cada quadro: a textura pertence à cadeia de troca, que pode substituí-la após apresentar ou redimensionar.' +concepts.platforms.lifecycle.details: 'Quando o tamanho do framebuffer mudar, espere os usos pendentes das imagens antigas na GPU antes de chamar {swapChainResize}. Para substituir o destino nativo de apresentação, aguarde esses usos da mesma forma e passe a nova descrição da superfície e seus identificadores a {swapChainRefresh}. No encerramento, libere a cadeia de troca antes de destruir seu destino nativo.' +concepts.platforms.lifecycle.guidance: 'Se a aplicação tiver texturas de profundidade ou fora da tela que acompanham o tamanho da janela, recrie-as quando esse tamanho mudar e atualize as constantes que contêm seus identificadores. O pipeline pode ser reutilizado enquanto os formatos e as quantidades de amostras dos anexos continuarem correspondentes. O {link} mostra essa separação entre as texturas redimensionadas e o pipeline reutilizável.' +concepts.platforms.lifecycle.guidance.link: 'renderizador de cubo giratório' +concepts.platforms.lifecycle.title: 'Dimensões e tempo de vida da cadeia de troca' +concepts.platforms.ownership.description: 'O contexto atribuído e os recursos de renderização pertencem à aplicação; os recursos de apresentação pertencem ao controle. Quando {graphicsContext} muda na visualização, o agendador recria os recursos do controle para o novo contexto. Recrie também os pipelines, buffers e texturas da aplicação para esse contexto.' +concepts.platforms.ownership.details: 'Antes de substituir recursos de renderização, interrompa o processamento de quadros da visualização e espere o trabalho da GPU que os utiliza. Só então libere os recursos ou o contexto antigos. Ao remover a visualização, a aplicação continua responsável por liberar o contexto atribuído a ela.' +concepts.platforms.ownership.guidance: 'O componente compartilhado {frameSchedulerCs} executa os manipuladores de quadro pelo dispatcher da interface. Concentre esses manipuladores na atualização da cena e no registro de comandos: um processamento prolongado na CPU também atrasa a resposta da interface.' +concepts.platforms.ownership.title: 'Responsabilidades da aplicação e do controle' +concepts.platforms.surface.description: 'O {link} usa Silk.NET para criar a janela e processar seus eventos. O Zenith.NET recebe os identificadores nativos e as dimensões em uma descrição {surface}, usada para criar uma {swapChain}. A aplicação continua responsável pela janela do sistema operacional.' +concepts.platforms.surface.description.link: 'tutorial do triângulo' +concepts.platforms.surface.details: 'Os identificadores da superfície devem corresponder ao backend:' +concepts.platforms.surface.guidance: 'O programa hospedeiro em {appCs} oferece suporte a Windows, macOS e X11. Sua janela Linux fornece identificadores Xlib, portanto uma sessão Wayland precisa de XWayland para executá-lo. Uma aplicação nativa de Wayland fornece os identificadores de display e superfície por meio de {surfaceWayland}.' +concepts.platforms.surface.table.android.backend: 'Vulkan no Android.' +concepts.platforms.surface.table.apple.backend: 'Metal nas plataformas Apple.' +concepts.platforms.surface.table.headings.backend: 'Backend e plataforma' +concepts.platforms.surface.table.headings.factory: 'Fábrica de superfícies' +concepts.platforms.surface.table.headings.handles: 'Identificadores fornecidos pelo programa hospedeiro' +concepts.platforms.surface.table.wayland.backend: 'Vulkan com um host nativo Wayland.' +concepts.platforms.surface.table.wayland.handles: 'Display e superfície Wayland' +concepts.platforms.surface.table.win32.backend: 'DirectX 12 ou Vulkan no Windows.' +concepts.platforms.surface.table.xlib.backend: 'Vulkan no Linux com X11 ou XWayland.' +concepts.platforms.surface.table.xlib.handles: 'Display e janela X11' +concepts.platforms.surface.title: 'Superfícies nativas de apresentação' +concepts.platforms.title: 'Integração de plataforma' +concepts.resources.allocation.context: 'Os recursos colocados em um heap dependem de seu armazenamento durante todo o tempo de vida. Depois do último uso na GPU, libere os recursos antes de liberar o heap.' +concepts.resources.allocation.description: 'Use um {heap} quando a aplicação precisar gerenciar as alocações por conta própria. Um heap fornece armazenamento no qual os recursos são colocados em deslocamentos explícitos em bytes; a aplicação escolhe esses deslocamentos e acompanha as regiões ocupadas.' +concepts.resources.allocation.details: 'Para cada recurso, chame {contextGetSizeAndAlignment} com a descrição de buffer ou textura que será usada na criação. Reserve o tamanho retornado em um deslocamento múltiplo do alinhamento informado, dentro dos limites do heap e sem sobrepor outra alocação ainda em uso. Texturas podem incluir preenchimento específico do backend; por isso, a quantidade de pixels e os bytes por pixel não bastam para calcular o tamanho da alocação.' +concepts.resources.allocation.guidance: 'Um buffer colocado em um heap deve declarar a mesma residência desse heap. Para armazenar texturas, use um heap exclusivo da GPU.' +concepts.resources.allocation.title: 'Alocação em heaps' +concepts.resources.bufferUsages.table.constant.role: 'Parâmetros de shader lidos por meio de uma vinculação de buffer de constantes.' +concepts.resources.bufferUsages.table.headings.role: 'Função' +concepts.resources.bufferUsages.table.headings.usage: 'Uso' +concepts.resources.bufferUsages.table.index.role: 'Índices usados pelo desenho indexado.' +concepts.resources.bufferUsages.table.indirect.role: 'Argumentos lidos por comandos de desenho ou despacho indiretos.' +concepts.resources.bufferUsages.table.none.role: 'Nenhum indicador de uso de buffer é declarado.' +concepts.resources.bufferUsages.table.storageReadOnly.role: 'Dados de buffer acessados por uma vinculação de shader somente leitura.' +concepts.resources.bufferUsages.table.storageReadWrite.role: 'Dados de buffer acessados por uma vinculação de shader de leitura e gravação.' +concepts.resources.bufferUsages.table.transferDst.role: 'Armazenamento de destino para uma cópia de GPU.' +concepts.resources.bufferUsages.table.transferSrc.role: 'Dados de origem para uma cópia de GPU.' +concepts.resources.bufferUsages.table.vertex.role: 'Atributos de vértice buscados para desenho.' +concepts.resources.bufferUsages.title: 'Usos de buffer' +concepts.resources.description: 'A descrição de um recurso define como a aplicação pode usar seu armazenamento. Por exemplo, uma textura usada como destino de renderização, amostrada por um shader e copiada de volta à CPU precisa dos indicadores de uso das três operações. A localização da memória determina o acesso da CPU; a sincronização e o gerenciamento do tempo de vida determinam quando os dados podem ser acessados ou o armazenamento liberado.' +concepts.resources.memory.context: 'Nos buffers acessíveis pela CPU, {map} fornece o endereço pelo qual os dados são lidos ou escritos. Nem o mapeamento nem {unmap} esperam o trabalho da GPU: antes de ler um resultado, a aplicação precisa esperar a escrita que o produz; antes de modificar os mesmos bytes, precisa esperar os acessos pendentes da GPU.' +concepts.resources.memory.description: 'O campo {residency} de {bufferDesc} especifica o acesso pretendido pela CPU:' +concepts.resources.memory.details: 'A residência expressa os requisitos de acesso da CPU, inclusive em sistemas em que CPU e GPU compartilham memória física. O triângulo utiliza {cpuWriteOnly} para inicializar diretamente seu pequeno buffer de vértices. Para geometrias estáticas maiores, pode ser mais adequado enviar os dados para armazenamento exclusivo da GPU.' +concepts.resources.memory.guidance: 'Texturas criadas diretamente pelo contexto usam armazenamento da GPU. Por isso, {textureDesc} não possui um campo de residência; a aplicação troca seus dados com a memória da CPU por meio de uploads e downloads.' +concepts.resources.memory.table.cpuReadOnly.cPUAccess: 'Somente leitura' +concepts.resources.memory.table.cpuReadOnly.typicalRole: 'Dados produzidos pela GPU para leitura na CPU' +concepts.resources.memory.table.cpuWriteOnly.cPUAccess: 'Somente escrita' +concepts.resources.memory.table.cpuWriteOnly.typicalRole: 'Dados fornecidos ou atualizados pela CPU' +concepts.resources.memory.table.gpuOnly.cPUAccess: 'Nenhum' +concepts.resources.memory.table.gpuOnly.typicalRole: 'Geometria estática e dados de trabalho da GPU' +concepts.resources.memory.table.headings.cPUAccess: 'Acesso previsto da CPU' +concepts.resources.memory.table.headings.residency: 'Residência' +concepts.resources.memory.table.headings.typicalRole: 'Função típica' +concepts.resources.memory.title: 'Acesso pela CPU e localização na memória' +concepts.resources.textureUsages.description: 'Os indicadores de transferência descrevem se o recurso é a origem ou o destino de uma cópia na GPU. A possibilidade de acesso direto pela CPU é uma decisão separada, tomada ao escolher a localização da memória.' +concepts.resources.textureUsages.details: 'Os indicadores de uso declaram as funções que uma textura pode desempenhar. Alternar entre elas exige os cuidados de {link} correspondentes, e o dispositivo escolhido deve oferecer suporte a esses usos para o formato da textura.' +concepts.resources.textureUsages.details.link: 'layout e sincronização' +concepts.resources.textureUsages.table.colorAttachment.role: 'Um anexo de cor em uma passagem de renderização.' +concepts.resources.textureUsages.table.depthStencilAttachment.role: 'Um anexo de profundidade e estêncil em uma passagem de renderização.' +concepts.resources.textureUsages.table.headings.role: 'Função' +concepts.resources.textureUsages.table.headings.usage: 'Uso' +concepts.resources.textureUsages.table.none.role: 'Nenhum indicador de uso de textura é declarado.' +concepts.resources.textureUsages.table.sampled.role: 'Dados de textura lidos por uma vinculação de textura amostrada.' +concepts.resources.textureUsages.table.storage.role: 'Dados de textura acessados por uma vinculação de textura de armazenamento para leituras ou gravações de shaders.' +concepts.resources.textureUsages.table.transferDst.role: 'Armazenamento da imagem de destino para uma cópia de GPU.' +concepts.resources.textureUsages.table.transferSrc.role: 'Dados da imagem de origem para uma cópia de GPU.' +concepts.resources.textureUsages.title: 'Usos de textura' +concepts.resources.title: 'Gerenciamento de recursos' +concepts.resources.transfers.context: 'Um download copia primeiro os dados da GPU para uma área interna de leitura. A biblioteca os copia para o destino de CPU fornecido quando recupera o buffer de comandos concluído. Chamar {wait} no valor de envio do download completa as duas etapas. Mantenha o destino alocado e a memória gerenciada fixada até o retorno dessa chamada.' +concepts.resources.transfers.description: 'Uploads copiam dados da CPU para um recurso da GPU; downloads copiam dados do recurso para a memória da CPU. Os métodos de buffers e texturas concluem essa transferência antes de retornar:' +concepts.resources.transfers.details: 'Antes de chamar esses métodos, resolva os acessos conflitantes em outras filas. A espera interna do método abrange sua própria transferência; ela não estabelece uma dependência de outra fila. Nas cópias diretas por memória mapeada, cabe inteiramente a quem chama esperar os acessos conflitantes da GPU.' +concepts.resources.transfers.guidance: 'Para enviar transferências junto com outro trabalho da GPU, registre-as com {commandBufferUpload} ou {commandBufferDownload}. A memória de origem de um upload e a de destino de um download precisam permanecer válidas por períodos diferentes:' +concepts.resources.transfers.item: 'Durante uma chamada de upload, a biblioteca copia os dados de origem para uma área temporária de transferência. A GPU lê dessa área posteriormente, portanto o ponteiro de origem da aplicação só é necessário até o retorno da chamada.' +concepts.resources.transfers.notes: 'Nas transferências de textura, o passo de linha é a distância em bytes entre linhas consecutivas dos dados da CPU; o passo de fatia é a distância entre fatias de profundidade consecutivas. Esses valores permitem copiar os dados entre sua organização na CPU e o armazenamento da textura na GPU. {link} explica por que concluir a cópia na GPU e entregar os dados ao destino de um download são etapas distintas.' +concepts.resources.transfers.notes.link: 'Sincronização' +concepts.resources.transfers.table.bufferDownload.transfer: 'Para {cpuReadOnly}, copia diretamente da memória mapeada. Nos demais casos, envia o download à fila de transferência e espera sua conclusão.' +concepts.resources.transfers.table.bufferUpload.transfer: 'Para {cpuWriteOnly}, copia diretamente para a memória mapeada. Nos demais casos, envia o upload à fila de transferência e espera sua conclusão.' +concepts.resources.transfers.table.headings.method: 'Método' +concepts.resources.transfers.table.headings.transfer: 'Comportamento da transferência' +concepts.resources.transfers.table.textureTransfers.method: '{textureUpload} / {textureDownload}' +concepts.resources.transfers.table.textureTransfers.transfer: 'Envia a cópia e as transições de textura à fila gráfica e espera sua conclusão. O sub-recurso selecionado fica no layout final solicitado.' +concepts.resources.transfers.title: 'Transferências imediatas e registradas' +concepts.resources.usages.description: '{bufferUsages} e {textureUsages} são enumerações de indicadores que declaram os usos de um recurso. Seus valores são atribuídos a {bufferDescUsages} e {textureDescUsages}, respectivamente. Para vários usos, combine os membros necessários com {value}.' +concepts.resources.usages.title: 'Usos de recursos' +concepts.resources.views.description: 'Uma {bufferView} descreve uma região de um buffer e a interpretação de seus dados. Uma {textureView} seleciona um intervalo de sub-recursos, com um tipo e formato de textura compatíveis. Ambas se referem ao armazenamento existente, com os usos declarados na criação. Os intervalos das visualizações descrevem o acesso, mas não garantem uma verificação de limites uniforme nos shaders de todos os backends.' +concepts.resources.views.details: 'O identificador do próprio recurso fornece sua visualização padrão. Crie uma visualização separada para escolher outra região ou uma interpretação compatível diferente. Mantenha vivos tanto a visualização quanto o recurso que a sustenta até a GPU terminar de utilizá-los; um identificador não mantém nenhum desses objetos vivo. Ao substituir qualquer um deles, atualize as constantes que contêm o {link} anterior.' +concepts.resources.views.details.link: 'identificador de recurso' +concepts.resources.views.title: 'Visualizações e recursos subjacentes' +concepts.shaders.binding.context: 'O exemplo de computação atribui {inputTextureSampledHandle} a {input} e {outputTextureStorageHandle} a {output}. Em Slang, o parâmetro de tipo de {descriptorHandle} define como o shader acessa cada recurso:' +concepts.shaders.binding.description: '{setConstantBuffer} seleciona um buffer existente e o deslocamento de byte a partir do qual o pipeline atual lê suas constantes. Envie os parâmetros para esse armazenamento antes de serem usados pelo shader. Se um trabalho anterior da GPU ainda estiver lendo os mesmos bytes, espere sua conclusão antes de atualizá-los.' +concepts.shaders.binding.details: 'Com o buffer de comandos, o pipeline de computação, o buffer de constantes preenchido e as quantidades de grupos de threads prontos, registre o despacho nesta ordem. Selecione primeiro o pipeline, pois a vinculação do buffer de constantes se aplica a ele:' +concepts.shaders.binding.guidance: 'Aqui, {commandBuffer} registra um despacho com {computePipeline} e os parâmetros armazenados em {constantBuffer}. O buffer precisa do uso {bufferUsagesConstant}, e o deslocamento 0 seleciona seu início. Se vários registros de constantes compartilharem um buffer, o deslocamento inicial de cada registro também deve atender ao alinhamento de vinculação do backend, independentemente do layout de seus campos internos.' +concepts.shaders.binding.notes: '{resourceHandle} contém dois campos de 32 bits cuja interpretação depende do backend. Seus valores são válidos apenas no contexto em que o recurso foi criado.' +concepts.shaders.binding.reference: 'Mantenha o recurso e a visualização usada para obter seu identificador até o último acesso do shader. A substituição exige atualizar constantes que ainda contenham o identificador antigo. {link} apresenta as regras de responsabilidade.' +concepts.shaders.binding.reference.link: 'Gerenciamento de recursos' +concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: 'Leitura de elementos estruturados do tipo {t} do shader' +concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: 'Leitura e escrita de elementos estruturados do tipo {t} do shader' +concepts.shaders.binding.table.headings.access: 'Acesso pretendido' +concepts.shaders.binding.table.headings.cHandle: 'Identificador C#' +concepts.shaders.binding.table.headings.slangFieldType: 'Tipo de campo Slang' +concepts.shaders.binding.table.samplerHandle.access: 'Estado de amostragem de texturas' +concepts.shaders.binding.table.textureSampledHandle.access: 'Leitura de texturas' +concepts.shaders.binding.table.textureStorageHandle.access: 'Leitura e escrita de texturas de armazenamento' +concepts.shaders.binding.title: 'Buffers de constantes e identificadores de recursos' +concepts.shaders.compilation.description: '{zenithCompiler} compila um ponto de entrada Slang em uma {shaderDesc}. O {graphicsApi} do contexto define o destino: DXIL para DirectX 12, biblioteca Metal para Metal ou SPIR-V para Vulkan.' +concepts.shaders.compilation.details: 'Com um contexto gráfico já criado e chamado {context}, compile o shader do triângulo a partir da cópia ao lado do executável:' +concepts.shaders.compilation.guidance: 'O nome do ponto de entrada {vSMain} deve corresponder à declaração no arquivo de shader. Compile os shaders e crie os pipelines na inicialização; depois, reutilize os pipelines durante a renderização. Após a criação dos pipelines, os objetos shader podem ser liberados, como mostra {link}.' +concepts.shaders.compilation.guidance.link: 'Primeiro triângulo' +concepts.shaders.compilation.title: 'Compilação de shaders' +concepts.shaders.description: 'As declarações em C# e Slang precisam concordar quanto à posição de cada valor e ao acesso feito pelo shader. Layouts de entrada descrevem os atributos dos vértices; declarações de buffers do shader descrevem parâmetros e arrays; identificadores apontam para os recursos usados pelo shader.' +concepts.shaders.dispatch.description: '{dispatch} especifica quantos grupos de threads serão executados. O exemplo de computação declara {numthreads}, portanto cada grupo contém 16 × 16 threads. Para cobrir uma imagem, divida a largura e a altura por 16 e arredonde cada resultado para cima: uma imagem de 17 × 19 precisa de 2 × 2 grupos. O shader verifica as coordenadas de cada thread e ignora as que ficam fora da imagem.' +concepts.shaders.dispatch.details: 'O tamanho de grupo declarado está disponível em {shaderDescThreadGroupSize} e permite calcular as quantidades de grupos passadas a {dispatch}. {computeShaderRendererCs} mostra o cálculo completo. Depois do despacho, o acesso à imagem resultante deve seguir os requisitos descritos em {link}.' +concepts.shaders.dispatch.details.link: 'Sincronização' +concepts.shaders.dispatch.title: 'Grupos de threads' +concepts.shaders.layout.context: 'As {link} ilustram essa organização com as dimensões de uma imagem e dois identificadores de textura. Deslocamentos explícitos indicam onde cada campo começa. A declaração usa {systemRuntimeInteropServices} e {zenithNET}:' +concepts.shaders.layout.context.link: 'constantes C# do exemplo de computação' +concepts.shaders.layout.description: 'Para a entrada de vértices, {inputLayout} descreve o formato, o deslocamento e a semântica de cada atributo, além do passo entre vértices. O triângulo coloca uma posição {float3} antes de uma cor {float4}: a cor começa no deslocamento de byte 12 e cada vértice ocupa 28 bytes. {inputLayoutAdd} calcula essa organização compacta a partir dos formatos. Se a estrutura C# contiver preenchimento, informe deslocamentos e um passo que o considerem.' +concepts.shaders.layout.details: 'Buffers de constantes contêm parâmetros do shader, e buffers estruturados contêm arrays de elementos tipados. Seus layouts seguem as declarações de Slang, e não {inputLayout}. Ajuste os deslocamentos dos campos, tamanhos dos elementos e preenchimento em C# ao layout do shader compilado. Um tipo não gerenciado de C# pode ser copiado byte a byte, mas seu layout na memória não corresponde necessariamente ao do shader; um {float3} armazenado sem preenchimento em um vértice pode exigir outro alinhamento em um buffer do shader.' +concepts.shaders.layout.guidance: 'Os parâmetros do shader podem incluir identificadores de recursos além de valores comuns. Um identificador aponta para armazenamento já existente, portanto copiá-lo para um buffer de constantes não copia o conteúdo do recurso.' +concepts.shaders.layout.notes: 'A declaração correspondente em {computeShaderSlang} é:' +concepts.shaders.layout.reference: 'As duas dimensões ocupam os primeiros oito bytes, seguidas de dois identificadores de oito bytes cada. O exemplo C# reserva 256 bytes para o registro completo. Para outros registros, determine o tamanho a partir de seus próprios campos e requisitos de layout e alinhamento.' +concepts.shaders.layout.title: 'Layout de dados' +concepts.shaders.matrices.description: 'O compilador usa armazenamento de matrizes por linhas, mantendo cada linha contígua. O {link} armazena três valores {matrix4x4} nos deslocamentos 0, 64 e 128. Seu {detail} aplica {mulVectorMatrix} na ordem modelo, visão e projeção.' +concepts.shaders.matrices.description.detail: 'shader' +concepts.shaders.matrices.description.link: 'renderizador de cubo giratório' +concepts.shaders.matrices.details: 'A ordem de armazenamento determina a disposição dos elementos da matriz na memória; a ordem de multiplicação determina a transformação. C# e Slang devem adotar convenções compatíveis.' +concepts.shaders.matrices.title: 'Convenções de matrizes' +concepts.shaders.title: 'Dados de shaders e vinculação' +concepts.synchronization.backends.description: 'DirectX 12 e Vulkan codificam as transições de textura como mudanças de layout e acesso. Em Metal, a implementação de {transition} do Zenith.NET não executa uma operação equivalente. O backend de Metal reúne os comandos em codificadores de renderização e computação e insere barreiras de visibilidade ao encerrar cada codificador. Operações dependentes no mesmo codificador, como despachos de computação sucessivos, usam chamadas explícitas a {barrier}.' +concepts.synchronization.backends.details: 'No {link}, iniciar a passagem gráfica encerra o codificador de computação e torna sua saída visível ao trabalho gráfico. Dois despachos consecutivos permanecem no mesmo codificador, portanto sua dependência exige uma barreira mesmo que haja uma transição de textura entre eles. Por isso, uma sequência de comandos portável deve considerar as dependências de acesso além dos layouts de textura.' +concepts.synchronization.backends.details.link: 'exemplo de computação' +concepts.synchronization.backends.title: 'Comportamento dos backends' +concepts.synchronization.barriers.context: 'Escolha etapas que incluam os acessos envolvidos e sejam compatíveis com a fila. {barrierStagesAll} inclui todas as etapas compatíveis; selecione um conjunto menor quando a dependência envolver apenas essas etapas.' +concepts.synchronization.barriers.description: 'Considere dois despachos de computação registrados no mesmo buffer de comandos: o primeiro escreve dados de simulação e o segundo os lê. Coloque uma barreira entre eles para que o segundo veja as escritas concluídas. Em um buffer de armazenamento, isso ordena os acessos sem uma transição de layout de textura:' +concepts.synchronization.barriers.details: 'O primeiro argumento identifica as etapas que produzem os dados; o segundo, as etapas que os consomem. Juntos, eles descrevem a ordem de execução e a visibilidade de memória necessárias entre os dois despachos.' +concepts.synchronization.barriers.guidance: 'A {link} usa esse padrão entre etapas da simulação. Cada barreira fica depois do despacho que produz os dados e antes daquele que os utiliza.' +concepts.synchronization.barriers.guidance.link: 'simulação FluidTank' +concepts.synchronization.barriers.title: 'Barreiras do pipeline' +concepts.synchronization.dependencies.description: 'Para cada recurso, identifique os acessos aos mesmos dados. Se algum deles escrever, preserve a ordem necessária entre as operações. Duas leituras não entram em conflito, embora os requisitos de layout de textura e apresentação continuem válidos. Atualizações pela CPU e a liberação de recursos também precisam esperar a GPU terminar de usar o armazenamento afetado.' +concepts.synchronization.dependencies.details: 'O mecanismo adequado depende de onde as operações são executadas:' +concepts.synchronization.dependencies.guidance: 'Uma carga de trabalho pode precisar de mais de um mecanismo. Por exemplo, uma textura produzida em outra fila precisa de uma dependência entre envios e do layout adequado para o próximo uso. Nenhuma dessas operações exige bloquear a CPU, a menos que ela própria precise acessar ou liberar os dados.' +concepts.synchronization.dependencies.table.cpuAccess.mechanism: 'Chamar {wait} no valor de conclusão relevante.' +concepts.synchronization.dependencies.table.cpuAccess.situation: 'O acesso da CPU ou a liberação de recursos depende da conclusão na GPU' +concepts.synchronization.dependencies.table.crossQueue.mechanism: 'Passe o {timelineValue} do produtor para o {submit} do consumidor.' +concepts.synchronization.dependencies.table.crossQueue.situation: 'Uma fila consome dados produzidos em outra' +concepts.synchronization.dependencies.table.headings.mechanism: 'Mecanismo' +concepts.synchronization.dependencies.table.headings.situation: 'Situação' +concepts.synchronization.dependencies.table.layoutChange.mechanism: '{commandBufferTransition} com seus layouts anterior e seguinte.' +concepts.synchronization.dependencies.table.layoutChange.situation: 'Um sub-recurso de textura altera como é usado' +concepts.synchronization.dependencies.table.pipelineStages.mechanism: '{commandBufferBarrier} com os estágios produtor e consumidor.' +concepts.synchronization.dependencies.table.pipelineStages.situation: 'Estágios dependentes da GPU em um fluxo de comandos' +concepts.synchronization.dependencies.title: 'Dependências de acesso' +concepts.synchronization.description: 'A sincronização estabelece a ordem de acesso aos dados compartilhados e garante que operações posteriores vejam os resultados necessários. Em uma dependência de escrita para leitura, quem escreve é o produtor e quem lê é o consumidor. Barreiras e transições de textura coordenam os acessos da GPU; linhas do tempo conectam envios e permitem que a CPU espere a conclusão do trabalho na GPU.' +concepts.synchronization.layouts.context: 'Use {undefined} como layout anterior quando o conteúdo existente puder ser descartado, como em uma imagem nova ou em um anexo que será limpo por completo. Para preservar o conteúdo para carregamento, amostragem ou acumulação, informe o layout do acesso anterior.' +concepts.synchronization.layouts.description: 'Os indicadores de uso declaram as funções permitidas da textura. {textureLayout} descreve o acesso a um sub-recurso, identificado pelo nível de mip e pela camada do array de texturas, em determinado ponto da sequência de comandos. Quando esse acesso mudar, registre uma transição. No exemplo de computação, a textura de saída é escrita em layout {storage} e depois preparada para amostragem em uma passagem gráfica:' +concepts.synchronization.layouts.details: 'Aqui, {outputTexture} foi criada com uso {sampledStorage}, e o sub-recurso selecionado está em {storage}. {default} seleciona o nível de mip 0 e a camada 0. A transição não afeta outros níveis ou camadas.' +concepts.synchronization.layouts.guidance: 'Em {transition}, informe o layout do uso anterior do sub-recurso. A aplicação acompanha esse estado ao registrar comandos e passar texturas entre as etapas de renderização.' +concepts.synchronization.layouts.title: 'Layouts de textura' +concepts.synchronization.readback.description: '{isCompleted} informa a conclusão na GPU. Um download registrado tem uma etapa adicional: copiar o resultado da área interna de leitura para a memória de destino da aplicação.' +concepts.synchronization.readback.details: '{commandBufferDownload} registra a cópia da GPU para essa área interna. Quando o envio termina, a biblioteca realiza a cópia na CPU ao recuperar o buffer de comandos concluído. Chamar {wait} no valor de envio do download espera a GPU e processa os buffers concluídos daquela fila, completando as duas etapas. Mantenha o destino alocado e a memória gerenciada fixada até o retorno da chamada.' +concepts.synchronization.readback.guidance: 'Consultar apenas {isCompleted} não executa a cópia final na CPU. Esperar em outra fila também não recupera os buffers concluídos da fila do download. {link} descreve quando uploads e downloads usam acesso direto à memória ou armazenamento temporário de transferência.' +concepts.synchronization.readback.guidance.link: 'Gerenciamento de recursos' +concepts.synchronization.readback.title: 'Conclusão da leitura de dados' +concepts.synchronization.reuse.description: 'O triângulo espera cada quadro terminar antes de reutilizar seus dados. Para sobrepor quadros, reserve armazenamento mutável próprio para cada quadro em andamento e acompanhe quando ele volta a estar disponível. Antes de modificar dados, espere o trabalho da GPU que ainda acessa os bytes afetados; antes de liberar um recurso, espere todos os seus usos pendentes.' +concepts.synchronization.reuse.details: 'Redimensionamento e encerramento seguem a mesma regra: impedir novos usos, esperar os existentes terminarem e então substituir ou liberar os recursos. Respeite essa ordem antes de chamar {swapChainResize} ou liberar recursos ou o contexto. Como o triângulo já espera a cada quadro, ele pode redimensionar entre as chamadas dos callbacks.' +concepts.synchronization.reuse.guidance: '{swapChainPresent} sinaliza um ponto da fila gráfica e espera por ele após a apresentação. Assim, o triângulo continua esperando ao apresentar, mesmo sem a espera explícita do envio. O trabalho independente em outras filas precisa de seu próprio acompanhamento de conclusão.' +concepts.synchronization.reuse.title: 'Reutilização de recursos' +concepts.synchronization.timelines.context: 'Se a CPU precisar ler o resultado, sobrescrever os dados compartilhados ou liberar os recursos após o consumidor terminar, espere esse envio:' +concepts.synchronization.timelines.description: 'Uma linha do tempo identifica a conclusão na fila por valores crescentes. {submit} retorna um {timelineValue} contendo a linha do tempo e o valor do envio. Campos {value} de linhas do tempo distintas não são diretamente comparáveis.' +concepts.synchronization.timelines.details: 'Considere {producer} e {consumer}, buffers já gravados em duas filas do mesmo contexto, com o consumidor usando dados escritos pelo produtor. Envie-os com esta dependência:' +concepts.synchronization.timelines.guidance: 'A fila consumidora espera o valor de conclusão recebido antes de executar seus comandos. A CPU pode continuar sem chamar {producedWait}. Mantenha os recursos compartilhados vivos até a conclusão de {consumed} e registre as transições de textura necessárias ao acesso do consumidor.' +concepts.synchronization.timelines.notes: 'O valor retornado por {queueTimelineSignal} também pode ser usado para esperar com {wait} ou estabelecer uma dependência para outra fila. {signal} coloca esse ponto de conclusão depois do trabalho já enviado; a GPU o alcança quando esse trabalho termina.' +concepts.synchronization.timelines.title: 'Linhas do tempo e dependências entre filas' +concepts.synchronization.title: 'Sincronização' +home.actions.reference: 'Navegar na API' +home.actions.tutorial: 'Começar com um triângulo' +home.entries.description: 'Tutoriais, exemplos e referência da API' +home.entries.label: 'Seções da documentação' +home.entries.reference.action: 'Explorar a API' +home.entries.reference.category: 'Referência' +home.entries.reference.description: 'Consulte tipos, membros e declarações da API' +home.entries.reference.title: 'Referência da API' +home.entries.samples.action: 'Procurar exemplos' +home.entries.samples.category: 'Exemplos' +home.entries.samples.description: 'Exemplos executáveis de técnicas gráficas e de computação' +home.entries.samples.title: 'Exemplos' +home.entries.title: 'Documentação' +home.entries.tutorial.action: 'Iniciar tutorial' +home.entries.tutorial.category: 'Tutorial' +home.entries.tutorial.description: 'De um projeto vazio ao primeiro triângulo na tela' +home.entries.tutorial.title: 'Primeiro triângulo' +home.introduction.accent: 'com .NET' +home.introduction.description: 'Zenith.NET oferece uma API comum de gráficos e computação para DirectX, Metal e Vulkan' +home.introduction.title: 'Gráficos multiplataforma{lineBreak}{accent}' +home.meta.description: 'Gráficos e computação multiplataforma em .NET com uma API comum para DirectX, Metal e Vulkan' +home.scene.description: 'Geometria interativa em rotação. Arraste ou use as teclas de direção para ajustar a visualização.' +home.scene.label: 'Exibição de geometria' +home.scene.surface: 'Superfície' +home.scene.wireframe: 'Wireframe' +home.title: 'RHI moderna para .NET' +learning.concepts.description: 'Critérios para escolher usos de recursos, descrever dados de shaders e coordenar a execução na GPU' +learning.concepts.execution.description: 'Gravação de comandos, envio e tempo de vida dos recursos' +learning.concepts.platforms.description: 'Apresentação nativa e controles de renderização' +learning.concepts.resources.description: 'Usos de recursos, localização na memória e visualizações' +learning.concepts.shaders.description: 'Convenções de layout e vinculação entre C# e Slang' +learning.concepts.synchronization.description: 'Dependências, visibilidade e conclusão' +learning.concepts.title: 'Conceitos fundamentais' +learning.description: 'Comece pelo tutorial do triângulo para criar sua primeira aplicação. Depois, consulte os artigos sobre recursos, dados de shaders e sincronização, ou escolha um exemplo da técnica que deseja implementar.' +learning.entries.samples.action: 'Procurar exemplos' +learning.entries.samples.description: 'Implementações em C# e Slang de geometria, computação, consultas de raios e sombreamento de malha' +learning.entries.tutorial.action: 'Abrir tutorial' +learning.entries.tutorial.description: 'Uma aplicação de console que abre uma janela e renderiza um triângulo' +learning.meta.description: 'Tutoriais e fundamentos do modelo de programação de Zenith.NET' +learning.title: 'Aprender' +reference.description: 'Referência de recursos, comandos e integrações de plataforma' +reference.entries.commands.description: 'Comandos gráficos, de computação e de transferência' +reference.entries.commands.label: 'Registrar comandos' +reference.entries.context.description: 'Criação de recursos da GPU no backend selecionado' +reference.entries.context.label: 'Comece aqui' +reference.meta.description: 'Namespaces, tipos e membros de Zenith.NET' +reference.navigation.core: 'Referência da API principal' +reference.title: 'Referência da API' +samples.computeShader.description: 'O exemplo carrega {assetsTexturesShokoPng}, converte a imagem para tons de cinza em um despacho de computação e exibe a textura resultante. A conversão ocorre uma vez; os quadros seguintes exibem o mesmo resultado. O renderizador mostra como vincular texturas para amostragem e escrita, arredondar para cima as quantidades de grupos de threads para cobrir a imagem e verificar seus limites no shader.' +samples.computeShader.details: '{computeShaderRendererCs} · {computeShaderSlang}' +samples.computeShader.title: 'Shader de computação' +samples.cube.description: 'O cubo acrescenta desenho indexado, matrizes de modelo, visão e projeção em um buffer de constantes e teste de profundidade. Sua textura de profundidade e estêncil {d32FloatS8UInt} é recriada no redimensionamento.' +samples.cube.details: '{spinningCubeRendererCs} · {spinningCubeSlang}' +samples.cube.title: 'Cubo giratório' +samples.description: 'Cada exemplo reúne um renderizador C# e seu shader Slang em torno de uma técnica. Para a configuração completa da aplicação e a sequência de renderização, comece por {link}.' +samples.description.link: 'Primeiro triângulo' +samples.execution.description: 'Execute o projeto {link} e escolha um exemplo no menu do console.' +samples.execution.description.link: 'ZenithTutorials' +samples.execution.title: 'Execução dos exemplos' +samples.host.description: '{appCs} inicializa contexto, janela e cadeia de troca. A cada quadro, obtém um buffer de comandos, chama o renderizador selecionado, envia os comandos e apresenta o resultado. {iRendererCs} define as operações de atualização, renderização, redimensionamento e liberação.' +samples.host.details: 'Os renderizadores de computação e traçado de raios produzem texturas fora da tela. {texturePresenterCs} e {presentTextureSlang} desenham essas texturas na saída do quadro atual; em seguida, o programa hospedeiro compartilhado envia os comandos e apresenta o quadro.' +samples.host.title: 'Programa hospedeiro e apresentação' +samples.indirectDrawing.description: 'O desenho indireto renderiza várias instâncias de cubos a partir de um buffer de argumentos de desenho indexado e de um buffer estruturado de dados por instância. A CPU fornece os argumentos e atualiza as transformações.' +samples.indirectDrawing.details: '{indirectDrawingRendererCs} · {indirectDrawingSlang}' +samples.indirectDrawing.title: 'Desenho indireto' +samples.meshShading.description: 'Um shader de tarefa descarta as instâncias de esferas não visíveis e passa os índices restantes ao shader de malha, que gera a geometria. O renderizador verifica {contextCapabilitiesMeshShadingSupported} antes de criar o pipeline.' +samples.meshShading.details: '{meshShadingRendererCs} · {meshShadingSlang}' +samples.meshShading.title: 'Sombreamento de malha' +samples.rayTracing.description: 'O exemplo cria estruturas de aceleração de nível inferior e superior para um piso e esferas procedurais e realiza consultas de raios em um shader de computação. Verifica {contextCapabilitiesRayTracingSupported} antes da inicialização.' +samples.rayTracing.details: '{rayTracingRendererCs} · {rayTracingSlang}' +samples.rayTracing.title: 'Traçado de raios' +samples.title: 'Exemplos' +samples.triangle.description: 'O triângulo associa um buffer de vértices ao layout de entrada correspondente e desenha três vértices por um pipeline gráfico.' +samples.triangle.details: '{helloTriangleRendererCs} · {helloTriangleSlang} · {link}' +samples.triangle.details.link: 'Tutorial completo' +samples.triangle.title: 'Olá triângulo' +samples.workloads.description: 'O {link} do repositório principal contém aplicações de maior porte que referenciam o código-fonte da biblioteca.' +samples.workloads.description.link: 'diretório Experiments' +samples.workloads.details: 'Os experimentos com janela usam os mesmos mecanismos de apresentação em Windows, macOS e Linux/X11. {link} trata dos controles para Avalonia, WinForms, WPF, WinUI/Uno e MAUI, incluindo o ciclo dos quadros e as implementações.' +samples.workloads.details.link: 'Integração de plataforma' +samples.workloads.table.cornellBox.example: '{link}' +samples.workloads.table.cornellBox.example.link: 'CornellBox' +samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: 'Traçado de caminhos, redução de ruído, mapeamento de tons, ampliação de resolução e controles ImGui. Requer suporte a traçado de raios.' +samples.workloads.table.fluidTank.example: '{link}' +samples.workloads.table.fluidTank.example.link: 'FluidTank' +samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: 'Simulação de fluidos por computação, dependências entre estágios de simulação e renderização de superfície em várias passagens.' +samples.workloads.table.headings.example: 'Exemplo' +samples.workloads.table.headings.whatItDemonstratesAndRequires: 'Técnicas e requisitos' +samples.workloads.table.inkCanvas.example: '{link}' +samples.workloads.table.inkCanvas.example.link: 'InkCanvas' +samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: 'Desenho com Skia e tratamento de entrada em uma janela nativa. Requer o backend e a biblioteca nativa do Skia para a plataforma de destino.' +samples.workloads.table.platformDetection.example: '{link}' +samples.workloads.table.platformDetection.example.link: 'PlatformDetection' +samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: 'Tenta criar um contexto para cada backend e informa as capacidades do dispositivo. Uma tentativa que falha é indicada como não compatível; a causa pode estar no dispositivo, no driver ou em uma dependência de execução ausente.' +samples.workloads.title: 'Aplicações de maior porte' +tutorial.context.description: 'Um {graphicsContext} conecta a aplicação à GPU por meio de um backend e fornece os métodos para criar os recursos de renderização.' +tutorial.context.details: 'Insira a inicialização do contexto {emphasis}:' +tutorial.context.details.emphasis: 'após as diretivas using, antes de {iWindowWindow}' +tutorial.context.guidance: 'Cada ramo seleciona o backend da plataforma e solicita a validação. As mensagens de {validationMessage} são exibidas no console.' +tutorial.context.imports: 'Adicione as seguintes diretivas using no início de {programCs}:' +tutorial.context.title: 'Contexto gráfico' +tutorial.description: 'Neste tutorial, um projeto de console .NET vazio se torna uma aplicação que abre uma janela e desenha um triângulo colorido.' +tutorial.details: 'O tutorial tem três pontos de verificação: uma janela vazia, um fundo de cor uniforme e o triângulo colorido. Execute a aplicação em cada ponto antes de acrescentar a próxima parte.' +tutorial.draw.context: 'Os argumentos para {draw} são:' +tutorial.draw.description: 'No callback {windowRender}, substitua {addTheTriangleDrawCommandsHereLater} pelos comandos abaixo, entre {beginRenderPass} e {endRenderPass}:' +tutorial.draw.details: '{setPipeline} seleciona shaders e estado de renderização. Deve preceder o vínculo dos vértices, pois o backend interpreta esse vínculo conforme o layout de entrada do pipeline.' +tutorial.draw.guidance: '{setVertexBufferVertexBuffer} vincula os dados de vértices já transferidos, a partir do deslocamento de byte 0, ao slot de entrada 0, correspondente à única entrada de {inputLayouts}.' +tutorial.draw.notes: 'Essas chamadas registram os comandos de desenho. A chamada existente a {submitWait} os envia e espera a GPU terminar; em seguida, {present} solicita a exibição da imagem concluída. Mantenha a limpeza no início da passagem para definir a cor de fundo na área externa ao triângulo.' +tutorial.draw.table.firstInstance.meaning: 'Iniciar a numeração de instâncias em zero.' +tutorial.draw.table.firstVertex.meaning: 'Começar com o primeiro vértice no buffer.' +tutorial.draw.table.headings.argument: 'Argumento' +tutorial.draw.table.headings.description: 'Valor' +tutorial.draw.table.headings.meaning: 'Significado' +tutorial.draw.table.instanceCount.meaning: 'Desenhar uma cópia do triângulo.' +tutorial.draw.table.vertexCount.meaning: 'Ler três vértices.' +tutorial.draw.title: 'Comandos de desenho' +tutorial.execution.description: 'Compile e execute o projeto {firstTriangle}.' +tutorial.execution.details: 'A janela deve exibir um triângulo sobre fundo escuro, vermelho no alto, verde embaixo à direita e azul embaixo à esquerda. A interpolação das cores dos vértices forma um gradiente suave em seu interior.' +tutorial.execution.guidance: 'O redimensionamento muda as dimensões da imagem em pixels, mas mantém as coordenadas dos vértices. O viewport ajusta essas coordenadas à nova largura e altura, por isso o triângulo se deforma quando a proporção da janela muda.' +tutorial.execution.title: 'Execução da aplicação' +tutorial.frame.commands.context: 'Após {endRenderPass}, a segunda transição prepara a textura de saída para apresentação. {submit} encerra o registro e envia o buffer de comandos; {wait} bloqueia a thread até a conclusão desse envio. Em seguida, {present} solicita a exibição da imagem renderizada.' +tutorial.frame.commands.description: 'Uma passagem de renderização reúne operações de desenho que escrevem nos mesmos anexos. Nesta passagem, a textura de saída da cadeia de troca recebe a cor. {colorAttachmentClear} descreve como inicializar esse anexo com uma cor RGBA e preservar seu conteúdo ao encerrar a passagem. {beginRenderPass} registra o início da passagem com essas configurações.' +tutorial.frame.commands.details: 'A coleção contém um anexo de cor. {null} indica que a passagem não possui anexo de profundidade e estêncil.' +tutorial.frame.commands.guidance: '{beginRenderPass} ajusta o viewport e a região de recorte para todo o anexo. O viewport converte coordenadas de renderização em posições de pixels; o recorte limita a região em que se pode escrever.' +tutorial.frame.commands.title: 'Limpeza, envio e apresentação' +tutorial.frame.description: 'Comece preenchendo a janela com uma cor de fundo. Essa operação é chamada de limpeza. Quando o fundo aparece, a superfície, o envio de comandos e a apresentação já funcionam juntos. A partir daí, acrescente os vértices e os shaders do triângulo.' +tutorial.frame.details: 'Silk.NET chama o callback quando há um quadro a renderizar. Como o exemplo não usa o argumento de tempo decorrido, o parâmetro se chama {value}. Registre o callback {emphasis}:' +tutorial.frame.details.emphasis: 'antes de {windowRun}' +tutorial.frame.target.description: '{graphicsQueueCommandBuffer} retorna um buffer pronto para gravação. Gravar define o trabalho da GPU; sua execução só começa após o envio.' +tutorial.frame.target.details: 'O layout de uma textura descreve o acesso necessário a uma operação. A primeira chamada a {transition} prepara a textura de saída para uso como anexo de cor. Aqui, {default} seleciona o nível de mip 0 e a camada 0 do array, ou seja, a imagem base da textura. Como a passagem limpa a imagem inteira, {undefined} permite descartar o conteúdo anterior.' +tutorial.frame.target.guidance: 'Obtenha a textura de saída atual a cada quadro, pois a apresentação pode passar a usar outra imagem.' +tutorial.frame.target.title: 'Preparação da textura de saída' +tutorial.frame.title: 'O primeiro quadro' +tutorial.geometry.data.description: 'Adicione o array de vértices {emphasis}. Mantenha também as próximas inicializações de recursos antes desse callback, na ordem apresentada.' +tutorial.geometry.data.description.emphasis: 'antes de {windowRender}' +tutorial.geometry.data.details: 'Cada entrada constrói um {vertex}; os dois {new} internos fornecem a posição {vector3} e a cor {vector4}. As posições formam os cantos superior, inferior direito e inferior esquerdo. O shader de vértices acrescenta {w} como quarta coordenada. Com w igual a 1, x e y também são coordenadas normalizadas de dispositivo: -1 e +1 marcam os limites da imagem, e 0, o centro. Sua interpretação independe da quantidade de pixels.' +tutorial.geometry.data.guidance: 'Cada cor tem componentes vermelho, verde, azul e alfa, com alfa igual a 1. Os três vértices têm z = 0 e estão no mesmo plano.' +tutorial.geometry.data.title: 'Posições e cores dos vértices' +tutorial.geometry.description: 'Cada um dos três vértices tem posição e cor. A GPU determina a forma do triângulo a partir das posições e interpola as cores em sua superfície.' +tutorial.geometry.format.description: 'Acrescente a declaração do vértice {emphasis}:' +tutorial.geometry.format.description.emphasis: 'no final de {programCs}, após as instruções de limpeza' +tutorial.geometry.format.details: '{file} restringe o tipo a {programCs}, e {layoutKindSequential} mantém os campos na ordem de declaração. {position} contém três valores de ponto flutuante de 32 bits e começa no deslocamento de byte 0; {color} contém quatro e começa no deslocamento de byte 12. Cada vértice ocupa, portanto, 28 bytes. O layout de entrada descreverá essa organização para que a GPU leia os campos corretamente.' +tutorial.geometry.format.imports: 'Adicione estas diretivas using no início de {programCs} para usar os tipos vetoriais e o atributo de layout da estrutura:' +tutorial.geometry.format.title: 'Representação dos vértices' +tutorial.geometry.title: 'Dados de vértices' +tutorial.geometry.upload.context: '{fixed} impede que o coletor de lixo mova o array enquanto seu endereço estiver em uso. Neste buffer gravável pela CPU, {upload} mapeia a memória, copia os bytes e desfaz o mapeamento antes de retornar. O array só precisa permanecer fixado durante a chamada. Envie os vértices uma vez na inicialização e mantenha o buffer vivo até o fim da renderização.' +tutorial.geometry.upload.description: 'Armazene os vértices em um {buffer} para que a GPU possa lê-los durante o desenho. Acrescente a alocação e o envio dos dados logo após o array:' +tutorial.geometry.upload.details: 'O tamanho é {sizeofVertexVerticesLength}: três vértices de 28 bytes, ou 84 bytes. {bufferUsagesVertex} declara o uso como entrada de vértices, e {cpuWriteOnly} permite a inicialização direta pela CPU. O passo do descritor registra o tamanho do elemento. O layout definido adiante especifica como cada atributo será lido.' +tutorial.geometry.upload.guidance: 'A alocação não inicializa o conteúdo do buffer. {upload} copia o array para o deslocamento 0 do destino, usando o ponteiro de origem e a quantidade de bytes da descrição de dados.' +tutorial.geometry.upload.imports: 'Em {programCs}, adicione {bufferAlias} às diretivas using para distinguir o tipo de buffer do Zenith.NET de {systemBuffer}.' +tutorial.geometry.upload.notes: 'Na limpeza ao final de {programCs}, insira {vertexBufferDispose} imediatamente antes de {swapChainDispose}. {link} trata do armazenamento exclusivo da GPU e de transferências para geometria estática maior.' +tutorial.geometry.upload.notes.link: 'Gerenciamento de recursos' +tutorial.geometry.upload.title: 'Alocação e transferência do buffer' +tutorial.input.description: 'A GPU precisa saber onde estão os atributos de cada vértice, como posição e cor. O layout de entrada fornece o formato e o deslocamento de cada atributo, além do passo: a distância em bytes até o próximo vértice. Adicione este código após criar os shaders:' +tutorial.input.details: '{inputLayoutAdd} coloca cada atributo após o anterior e soma seu tamanho ao passo entre vértices. Os deslocamentos são calculados a partir dos formatos informados, sem inspecionar a estrutura C#. Para esses dois campos, o resultado é:' +tutorial.input.guidance: 'O valor padrão de {semanticIndex} é zero, correspondente a {pOSITION0} e {cOLOR0} no shader. Posição e cor ficam juntas em um buffer de vértices, portanto o pipeline utiliza um único layout de entrada no slot 0. Se a ordem dos campos ou o preenchimento da estrutura C# mudar, ajuste também esse layout.' +tutorial.input.table.headings.byteOffset: 'Deslocamento de bytes' +tutorial.input.table.headings.cField: 'Campo C#' +tutorial.input.table.headings.format: 'Formato' +tutorial.input.table.headings.shaderInput: 'Entrada do shader' +tutorial.input.table.nextVertex.cField: 'Próximo vértice' +tutorial.input.table.nextVertex.format: 'Passo total: 28 bytes' +tutorial.input.table.nextVertex.shaderInput: 'Próximo registro de entrada' +tutorial.input.table.vertexColor.format: '{float4} (16 bytes)' +tutorial.input.table.vertexPosition.format: '{float3} (12 bytes)' +tutorial.input.title: 'Layout de entrada dos vértices' +tutorial.lifecycle.description: 'Cada quadro segue esta sequência:' +tutorial.lifecycle.details: 'Quando a janela fecha, {run} retorna e a execução continua no código de limpeza. Como cada quadro já esperou seus comandos terminarem, os recursos usados por eles podem ser liberados. O bloco completo de limpeza após {windowRun} é:' +tutorial.lifecycle.guidance: 'Libere a cadeia de troca antes de destruir sua janela nativa e o contexto depois de seus recursos. A fila recicla os buffers de comandos enviados, e a cadeia de troca gerencia a textura de saída; nenhum deles precisa de uma chamada separada a {dispose}.' +tutorial.lifecycle.title: 'Ciclo dos quadros e liberação' +tutorial.pipeline.behavior: 'Após o layout de entrada, crie o pipeline:' +tutorial.pipeline.context: '{cullNone} desativa o descarte de faces, de modo que o triângulo seja desenhado tanto com os vértices em sentido horário quanto em sentido anti-horário.' +tutorial.pipeline.description: 'Um {graphicsPipeline} reúne o layout dos vértices, os dois shaders e as configurações de montagem de primitivas e escrita nos anexos.' +tutorial.pipeline.details: 'Os shaders processam vértices e fragmentos. As demais configurações do pipeline controlam a montagem de primitivas, o descarte de faces, o teste de profundidade e a mesclagem de cores:' +tutorial.pipeline.guidance: 'O formato de cor do pipeline deve corresponder ao anexo da passagem, por isso é obtido de {swapChainDescFormat}. {count1} especifica uma amostra por pixel.' +tutorial.pipeline.item: '{triangleList} monta um triângulo a cada grupo de três vértices consecutivos.' +tutorial.pipeline.notes: '{depthNone} desativa teste e escrita de profundidade, de acordo com a ausência desse anexo.' +tutorial.pipeline.reference: '{opaque} desativa a mesclagem. A saída do shader de fragmentos substitui, portanto, a cor de fundo dentro do triângulo.' +tutorial.pipeline.title: 'Pipeline gráfico' +tutorial.pipeline.usage: 'Os objetos de shader podem ser liberados após a criação do pipeline. Mantenha o pipeline durante a renderização e adicione {pipelineDispose} antes de {vertexBufferDispose} na limpeza.' +tutorial.presentation.title: 'Contexto gráfico e apresentação' +tutorial.project.context: 'Ative {emphasis} ({allowUnsafeBlocks}) nas opções de compilação do projeto. As chamadas nativas do auxiliar de janela e a transferência de vértices exigem código não seguro.' +tutorial.project.context.emphasis: 'Permitir código não seguro' +tutorial.project.description: 'Crie um projeto de console C# chamado {firstTriangle}, com .NET 10 como framework de destino.' +tutorial.project.details: 'Adicione os seguintes pacotes NuGet ao projeto:' +tutorial.project.guidance: '{zenithNET} fornece a API comum de renderização; os três pacotes de backend, suas implementações. {zenithNETCompiler} compila os shaders Slang apresentados adiante para o backend selecionado. Silk.NET cria a janela e processa eventos.' +tutorial.project.title: 'Configuração do projeto' +tutorial.requirements.context: 'O {link} e seu {detail} fornecem as implementações de referência deste tutorial.' +tutorial.requirements.context.detail: 'programa hospedeiro' +tutorial.requirements.context.link: 'exemplo Olá triângulo' +tutorial.requirements.description: 'São necessários o {emphasis} e conhecimentos básicos de C#. A aplicação tem {net10} como destino. A GPU e o driver devem oferecer suporte ao backend escolhido para sua plataforma:' +tutorial.requirements.description.emphasis: 'SDK do .NET 10' +tutorial.requirements.guidance: 'Zenith.NET renderiza em uma superfície nativa fornecida pela aplicação. Silk.NET.Windowing cria a janela e processa seus eventos. No macOS, a apresentação usa uma camada Metal, representada por {cAMetalLayerCs}, que o auxiliar associa à janela.' +tutorial.requirements.table.headings.graphicsBackend: 'Backend gráfico' +tutorial.requirements.table.headings.platform: 'Plataforma' +tutorial.requirements.table.linux.graphicsBackend: 'Vulkan 1.4' +tutorial.requirements.table.linux.platform: 'Linux (X11 ou XWayland)' +tutorial.requirements.table.macOS.graphicsBackend: 'Metal 4' +tutorial.requirements.table.macOS.platform: 'macOS' +tutorial.requirements.table.windows.graphicsBackend: 'DirectX 12' +tutorial.requirements.table.windows.platform: 'Windows' +tutorial.requirements.title: 'Pré-requisitos' +tutorial.resize.context: 'Compile e execute a aplicação novamente. O fundo deve continuar preenchendo a janela quando ela for redimensionada: cada nova passagem ajusta o viewport e o retângulo de recorte às dimensões do anexo. Mantenha o callback de renderização; o triângulo será desenhado dentro dessa mesma passagem.' +tutorial.resize.description: 'A cadeia de troca precisa acompanhar as mudanças de tamanho do framebuffer. Registre um callback de {framebufferResize} depois do callback de renderização e antes de {windowRun}:' +tutorial.resize.details: 'Responda às {link}, medidas em pixels, em vez de às mudanças no tamanho lógico da janela. Se minimizar a janela fizer alguma dimensão chegar a zero, o callback de redimensionamento mantém a cadeia de troca como está. O callback de renderização também retorna enquanto alguma dimensão for zero, interrompendo a renderização até que o framebuffer volte a ter um tamanho utilizável.' +tutorial.resize.details.link: 'alterações no tamanho do framebuffer' +tutorial.resize.guidance: 'O callback de renderização espera cada quadro enviado terminar antes de chamar {present}. Assim, o callback de redimensionamento pode substituir as imagens da cadeia de troca sem interromper o trabalho de um quadro anterior. O artigo {link} detalha essa relação entre a conclusão do trabalho e o tempo de vida dos recursos.' +tutorial.resize.guidance.link: 'Sincronização' +tutorial.resize.title: 'Redimensionamento' +tutorial.shaders.compilation.context: '{appContextBaseDirectory} permite carregar a cópia do shader no diretório de saída da aplicação. Assim, iniciar a aplicação a partir de outro diretório de trabalho não altera o local em que ela procura o arquivo.' +tutorial.shaders.compilation.description: 'Nas propriedades de {triangleSlang}, defina {emphasis} como {detail}. A compilação copiará o shader para o diretório do executável.' +tutorial.shaders.compilation.description.detail: 'Copiar se mais recente' +tutorial.shaders.compilation.description.emphasis: 'Copiar para o Diretório de Saída' +tutorial.shaders.compilation.details: 'Em {programCs}, acrescente a inicialização dos shaders após a transferência dos vértices e antes do callback de renderização:' +tutorial.shaders.compilation.guidance: '{zenithCompiler} compila o código-fonte para {contextGraphicsApi}, e {createShader} cria um objeto shader a partir da descrição compilada. Os nomes de ponto de entrada {vSMain} e {fSMain} selecionam as duas funções definidas no arquivo Slang.' +tutorial.shaders.compilation.title: 'Compilação dos shaders' +tutorial.shaders.context: '{fSInput} conecta as duas etapas do shader. O shader de vértices escreve em {sVPOSITION} uma posição no espaço de recorte, que a GPU usa para determinar a parte visível do triângulo. O campo {cOLOR0} leva a cor do vértice, interpolada ao longo do triângulo antes de chegar ao shader de fragmentos. Seu tipo e sua semântica devem corresponder nas duas etapas.' +tutorial.shaders.description: 'Shaders são programas executados na GPU. O shader de vértices determina a posição de cada vértice, e o shader de fragmentos determina a cor em cada posição coberta da imagem. As duas etapas serão escritas em um único arquivo Slang, cada uma com seu ponto de entrada: a função em que a execução começa.' +tutorial.shaders.details: 'Crie {triangleSlang} com estas estruturas de entrada e saída:' +tutorial.shaders.fragment.description: 'Acrescente o ponto de entrada de fragmentos ao mesmo arquivo:' +tutorial.shaders.fragment.details: 'A rasterização identifica as posições da imagem cobertas pelo triângulo e gera fragmentos para elas. Cada fragmento recebe uma cor interpolada a partir das cores dos três vértices. {fSMain} retorna essa cor, e {sVTARGET} direciona o resultado ao primeiro anexo de cor.' +tutorial.shaders.fragment.title: 'Sombreamento de fragmentos' +tutorial.shaders.guidance: '{vSInput} define as entradas do shader de vértices. {pOSITION0} e {cOLOR0} identificam os atributos por semântica; nomes de campos em C# não estabelecem sozinhos essa correspondência.' +tutorial.shaders.title: 'Estágios dos shaders' +tutorial.shaders.vertex.description: 'Acrescente o ponto de entrada de vértices a {triangleSlang}:' +tutorial.shaders.vertex.details: 'A GPU executa esse ponto de entrada para cada vértice. Ele acrescenta a coordenada homogênea {w} e repassa a cor. Após o processamento dos vértices, a posição é dividida por w. Como w vale 1, x, y e z permanecem iguais e podem ser interpretados como coordenadas normalizadas de dispositivo.' +tutorial.shaders.vertex.title: 'Sombreamento de vértices' +tutorial.surface.description: 'Especifique o destino nativo de apresentação {emphasis}:' +tutorial.surface.description.emphasis: 'após {windowCenter} e antes de {windowRun}' +tutorial.surface.details: 'O framebuffer é a imagem da janela em pixels. {surface} descreve o destino nativo de apresentação e suas dimensões; {framebufferSize} fornece o tamanho em pixels. Com a escala da tela, esse tamanho pode diferir das dimensões lógicas da janela.' +tutorial.surface.guidance: 'A superfície fornece os identificadores nativos do backend: uma janela Win32 no Windows, display e janela X11 no Linux ou a camada Metal associada no macOS.' +tutorial.surface.title: 'Superfície nativa' +tutorial.swapChain.context: 'A cadeia de troca depende do contexto e da janela. Substitua {windowDispose} no final de {programCs} por esta ordem de liberação:' +tutorial.swapChain.description: 'Crie a cadeia de troca logo após a descrição da superfície:' +tutorial.swapChain.details: 'A {swapChain} gerencia as imagens apresentadas pela janela. {drawable} fornece a imagem atual como uma {texture}, o recurso de imagem da API. Após a renderização, {present} solicita sua exibição e avança para a próxima textura de saída.' +tutorial.swapChain.guidance: '{b8G8R8A8UNorm} armazena quatro canais de 8 bits na ordem azul, verde, vermelho e alfa. {uNorm} mapeia os inteiros de 0–255 para 0–1. A saída do shader continua sendo um valor RGBA lógico; o formato define sua representação no armazenamento. O pipeline usará {swapChainDescFormat} para corresponder a esse anexo.' +tutorial.swapChain.title: 'Cadeia de troca' +tutorial.title: 'Primeiro triângulo' +tutorial.troubleshooting.description: 'Use os diagnósticos do console e os três pontos de verificação para localizar a etapa com falha:' +tutorial.troubleshooting.details: 'O {link} e o {detail} servem de referência para dados de vértices, layout e desenho. O exemplo separa janela e envio em um programa hospedeiro comum; este tutorial mantém o fluxo em {programCs}. O {context} introduz desenho indexado, transformações e teste de profundidade.' +tutorial.troubleshooting.details.context: 'Cubo giratório' +tutorial.troubleshooting.details.detail: 'shader Slang' +tutorial.troubleshooting.details.link: 'renderizador de exemplo' +tutorial.troubleshooting.table.backend.check: 'Verifique se o backend selecionado é suportado pelo dispositivo e pelo driver gráfico instalado.' +tutorial.troubleshooting.table.backend.symptom: 'Falha na criação do backend' +tutorial.troubleshooting.table.drawing.check: 'Verifique o tamanho do upload, o layout de entrada, a seleção de pipeline e o posicionamento dos comandos de desenho dentro da passagem de renderização.' +tutorial.troubleshooting.table.drawing.symptom: 'O fundo aparece, mas o triângulo não' +tutorial.troubleshooting.table.headings.check: 'Verificação' +tutorial.troubleshooting.table.headings.symptom: 'Sintoma' +tutorial.troubleshooting.table.input.check: 'Verifique o passo de 28 bytes e os deslocamentos de posição/cor de 0 e 12.' +tutorial.troubleshooting.table.input.symptom: 'Posições ou cores dos vértices estão corrompidas' +tutorial.troubleshooting.table.shaders.check: 'Verifique o {triangleSlang} copiado, a ortografia do ponto de entrada e o diagnóstico relatado pelo compilador.' +tutorial.troubleshooting.table.shaders.symptom: 'O fundo aparece, mas o carregamento dos shaders falha' +tutorial.troubleshooting.table.window.check: 'Confirme se o projeto .NET compila e se a etapa somente de janela é executada em uma sessão de desktop. No Linux, verifique se o X11 ou XWayland está disponível.' +tutorial.troubleshooting.table.window.symptom: 'Nenhuma janela se abre' +tutorial.troubleshooting.title: 'Diagnóstico de problemas' +tutorial.window.description: 'Baixe {cocoaHelperCs} para o diretório do projeto. Essa classe auxiliar conecta a camada Metal à janela do macOS.' +tutorial.window.details: 'Substitua o conteúdo gerado de {programCs} pelo código abaixo. Ele usa instruções de nível superior, executadas em ordem sem um método {main} explícito. As próximas seções indicarão onde acrescentar cada trecho:' +tutorial.window.guidance: '{graphicsAPINone} deixa a criação do contexto gráfico a cargo de Zenith.NET. {initialize} cria a janela nativa e disponibiliza os identificadores do sistema de janelas. {center} a coloca no centro da tela. {run} processa eventos até seu fechamento; depois, {dispose} libera a janela.' +tutorial.window.notes: 'Compile e execute a aplicação. Verifique se a janela abre e fecha normalmente e se é possível movê-la e redimensioná-la. O conteúdo ainda não está definido, pois nenhum comando de renderização foi enviado. Feche a janela antes de continuar.' +tutorial.window.title: 'Criação da janela' +ui.action.copy: 'Copiar' +ui.action.navigate: 'Navegar' +ui.action.open: 'Abrir' +ui.action.source: 'Ver código-fonte' +ui.api.browse: 'Navegar por namespaces e tipos.' +ui.api.clearTypeSearch: 'Limpar busca de tipos' +ui.api.findType: 'Localizar um tipo' +ui.api.loadError: 'Não foi possível carregar os tipos. Recarregue esta página para tentar novamente.' +ui.api.loadingNamespaces: 'Carregando namespaces…' +ui.api.loadingTypes: 'Carregando tipos…' +ui.api.matchingTypes: 'Tipos correspondentes' +ui.api.namespace: 'Namespace' +ui.api.namespaces: 'Namespaces' +ui.api.noNamespaceTypes: 'Nenhum tipo neste namespace.' +ui.api.noTypes: 'Nenhum tipo correspondente.' +ui.api.types: 'Tipos' +ui.content.reference: 'Referência' +ui.content.source: 'Código-fonte' +ui.content.tutorial: 'Tutorial' +ui.contents.close: 'Fechar sumário' +ui.contents.open: 'Abrir sumário' +ui.contents.title: 'Sumário' +ui.footer.caption: 'RHI moderna para .NET' +ui.footer.label: 'Rodapé' +ui.language.label: 'Idioma' +ui.language.unavailable: 'Não traduzido' +ui.members.clear: 'Limpar busca de membros' +ui.members.close: 'Fechar localizador de membros' +ui.members.empty: 'Nenhum membro correspondente.' +ui.members.open: 'Ir para o membro' +ui.members.placeholder: 'Nome ou assinatura…' +ui.members.search: 'Buscar membros' +ui.members.title: 'Localizar um membro' +ui.members.undeclared: 'Este tipo não possui membros declarados.' +ui.navigation.api: 'API' +ui.navigation.concepts: 'Conceitos' +ui.navigation.home: 'Início' +ui.navigation.label: 'Navegação principal' ui.navigation.skip: Ir para o conteúdo -ui.navigation.toggle: "Alternar navegação" -ui.outline.title: "Nesta página" -ui.reference.assembly: "Assembly" -ui.reference.classes: "Classes" -ui.reference.constructors: "Construtores" -ui.reference.declaration: "Declaração de tipo C#" -ui.reference.delegates: "Delegados" -ui.reference.derived: "Tipos derivados" -ui.reference.enums: "Enumerações" -ui.reference.events: "Eventos" -ui.reference.examples: "Exemplos" -ui.reference.exceptions: "Exceções" -ui.reference.extensionMethods: "Métodos de extensão" -ui.reference.fields: "Campos" -ui.reference.implementations: "Implementações explícitas de interface" -ui.reference.implements: "Implementa" -ui.reference.inheritance: "Herança" -ui.reference.inheritedMembers: "Membros herdados" -ui.reference.interfaces: "Interfaces" -ui.reference.metadata: "Metadados do tipo" -ui.reference.methods: "Métodos" -ui.reference.namespace: "Namespace" -ui.reference.open: "Abrir referência para {name}" -ui.reference.operators: "Operadores" -ui.reference.parameters: "Parâmetros" -ui.reference.properties: "Propriedades" -ui.reference.related: "Consulte também" -ui.reference.relationships: "Herança e metadados" -ui.reference.remarks: "Comentários" -ui.reference.returns: "Retornos" -ui.reference.structs: "Estruturas" -ui.reference.typeParameters: "Parâmetros de tipo" -ui.reference.value: "Valor" -ui.reference.values: "Valores" -ui.search.close: "Fechar busca" -ui.search.empty: "Nenhum resultado para “{query}”." -ui.search.hint: "Pesquise tutoriais, conceitos, exemplos e a referência da API." -ui.search.loading: "Carregando busca…" -ui.search.more: "Mostrar mais resultados" -ui.search.pending: "Buscando…" -ui.search.placeholder: "O que você está procurando?" -ui.search.resultCount: "Resultados: {count}" -ui.search.title: "Pesquisar documentação" -ui.search.unavailable: "A busca não está disponível. Você ainda pode abrir as páginas abaixo." +ui.navigation.toggle: 'Alternar navegação' +ui.outline.title: 'Nesta página' +ui.reference.assembly: 'Assembly' +ui.reference.classes: 'Classes' +ui.reference.constructors: 'Construtores' +ui.reference.declaration: 'Declaração de tipo C#' +ui.reference.delegates: 'Delegados' +ui.reference.derived: 'Tipos derivados' +ui.reference.enums: 'Enumerações' +ui.reference.events: 'Eventos' +ui.reference.examples: 'Exemplos' +ui.reference.exceptions: 'Exceções' +ui.reference.extensionMethods: 'Métodos de extensão' +ui.reference.fields: 'Campos' +ui.reference.implementations: 'Implementações explícitas de interface' +ui.reference.implements: 'Implementa' +ui.reference.inheritance: 'Herança' +ui.reference.inheritedMembers: 'Membros herdados' +ui.reference.interfaces: 'Interfaces' +ui.reference.metadata: 'Metadados do tipo' +ui.reference.methods: 'Métodos' +ui.reference.namespace: 'Namespace' +ui.reference.open: 'Abrir referência para {name}' +ui.reference.operators: 'Operadores' +ui.reference.parameters: 'Parâmetros' +ui.reference.properties: 'Propriedades' +ui.reference.related: 'Consulte também' +ui.reference.relationships: 'Herança e metadados' +ui.reference.remarks: 'Comentários' +ui.reference.returns: 'Retornos' +ui.reference.structs: 'Estruturas' +ui.reference.typeParameters: 'Parâmetros de tipo' +ui.reference.value: 'Valor' +ui.reference.values: 'Valores' +ui.search.close: 'Fechar busca' +ui.search.empty: 'Nenhum resultado para “{query}”.' +ui.search.hint: 'Pesquise tutoriais, conceitos, exemplos e a referência da API.' +ui.search.loading: 'Carregando busca…' +ui.search.more: 'Mostrar mais resultados' +ui.search.pending: 'Buscando…' +ui.search.placeholder: 'O que você está procurando?' +ui.search.resultCount: 'Resultados: {count}' +ui.search.title: 'Pesquisar documentação' +ui.search.unavailable: 'A busca não está disponível. Você ainda pode abrir as páginas abaixo.' diff --git a/documents/locales/pt-BR/translation.md b/documents/locales/pt-BR/translation.md index 71505a78..8d55ed34 100644 --- a/documents/locales/pt-BR/translation.md +++ b/documents/locales/pt-BR/translation.md @@ -2,7 +2,7 @@ ## Recursos e estrutura -O [dicionário de recursos em inglês](../en-US/strings.yml) é a única fonte do texto. Consulte as regras do projeto no [guia de manutenção da documentação](../../authoring.md). Para iniciar uma tradução, copie o arquivo inglês completo para `strings.yml` neste diretório. Preserve a primeira linha `### YamlMime:Resources` e a codificação UTF-8. Nas atualizações, incorpore as mudanças do original sem sobrescrever as traduções existentes. Este arquivo `translation.md` permanece no diretório e não é publicado no site. +O [dicionário de recursos em inglês](../en-US/strings.yml) é a única fonte do texto. Consulte as regras do projeto no [guia de manutenção da documentação](../../maintenance.md). Para iniciar uma tradução, copie o arquivo inglês completo para `strings.yml` neste diretório. Preserve a primeira linha `### YamlMime:Resources` e a codificação UTF-8. Nas atualizações, incorpore as mudanças do original sem sobrescrever as traduções existentes. Este arquivo `translation.md` permanece no diretório e não é publicado no site. Navegação, ordem dos capítulos, âncoras, links, formatação, código e imagens são mantidos fora de `locales/` e compartilhados entre idiomas. Não adicione artigos, TOC, templates, scripts ou configurações neste diretório. @@ -65,21 +65,21 @@ Antes de entregar, confira as chaves e os marcadores. Revise a página inicial, ## Terminologia -| Termo em inglês | Forma adotada | -| --- | --- | -| API / GPU / RHI | Preservar as siglas e explicá-las conforme o original | -| barrier | barreira | -| buffer | buffer; preservar `Buffer` | -| command buffer | buffer de comandos | -| command queue | fila de comandos | -| drawable | textura de saída do quadro atual; preservar `Drawable`, sem presumir que seja uma imagem da cadeia de troca | -| graphics context | contexto gráfico | -| pipeline | pipeline | -| readback | leitura de dados da GPU | -| render pass | passagem de renderização | -| resource | recurso | -| shader | shader | -| swap chain | cadeia de troca | -| texture | textura | -| timeline | linha do tempo | -| upload | envio de dados à GPU | +| Termo em inglês | Forma adotada | +| ---------------- | ----------------------------------------------------------------------------------------------------------- | +| API / GPU / RHI | Preservar as siglas e explicá-las conforme o original | +| barrier | barreira | +| buffer | buffer; preservar `Buffer` | +| command buffer | buffer de comandos | +| command queue | fila de comandos | +| drawable | textura de saída do quadro atual; preservar `Drawable`, sem presumir que seja uma imagem da cadeia de troca | +| graphics context | contexto gráfico | +| pipeline | pipeline | +| readback | leitura de dados da GPU | +| render pass | passagem de renderização | +| resource | recurso | +| shader | shader | +| swap chain | cadeia de troca | +| texture | textura | +| timeline | linha do tempo | +| upload | envio de dados à GPU | diff --git a/documents/locales/ru-RU/strings.yml b/documents/locales/ru-RU/strings.yml index c1dc26df..9ccc4f3b 100644 --- a/documents/locales/ru-RU/strings.yml +++ b/documents/locales/ru-RU/strings.yml @@ -1,62 +1,62 @@ ### YamlMime:Resources -concepts.execution.context.description: "{graphicsContext} связывает приложение с устройством GPU через определённый бэкенд и предоставляет его графическую, вычислительную и передающую очереди. Совместно используемые ресурсы должны принадлежать одному контексту: буферы, текстуры, шейдеры, конвейеры и их дескрипторы нельзя привязывать между разными контекстами." -concepts.execution.context.details: "{capabilities} сообщает имя устройства и поддерживаемые возможности. Перед созданием ресурсов для трассировки лучей или меш-шейдинга проверяйте соответственно {rayTracingSupported} и {meshShadingSupported}. Такие проверки при инициализации показаны в примерах {link} и {detail}." -concepts.execution.context.details.detail: "меш-шейдинга" +concepts.execution.context.description: '{graphicsContext} связывает приложение с устройством GPU через определённый бэкенд и предоставляет его графическую, вычислительную и передающую очереди. Совместно используемые ресурсы должны принадлежать одному контексту: буферы, текстуры, шейдеры, конвейеры и их дескрипторы нельзя привязывать между разными контекстами.' +concepts.execution.context.details: '{capabilities} сообщает имя устройства и поддерживаемые возможности. Перед созданием ресурсов для трассировки лучей или меш-шейдинга проверяйте соответственно {rayTracingSupported} и {meshShadingSupported}. Такие проверки при инициализации показаны в примерах {link} и {detail}.' +concepts.execution.context.details.detail: 'меш-шейдинга' concepts.execution.context.details.link: трассировки лучей -concepts.execution.context.title: "Графический контекст" -concepts.execution.description: "Подготовка работы GPU начинается на CPU: приложение создаёт ресурсы, записывает команды, которые их используют, и отправляет команды в очередь. После отправки CPU может продолжать работу, пока GPU выполняет команды. Нужные им ресурсы должны оставаться доступными до завершения выполнения." -concepts.execution.ownership.description: "Владение определяет, кто освобождает объект, а завершение работы GPU — когда его можно освободить. Вызов {dispose} освобождает нативные ресурсы, даже если ссылки C# на объект ещё существуют. Отправка команд не передаёт очереди владение их ресурсами." -concepts.execution.ownership.details: "При завершении приложения прекратите новые отправки и дождитесь последнего использования ресурсов во всех задействованных очередях. Затем освободите ресурсы приложения и контекст. Контекст освобождает свои очереди и внутренние вспомогательные объекты, поэтому этот последний шаг должен выполняться после завершения работы приложения с GPU." -concepts.execution.ownership.guidance: "Во время рендеринга отслеживайте завершение обращений к данным, которые предстоит перезаписать, или к ресурсам, которые предстоит заменить. Прежде чем изменять или освобождать память, дождитесь окончания этих обращений. Время жизни представлений и лежащих в их основе ресурсов описано в статье «{link}»." +concepts.execution.context.title: 'Графический контекст' +concepts.execution.description: 'Подготовка работы GPU начинается на CPU: приложение создаёт ресурсы, записывает команды, которые их используют, и отправляет команды в очередь. После отправки CPU может продолжать работу, пока GPU выполняет команды. Нужные им ресурсы должны оставаться доступными до завершения выполнения.' +concepts.execution.ownership.description: 'Владение определяет, кто освобождает объект, а завершение работы GPU — когда его можно освободить. Вызов {dispose} освобождает нативные ресурсы, даже если ссылки C# на объект ещё существуют. Отправка команд не передаёт очереди владение их ресурсами.' +concepts.execution.ownership.details: 'При завершении приложения прекратите новые отправки и дождитесь последнего использования ресурсов во всех задействованных очередях. Затем освободите ресурсы приложения и контекст. Контекст освобождает свои очереди и внутренние вспомогательные объекты, поэтому этот последний шаг должен выполняться после завершения работы приложения с GPU.' +concepts.execution.ownership.guidance: 'Во время рендеринга отслеживайте завершение обращений к данным, которые предстоит перезаписать, или к ресурсам, которые предстоит заменить. Прежде чем изменять или освобождать память, дождитесь окончания этих обращений. Время жизни представлений и лежащих в их основе ресурсов описано в статье «{link}».' concepts.execution.ownership.guidance.link: Управление ресурсами concepts.execution.ownership.table.applicationResources.object: Ресурсы, созданные приложением concepts.execution.ownership.table.applicationResources.ownership: Приложение освобождает их после последнего использования на GPU. -concepts.execution.ownership.table.commandBuffers.object: "Заимствованные буферы команд" +concepts.execution.ownership.table.commandBuffers.object: 'Заимствованные буферы команд' concepts.execution.ownership.table.commandBuffers.ownership: Очередь управляет ими и повторно использует их. concepts.execution.ownership.table.headings.object: Объект -concepts.execution.ownership.table.headings.ownership: "Ответственность за освобождение" +concepts.execution.ownership.table.headings.ownership: 'Ответственность за освобождение' concepts.execution.ownership.table.queues.object: Очереди контекста и их временные шкалы concepts.execution.ownership.table.queues.ownership: Контекст и очереди управляют ими. concepts.execution.ownership.table.swapChainDrawable.ownership: Цепочка обмена управляет ею. -concepts.execution.ownership.title: "Владение и время жизни" -concepts.execution.pipelines.description: "Графический конвейер задаёт шейдеры, формат вершинных данных, сборку примитивов, форматы вложений и состояние для команд рисования. Выберите конвейер до привязки вершин, индексов и констант. Форматы вложений и число выборок должны соответствовать проходу рендеринга." -concepts.execution.pipelines.details: "Вычислительный конвейер выбирает точку входа шейдера для запуска вычислений. Привяжите конвейер и его константы перед запуском, вне графического прохода рендеринга." -concepts.execution.pipelines.guidance: "Последовательность графических команд разобрана в {link}. В {detail} перед графическим проходом добавляется вычисление изображения, которое затем выводится на экран." -concepts.execution.pipelines.guidance.detail: "вычислительном примере" -concepts.execution.pipelines.guidance.link: "обработчике рендеринга треугольника" -concepts.execution.pipelines.title: "Состояние конвейера" -concepts.execution.queues.description: "{graphicsQueue} обычно подходит для кадра, объединяющего рисование, вычисления и копирование. Размещение зависимых операций в одной очереди упрощает их упорядочивание." -concepts.execution.queues.details: "Отдельные очереди позволяют независимо отправлять разные задачи, но не обязательно соответствуют независимым аппаратным блокам. Дополнительные очереди полезны, если задачи могут выиграть от перекрытия выполнения. Когда одна очередь использует данные другой, между их отправками нужна явная зависимость." -concepts.execution.queues.guidance: "Даже в одной очереди зависимым операциям могут понадобиться барьеры или переходы состояния текстур, чтобы последующие обращения видели результаты предыдущих записей. Эти зависимости по памяти отличаются от порядка отправки команд. Как их задавать, описано в статье «{link}»." +concepts.execution.ownership.title: 'Владение и время жизни' +concepts.execution.pipelines.description: 'Графический конвейер задаёт шейдеры, формат вершинных данных, сборку примитивов, форматы вложений и состояние для команд рисования. Выберите конвейер до привязки вершин, индексов и констант. Форматы вложений и число выборок должны соответствовать проходу рендеринга.' +concepts.execution.pipelines.details: 'Вычислительный конвейер выбирает точку входа шейдера для запуска вычислений. Привяжите конвейер и его константы перед запуском, вне графического прохода рендеринга.' +concepts.execution.pipelines.guidance: 'Последовательность графических команд разобрана в {link}. В {detail} перед графическим проходом добавляется вычисление изображения, которое затем выводится на экран.' +concepts.execution.pipelines.guidance.detail: 'вычислительном примере' +concepts.execution.pipelines.guidance.link: 'обработчике рендеринга треугольника' +concepts.execution.pipelines.title: 'Состояние конвейера' +concepts.execution.queues.description: '{graphicsQueue} обычно подходит для кадра, объединяющего рисование, вычисления и копирование. Размещение зависимых операций в одной очереди упрощает их упорядочивание.' +concepts.execution.queues.details: 'Отдельные очереди позволяют независимо отправлять разные задачи, но не обязательно соответствуют независимым аппаратным блокам. Дополнительные очереди полезны, если задачи могут выиграть от перекрытия выполнения. Когда одна очередь использует данные другой, между их отправками нужна явная зависимость.' +concepts.execution.queues.guidance: 'Даже в одной очереди зависимым операциям могут понадобиться барьеры или переходы состояния текстур, чтобы последующие обращения видели результаты предыдущих записей. Эти зависимости по памяти отличаются от порядка отправки команд. Как их задавать, описано в статье «{link}».' concepts.execution.queues.guidance.link: Синхронизация -concepts.execution.queues.table.computeQueue.workToRecord: "Запуск вычислений и совместимые операции передачи данных, без графических проходов рендеринга." -concepts.execution.queues.table.graphicsQueue.workToRecord: "Проходы рендеринга, рисование, вычисления и передача данных." +concepts.execution.queues.table.computeQueue.workToRecord: 'Запуск вычислений и совместимые операции передачи данных, без графических проходов рендеринга.' +concepts.execution.queues.table.graphicsQueue.workToRecord: 'Проходы рендеринга, рисование, вычисления и передача данных.' concepts.execution.queues.table.headings.queue: Очередь -concepts.execution.queues.table.headings.workToRecord: "Поддерживаемые операции" -concepts.execution.queues.table.transferQueue.workToRecord: "Загрузка, считывание и копирование без рисования и вычислительных запусков." -concepts.execution.queues.title: "Выбор очереди" -concepts.execution.recording.context: "Очередь возвращает завершённые командные буферы для повторного использования. Для каждой записи получите буфер через {queueCommandBuffer}, записывайте его только из одного потока одновременно и отправьте один раз. После отправки оставьте управление очереди: не изменяйте буфер, не отправляйте его повторно и не освобождайте самостоятельно." -concepts.execution.recording.description: "{queueCommandBuffer} возвращает {commandBuffer}, уже открытый для записи. Запишите операции и зависимости, затем один раз вызовите {submit}. Вызов завершает запись и возвращает {timelineValue}, обозначающий точку завершения в этой очереди." -concepts.execution.recording.details: "После записи кадра в {commandBuffer} учебный пример отправляет команды и ожидает завершения:" -concepts.execution.recording.guidance: "Запись формирует последовательность команд, а {submit} планирует её выполнение. Последующий вызов {wait} блокирует поток CPU до завершения отправленной работы. Поэтому цикл кадров в уроке легко проследить: каждый кадр заканчивается до начала следующего." -concepts.execution.recording.title: "Запись и отправка команд" +concepts.execution.queues.table.headings.workToRecord: 'Поддерживаемые операции' +concepts.execution.queues.table.transferQueue.workToRecord: 'Загрузка, считывание и копирование без рисования и вычислительных запусков.' +concepts.execution.queues.title: 'Выбор очереди' +concepts.execution.recording.context: 'Очередь возвращает завершённые командные буферы для повторного использования. Для каждой записи получите буфер через {queueCommandBuffer}, записывайте его только из одного потока одновременно и отправьте один раз. После отправки оставьте управление очереди: не изменяйте буфер, не отправляйте его повторно и не освобождайте самостоятельно.' +concepts.execution.recording.description: '{queueCommandBuffer} возвращает {commandBuffer}, уже открытый для записи. Запишите операции и зависимости, затем один раз вызовите {submit}. Вызов завершает запись и возвращает {timelineValue}, обозначающий точку завершения в этой очереди.' +concepts.execution.recording.details: 'После записи кадра в {commandBuffer} учебный пример отправляет команды и ожидает завершения:' +concepts.execution.recording.guidance: 'Запись формирует последовательность команд, а {submit} планирует её выполнение. Последующий вызов {wait} блокирует поток CPU до завершения отправленной работы. Поэтому цикл кадров в уроке легко проследить: каждый кадр заканчивается до начала следующего.' +concepts.execution.recording.title: 'Запись и отправка команд' concepts.execution.title: Модель выполнения -concepts.platforms.description: "Выводом управляет приложение или элемент интерфейса. От этого зависит, кто получает выходную текстуру кадра, записывает и отправляет команды и выводит результат. Эта выходная текстура называется drawable." -concepts.platforms.frame.context: "Записывайте привязку конвейера и команды рисования внутри прохода и завершайте его до возврата из обработчика. Элемент управления сам отправит команды и выведет результат. Обработчик не должен отправлять командный буфер или освобождать любой из двух предоставленных объектов. Если он меняет состояние выходной текстуры, перед возвратом нужно восстановить {colorAttachment}, чтобы элемент управления выполнил заключительный переход." -concepts.platforms.frame.description: "Элементы реализуют {iZenithView}. Приложение назначает {graphicsContext}, обновляет сцену в {updateRequested} и записывает команды в {renderRequested}, используя переданный {renderEventArgs}." -concepts.platforms.frame.details: "Для каждого кадра элемент управления получает выходную текстуру и командный буфер, переводит текстуру в {colorAttachment} и вызывает обработчики обновления и рендеринга. Затем он отправляет записанные команды и выводит изображение средствами выбранного UI-фреймворка." -concepts.platforms.frame.guidance: "Добавьте {usingZenithNET} в файл. Для инициализированного {iZenithView} с именем {view} и назначенным графическим контекстом зарегистрируйте обработчик, заполняющий выходную текстуру цветом:" -concepts.platforms.frame.notes: "Первый переход использует {undefined}, разрешая отбросить прежнее содержимое изображения. Поэтому каждый кадр должен заново заполнять или отрисовывать всё изображение. Накопленные или кешированные результаты храните в текстуре приложения, а затем рисуйте её в выходную текстуру элемента управления." -concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat} предоставляет цветовой формат, используемый по умолчанию в этих интеграциях." -concepts.platforms.frame.title: "Рендеринг в элементах интерфейса" -concepts.platforms.integration.context: "WinForms, WPF и Windows-интеграция WinUI работают под Windows. Для MAUI установите рабочую нагрузку целевой платформы и зарегистрируйте обработчик элемента управления через {useZenithView}, как показано в {extensionsCs}." -concepts.platforms.integration.description: "Интерфейс событий общий, но механизм вывода зависит от фреймворка:" -concepts.platforms.integration.details: "Реализации различаются тем, как изображение GPU попадает в интерфейс. Считывание в растровое изображение копирует пиксели в память CPU перед показом. Совместное использование текстуры исключает эту копию на CPU, но всё ещё может требовать копирования на GPU и синхронизации. При выборе интеграции учитывайте этот путь вывода наряду с общим событием {renderRequested}." -concepts.platforms.integration.guidance: "Добавьте через NuGet пакет интеграции для вашего UI-фреймворка. Для Avalonia используйте {avaloniaPackage}." +concepts.platforms.description: 'Выводом управляет приложение или элемент интерфейса. От этого зависит, кто получает выходную текстуру кадра, записывает и отправляет команды и выводит результат. Эта выходная текстура называется drawable.' +concepts.platforms.frame.context: 'Записывайте привязку конвейера и команды рисования внутри прохода и завершайте его до возврата из обработчика. Элемент управления сам отправит команды и выведет результат. Обработчик не должен отправлять командный буфер или освобождать любой из двух предоставленных объектов. Если он меняет состояние выходной текстуры, перед возвратом нужно восстановить {colorAttachment}, чтобы элемент управления выполнил заключительный переход.' +concepts.platforms.frame.description: 'Элементы реализуют {iZenithView}. Приложение назначает {graphicsContext}, обновляет сцену в {updateRequested} и записывает команды в {renderRequested}, используя переданный {renderEventArgs}.' +concepts.platforms.frame.details: 'Для каждого кадра элемент управления получает выходную текстуру и командный буфер, переводит текстуру в {colorAttachment} и вызывает обработчики обновления и рендеринга. Затем он отправляет записанные команды и выводит изображение средствами выбранного UI-фреймворка.' +concepts.platforms.frame.guidance: 'Добавьте {usingZenithNET} в файл. Для инициализированного {iZenithView} с именем {view} и назначенным графическим контекстом зарегистрируйте обработчик, заполняющий выходную текстуру цветом:' +concepts.platforms.frame.notes: 'Первый переход использует {undefined}, разрешая отбросить прежнее содержимое изображения. Поэтому каждый кадр должен заново заполнять или отрисовывать всё изображение. Накопленные или кешированные результаты храните в текстуре приложения, а затем рисуйте её в выходную текстуру элемента управления.' +concepts.platforms.frame.reference: '{zenithViewHelperDrawableFormat} предоставляет цветовой формат, используемый по умолчанию в этих интеграциях.' +concepts.platforms.frame.title: 'Рендеринг в элементах интерфейса' +concepts.platforms.integration.context: 'WinForms, WPF и Windows-интеграция WinUI работают под Windows. Для MAUI установите рабочую нагрузку целевой платформы и зарегистрируйте обработчик элемента управления через {useZenithView}, как показано в {extensionsCs}.' +concepts.platforms.integration.description: 'Интерфейс событий общий, но механизм вывода зависит от фреймворка:' +concepts.platforms.integration.details: 'Реализации различаются тем, как изображение GPU попадает в интерфейс. Считывание в растровое изображение копирует пиксели в память CPU перед показом. Совместное использование текстуры исключает эту копию на CPU, но всё ещё может требовать копирования на GPU и синхронизации. При выборе интеграции учитывайте этот путь вывода наряду с общим событием {renderRequested}.' +concepts.platforms.integration.guidance: 'Добавьте через NuGet пакет интеграции для вашего UI-фреймворка. Для Avalonia используйте {avaloniaPackage}.' concepts.platforms.integration.table.avalonia.integration: Avalonia -concepts.platforms.integration.table.avalonia.presentation: "Рисует в текстуру и считывает пиксели в {writeableBitmap}. Реализация: {zenithViewCs} и {surfaceCs}." +concepts.platforms.integration.table.avalonia.presentation: 'Рисует в текстуру и считывает пиксели в {writeableBitmap}. Реализация: {zenithViewCs} и {surfaceCs}.' concepts.platforms.integration.table.headings.integration: Интеграция -concepts.platforms.integration.table.headings.presentation: "Механизм вывода" +concepts.platforms.integration.table.headings.presentation: 'Механизм вывода' concepts.platforms.integration.table.maui.integration: .NET MAUI concepts.platforms.integration.table.maui.presentation: Использует нативные поверхности в Android, iOS и Mac Catalyst, а в Windows — композицию через разделяемые текстуры. См. {link}. concepts.platforms.integration.table.maui.presentation.link: реализации для платформ @@ -65,27 +65,27 @@ concepts.platforms.integration.table.uno.presentation: Считывает пик concepts.platforms.integration.table.winForms.integration: WinForms concepts.platforms.integration.table.winForms.presentation: Создаёт цепочку обмена Zenith.NET для дескриптора {hWND} элемента управления. См. {zenithViewCs}. concepts.platforms.integration.table.winUI.integration: WinUI в Windows -concepts.platforms.integration.table.winUI.presentation: "Рисует в импортированную общую текстуру Direct3D 11, затем копирует результат в композиционную цепочку обмена, связанную с {swapChainPanel}. Реализация: {zenithViewWinUICs}." +concepts.platforms.integration.table.winUI.presentation: 'Рисует в импортированную общую текстуру Direct3D 11, затем копирует результат в композиционную цепочку обмена, связанную с {swapChainPanel}. Реализация: {zenithViewWinUICs}.' concepts.platforms.integration.table.wpf.integration: WPF -concepts.platforms.integration.table.wpf.presentation: "Импортирует общую текстуру Direct3D 11 и через взаимодействие с Direct3D копирует её в поверхность, отображаемую {d3DImage}. Реализация: {surfaceCs}." -concepts.platforms.integration.title: "Фреймворк и вывод изображения" -concepts.platforms.lifecycle.context: "При создании соответствующих вложений используйте {descWidth}, {descHeight}, {descFormat} и {descSampleCount} выходной текстуры, переданной событием рендеринга. Эта текстура задаёт реальные размеры цели вывода; их не следует вычислять по размеру элемента интерфейса или масштабу экрана." -concepts.platforms.lifecycle.description: "Цепочка обмена использует ширину и высоту кадрового буфера в пикселях. При масштабировании экрана они могут отличаться от логических размеров окна. Отложите рендеринг и изменение размера цепочки, пока хотя бы один размер равен нулю. Получайте {swapChainDrawable} для каждого кадра: цепочка обмена владеет этой текстурой и может заменить её после вывода или изменения размера." -concepts.platforms.lifecycle.details: "При изменении размеров кадрового буфера дождитесь всех обращений GPU к старым изображениям перед вызовом {swapChainResize}. Чтобы заменить нативную цель вывода, после завершения этих обращений передайте её новое описание и дескрипторы в {swapChainRefresh}. При завершении приложения освободите цепочку обмена до уничтожения её нативной цели вывода." -concepts.platforms.lifecycle.guidance: "Если размеры принадлежащих приложению текстур глубины или внеэкранных текстур следуют за окном, пересоздайте их при изменении размера и обновите константы с их дескрипторами. Конвейер можно использовать дальше, пока форматы вложений и число выборок совпадают. Повторное использование конвейера при замене текстур показано в {link}." -concepts.platforms.lifecycle.guidance.link: "примере вращающегося куба" -concepts.platforms.lifecycle.title: "Размеры и время жизни цепочки обмена" -concepts.platforms.ownership.description: "Приложение владеет назначенным контекстом и своими ресурсами рендеринга, а элемент управления — ресурсами вывода. При изменении {graphicsContext} представления планировщик пересоздаёт ресурсы элемента управления для нового контекста. Приложение также должно пересоздать для этого контекста свои конвейеры, буферы и текстуры." -concepts.platforms.ownership.details: "Перед заменой ресурсов рендеринга остановите обработку кадров представления и дождитесь использующей их работы GPU. Только после этого освобождайте старые ресурсы или контекст. При удалении представления приложение по-прежнему отвечает за освобождение назначенного контекста." -concepts.platforms.ownership.guidance: "Общий {frameSchedulerCs} выполняет обработчики кадров через диспетчер UI представления. Ограничивайте их работу обновлением сцены и записью команд: длительные вычисления на CPU здесь задерживают и отклик интерфейса." -concepts.platforms.ownership.title: "Ресурсы приложения и элемента интерфейса" -concepts.platforms.surface.description: "В {link} Silk.NET создаёт окно и обрабатывает события. Zenith.NET получает нативные дескрипторы окна и его размеры через описание {surface}, по которому создаёт {swapChain}. За само окно операционной системы по-прежнему отвечает приложение." -concepts.platforms.surface.description.link: "уроке с треугольником" -concepts.platforms.surface.details: "Дескрипторы поверхности должны соответствовать бэкенду:" -concepts.platforms.surface.guidance: "Общая оболочка примеров в {appCs} поддерживает Windows, macOS и X11. Под Linux её окно предоставляет дескрипторы Xlib, поэтому в сеансе Wayland для запуска нужен XWayland. Приложение с нативным Wayland передаёт дескрипторы дисплея и поверхности через {surfaceWayland}." +concepts.platforms.integration.table.wpf.presentation: 'Импортирует общую текстуру Direct3D 11 и через взаимодействие с Direct3D копирует её в поверхность, отображаемую {d3DImage}. Реализация: {surfaceCs}.' +concepts.platforms.integration.title: 'Фреймворк и вывод изображения' +concepts.platforms.lifecycle.context: 'При создании соответствующих вложений используйте {descWidth}, {descHeight}, {descFormat} и {descSampleCount} выходной текстуры, переданной событием рендеринга. Эта текстура задаёт реальные размеры цели вывода; их не следует вычислять по размеру элемента интерфейса или масштабу экрана.' +concepts.platforms.lifecycle.description: 'Цепочка обмена использует ширину и высоту кадрового буфера в пикселях. При масштабировании экрана они могут отличаться от логических размеров окна. Отложите рендеринг и изменение размера цепочки, пока хотя бы один размер равен нулю. Получайте {swapChainDrawable} для каждого кадра: цепочка обмена владеет этой текстурой и может заменить её после вывода или изменения размера.' +concepts.platforms.lifecycle.details: 'При изменении размеров кадрового буфера дождитесь всех обращений GPU к старым изображениям перед вызовом {swapChainResize}. Чтобы заменить нативную цель вывода, после завершения этих обращений передайте её новое описание и дескрипторы в {swapChainRefresh}. При завершении приложения освободите цепочку обмена до уничтожения её нативной цели вывода.' +concepts.platforms.lifecycle.guidance: 'Если размеры принадлежащих приложению текстур глубины или внеэкранных текстур следуют за окном, пересоздайте их при изменении размера и обновите константы с их дескрипторами. Конвейер можно использовать дальше, пока форматы вложений и число выборок совпадают. Повторное использование конвейера при замене текстур показано в {link}.' +concepts.platforms.lifecycle.guidance.link: 'примере вращающегося куба' +concepts.platforms.lifecycle.title: 'Размеры и время жизни цепочки обмена' +concepts.platforms.ownership.description: 'Приложение владеет назначенным контекстом и своими ресурсами рендеринга, а элемент управления — ресурсами вывода. При изменении {graphicsContext} представления планировщик пересоздаёт ресурсы элемента управления для нового контекста. Приложение также должно пересоздать для этого контекста свои конвейеры, буферы и текстуры.' +concepts.platforms.ownership.details: 'Перед заменой ресурсов рендеринга остановите обработку кадров представления и дождитесь использующей их работы GPU. Только после этого освобождайте старые ресурсы или контекст. При удалении представления приложение по-прежнему отвечает за освобождение назначенного контекста.' +concepts.platforms.ownership.guidance: 'Общий {frameSchedulerCs} выполняет обработчики кадров через диспетчер UI представления. Ограничивайте их работу обновлением сцены и записью команд: длительные вычисления на CPU здесь задерживают и отклик интерфейса.' +concepts.platforms.ownership.title: 'Ресурсы приложения и элемента интерфейса' +concepts.platforms.surface.description: 'В {link} Silk.NET создаёт окно и обрабатывает события. Zenith.NET получает нативные дескрипторы окна и его размеры через описание {surface}, по которому создаёт {swapChain}. За само окно операционной системы по-прежнему отвечает приложение.' +concepts.platforms.surface.description.link: 'уроке с треугольником' +concepts.platforms.surface.details: 'Дескрипторы поверхности должны соответствовать бэкенду:' +concepts.platforms.surface.guidance: 'Общая оболочка примеров в {appCs} поддерживает Windows, macOS и X11. Под Linux её окно предоставляет дескрипторы Xlib, поэтому в сеансе Wayland для запуска нужен XWayland. Приложение с нативным Wayland передаёт дескрипторы дисплея и поверхности через {surfaceWayland}.' concepts.platforms.surface.table.android.backend: Vulkan в Android. concepts.platforms.surface.table.apple.backend: Metal на платформах Apple. -concepts.platforms.surface.table.headings.backend: "Бэкенд и платформа" +concepts.platforms.surface.table.headings.backend: 'Бэкенд и платформа' concepts.platforms.surface.table.headings.factory: Фабрика поверхности concepts.platforms.surface.table.headings.handles: Дескрипторы, предоставляемые хостом concepts.platforms.surface.table.wayland.backend: Vulkan с нативным хостом Wayland. @@ -93,268 +93,268 @@ concepts.platforms.surface.table.wayland.handles: Дисплей и поверх concepts.platforms.surface.table.win32.backend: DirectX 12 или Vulkan в Windows. concepts.platforms.surface.table.xlib.backend: Vulkan в Linux с X11 или XWayland. concepts.platforms.surface.table.xlib.handles: Дисплей и окно X11 -concepts.platforms.surface.title: "Нативные поверхности вывода" +concepts.platforms.surface.title: 'Нативные поверхности вывода' concepts.platforms.title: Интеграция с платформами -concepts.resources.allocation.context: "Размещённые в куче ресурсы зависят от её памяти в течение всего своего времени жизни. После последнего использования на GPU освободите сначала ресурсы, затем кучу." -concepts.resources.allocation.description: "Используйте {heap}, если приложение должно самостоятельно управлять выделением памяти. Ресурсы размещаются в куче по явно заданным смещениям в байтах; приложение выбирает эти смещения и учитывает занятые области." -concepts.resources.allocation.details: "Для каждого ресурса вызовите {contextGetSizeAndAlignment} с тем описанием буфера или текстуры, которое будет использовано при создании. Зарезервируйте возвращённый размер по смещению, кратному указанному выравниванию. Вся область должна находиться в пределах кучи и не пересекать другую ещё действующую область. Размер текстуры может включать дополнительные промежутки, зависящие от бэкенда, поэтому вычислить его только по числу пикселей и байтам на пиксель нельзя." -concepts.resources.allocation.guidance: "Резидентность буфера, размещённого в куче, должна совпадать с резидентностью этой кучи. Для текстур используйте кучу, предназначенную только для GPU." -concepts.resources.allocation.title: "Размещение в кучах памяти" +concepts.resources.allocation.context: 'Размещённые в куче ресурсы зависят от её памяти в течение всего своего времени жизни. После последнего использования на GPU освободите сначала ресурсы, затем кучу.' +concepts.resources.allocation.description: 'Используйте {heap}, если приложение должно самостоятельно управлять выделением памяти. Ресурсы размещаются в куче по явно заданным смещениям в байтах; приложение выбирает эти смещения и учитывает занятые области.' +concepts.resources.allocation.details: 'Для каждого ресурса вызовите {contextGetSizeAndAlignment} с тем описанием буфера или текстуры, которое будет использовано при создании. Зарезервируйте возвращённый размер по смещению, кратному указанному выравниванию. Вся область должна находиться в пределах кучи и не пересекать другую ещё действующую область. Размер текстуры может включать дополнительные промежутки, зависящие от бэкенда, поэтому вычислить его только по числу пикселей и байтам на пиксель нельзя.' +concepts.resources.allocation.guidance: 'Резидентность буфера, размещённого в куче, должна совпадать с резидентностью этой кучи. Для текстур используйте кучу, предназначенную только для GPU.' +concepts.resources.allocation.title: 'Размещение в кучах памяти' concepts.resources.bufferUsages.table.constant.role: Параметры шейдера, считываемые через привязку буфера констант. -concepts.resources.bufferUsages.table.headings.role: "Роль" +concepts.resources.bufferUsages.table.headings.role: 'Роль' concepts.resources.bufferUsages.table.headings.usage: Назначение -concepts.resources.bufferUsages.table.index.role: "Индексы, используемые при индексированном рисовании." -concepts.resources.bufferUsages.table.indirect.role: "Аргументы, считываемые командами косвенного рисования или косвенного запуска вычислений." -concepts.resources.bufferUsages.table.none.role: "Флаги назначения буфера не объявлены." -concepts.resources.bufferUsages.table.storageReadOnly.role: "Данные буфера, доступные через привязку шейдера только для чтения." -concepts.resources.bufferUsages.table.storageReadWrite.role: "Данные буфера, доступные через привязку шейдера для чтения и записи." -concepts.resources.bufferUsages.table.transferDst.role: "Память назначения для копирования на GPU." -concepts.resources.bufferUsages.table.transferSrc.role: "Исходные данные для копирования на GPU." -concepts.resources.bufferUsages.table.vertex.role: "Вершинные атрибуты, считываемые для рисования." +concepts.resources.bufferUsages.table.index.role: 'Индексы, используемые при индексированном рисовании.' +concepts.resources.bufferUsages.table.indirect.role: 'Аргументы, считываемые командами косвенного рисования или косвенного запуска вычислений.' +concepts.resources.bufferUsages.table.none.role: 'Флаги назначения буфера не объявлены.' +concepts.resources.bufferUsages.table.storageReadOnly.role: 'Данные буфера, доступные через привязку шейдера только для чтения.' +concepts.resources.bufferUsages.table.storageReadWrite.role: 'Данные буфера, доступные через привязку шейдера для чтения и записи.' +concepts.resources.bufferUsages.table.transferDst.role: 'Память назначения для копирования на GPU.' +concepts.resources.bufferUsages.table.transferSrc.role: 'Исходные данные для копирования на GPU.' +concepts.resources.bufferUsages.table.vertex.role: 'Вершинные атрибуты, считываемые для рисования.' concepts.resources.bufferUsages.title: Назначения буфера -concepts.resources.description: "Описание ресурса задаёт допустимые способы использования его памяти. Например, текстуре, которая служит целью рендеринга, читается шейдером и копируется на CPU, нужны флаги назначения для всех трёх операций. Размещение памяти определяет доступ CPU, а синхронизация и управление временем жизни — когда можно обращаться к данным и освобождать память." -concepts.resources.memory.context: "Для доступных CPU буферов {map} возвращает адрес, по которому можно читать или записывать данные. Ни отображение памяти, ни {unmap} не дожидаются GPU. Перед чтением результата приложение должно дождаться его записи на GPU, а перед изменением тех же байтов — всех ещё выполняющихся обращений GPU к ним." -concepts.resources.memory.description: "Поле {residency} в {bufferDesc} задаёт предполагаемый доступ CPU к памяти:" -concepts.resources.memory.details: "Резидентность выражает требования к доступу CPU, в том числе на системах с общей физической памятью CPU и GPU. В примере треугольника {cpuWriteOnly} позволяет напрямую заполнить небольшой вершинный буфер. Для более объёмной статической геометрии может быть предпочтительнее загрузка в память, предназначенную только для GPU." -concepts.resources.memory.guidance: "Текстуры, создаваемые непосредственно через контекст, используют память GPU. Поэтому в {textureDesc} нет поля резидентности: приложение обменивается данными с памятью CPU через загрузку и считывание." -concepts.resources.memory.table.cpuReadOnly.cPUAccess: "Только чтение" -concepts.resources.memory.table.cpuReadOnly.typicalRole: "Данные, полученные на GPU для считывания на CPU" -concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "Только запись" -concepts.resources.memory.table.cpuWriteOnly.typicalRole: "Данные, предоставляемые или обновляемые CPU" -concepts.resources.memory.table.gpuOnly.cPUAccess: "Не предусмотрен" -concepts.resources.memory.table.gpuOnly.typicalRole: "Статическая геометрия и рабочие данные GPU" -concepts.resources.memory.table.headings.cPUAccess: "Предусмотренный доступ CPU" -concepts.resources.memory.table.headings.residency: "Режим доступа к памяти" +concepts.resources.description: 'Описание ресурса задаёт допустимые способы использования его памяти. Например, текстуре, которая служит целью рендеринга, читается шейдером и копируется на CPU, нужны флаги назначения для всех трёх операций. Размещение памяти определяет доступ CPU, а синхронизация и управление временем жизни — когда можно обращаться к данным и освобождать память.' +concepts.resources.memory.context: 'Для доступных CPU буферов {map} возвращает адрес, по которому можно читать или записывать данные. Ни отображение памяти, ни {unmap} не дожидаются GPU. Перед чтением результата приложение должно дождаться его записи на GPU, а перед изменением тех же байтов — всех ещё выполняющихся обращений GPU к ним.' +concepts.resources.memory.description: 'Поле {residency} в {bufferDesc} задаёт предполагаемый доступ CPU к памяти:' +concepts.resources.memory.details: 'Резидентность выражает требования к доступу CPU, в том числе на системах с общей физической памятью CPU и GPU. В примере треугольника {cpuWriteOnly} позволяет напрямую заполнить небольшой вершинный буфер. Для более объёмной статической геометрии может быть предпочтительнее загрузка в память, предназначенную только для GPU.' +concepts.resources.memory.guidance: 'Текстуры, создаваемые непосредственно через контекст, используют память GPU. Поэтому в {textureDesc} нет поля резидентности: приложение обменивается данными с памятью CPU через загрузку и считывание.' +concepts.resources.memory.table.cpuReadOnly.cPUAccess: 'Только чтение' +concepts.resources.memory.table.cpuReadOnly.typicalRole: 'Данные, полученные на GPU для считывания на CPU' +concepts.resources.memory.table.cpuWriteOnly.cPUAccess: 'Только запись' +concepts.resources.memory.table.cpuWriteOnly.typicalRole: 'Данные, предоставляемые или обновляемые CPU' +concepts.resources.memory.table.gpuOnly.cPUAccess: 'Не предусмотрен' +concepts.resources.memory.table.gpuOnly.typicalRole: 'Статическая геометрия и рабочие данные GPU' +concepts.resources.memory.table.headings.cPUAccess: 'Предусмотренный доступ CPU' +concepts.resources.memory.table.headings.residency: 'Режим доступа к памяти' concepts.resources.memory.table.headings.typicalRole: Типичная роль -concepts.resources.memory.title: "Доступ CPU и размещение памяти" -concepts.resources.textureUsages.description: "Флаги передачи указывают, служит ли ресурс источником или приёмником при копировании на GPU. Прямой доступ CPU к его памяти определяется отдельно, при выборе размещения памяти." -concepts.resources.textureUsages.details: "Флаги назначения объявляют допустимые способы использования текстуры. Переход между ними требует соблюдения правил, описанных в разделе «{link}». Устройство также должно поддерживать выбранные операции для указанного формата текстуры." -concepts.resources.textureUsages.details.link: "состояния доступа и синхронизация" -concepts.resources.textureUsages.table.colorAttachment.role: "Цветовое вложение в проходе рендеринга." -concepts.resources.textureUsages.table.depthStencilAttachment.role: "Вложение глубины и трафарета в проходе рендеринга." -concepts.resources.textureUsages.table.headings.role: "Роль" +concepts.resources.memory.title: 'Доступ CPU и размещение памяти' +concepts.resources.textureUsages.description: 'Флаги передачи указывают, служит ли ресурс источником или приёмником при копировании на GPU. Прямой доступ CPU к его памяти определяется отдельно, при выборе размещения памяти.' +concepts.resources.textureUsages.details: 'Флаги назначения объявляют допустимые способы использования текстуры. Переход между ними требует соблюдения правил, описанных в разделе «{link}». Устройство также должно поддерживать выбранные операции для указанного формата текстуры.' +concepts.resources.textureUsages.details.link: 'состояния доступа и синхронизация' +concepts.resources.textureUsages.table.colorAttachment.role: 'Цветовое вложение в проходе рендеринга.' +concepts.resources.textureUsages.table.depthStencilAttachment.role: 'Вложение глубины и трафарета в проходе рендеринга.' +concepts.resources.textureUsages.table.headings.role: 'Роль' concepts.resources.textureUsages.table.headings.usage: Назначение -concepts.resources.textureUsages.table.none.role: "Флаги назначения текстуры не объявлены." -concepts.resources.textureUsages.table.sampled.role: "Данные текстуры, считываемые через привязку сэмплируемой текстуры." -concepts.resources.textureUsages.table.storage.role: "Данные текстуры, доступные через привязку текстуры хранения для чтения или записи шейдером." -concepts.resources.textureUsages.table.transferDst.role: "Память изображения назначения для копирования на GPU." -concepts.resources.textureUsages.table.transferSrc.role: "Данные исходного изображения для копирования на GPU." +concepts.resources.textureUsages.table.none.role: 'Флаги назначения текстуры не объявлены.' +concepts.resources.textureUsages.table.sampled.role: 'Данные текстуры, считываемые через привязку сэмплируемой текстуры.' +concepts.resources.textureUsages.table.storage.role: 'Данные текстуры, доступные через привязку текстуры хранения для чтения или записи шейдером.' +concepts.resources.textureUsages.table.transferDst.role: 'Память изображения назначения для копирования на GPU.' +concepts.resources.textureUsages.table.transferSrc.role: 'Данные исходного изображения для копирования на GPU.' concepts.resources.textureUsages.title: Назначения текстуры concepts.resources.title: Управление ресурсами -concepts.resources.transfers.context: "При считывании данные GPU сначала копируются во внутреннюю промежуточную память. Затем библиотека переносит их в указанную память CPU, когда возвращает завершённый командный буфер для повторного использования. Вызов {wait} для значения отправки, содержащей считывание, завершает оба шага. До возврата из этого вызова память назначения должна оставаться выделенной, а управляемая память — закреплённой." -concepts.resources.transfers.description: "Загрузка копирует данные CPU в ресурс GPU, а считывание — данные ресурса в память CPU. Методы буферов и текстур завершают передачу до возврата управления:" -concepts.resources.transfers.details: "Перед вызовом этих методов устраните конфликтующие обращения из других очередей. Внутреннее ожидание метода относится только к его собственной передаче и не создаёт зависимость от другой очереди. При прямом копировании через отображённую память ожидание конфликтующих обращений GPU полностью возлагается на вызывающий код." -concepts.resources.transfers.guidance: "Чтобы отправить передачу данных вместе с другой работой GPU, запишите её через {commandBufferUpload} или {commandBufferDownload}. Требования ко времени жизни исходной памяти при загрузке и памяти назначения при считывании различаются:" -concepts.resources.transfers.item: "Во время вызова загрузки библиотека копирует исходные данные во временную промежуточную память. Позже GPU читает данные именно из неё, поэтому исходный указатель приложения нужен только до возврата из вызова." -concepts.resources.transfers.notes: "При передаче текстур шаг строки — это расстояние в байтах между соседними строками данных CPU, а шаг среза — расстояние между соседними срезами по глубине. По этим значениям выполняется копирование между памятью CPU и хранилищем текстуры на GPU. Почему завершение GPU и запись в память назначения — разные этапы, объясняется в статье «{link}»." +concepts.resources.transfers.context: 'При считывании данные GPU сначала копируются во внутреннюю промежуточную память. Затем библиотека переносит их в указанную память CPU, когда возвращает завершённый командный буфер для повторного использования. Вызов {wait} для значения отправки, содержащей считывание, завершает оба шага. До возврата из этого вызова память назначения должна оставаться выделенной, а управляемая память — закреплённой.' +concepts.resources.transfers.description: 'Загрузка копирует данные CPU в ресурс GPU, а считывание — данные ресурса в память CPU. Методы буферов и текстур завершают передачу до возврата управления:' +concepts.resources.transfers.details: 'Перед вызовом этих методов устраните конфликтующие обращения из других очередей. Внутреннее ожидание метода относится только к его собственной передаче и не создаёт зависимость от другой очереди. При прямом копировании через отображённую память ожидание конфликтующих обращений GPU полностью возлагается на вызывающий код.' +concepts.resources.transfers.guidance: 'Чтобы отправить передачу данных вместе с другой работой GPU, запишите её через {commandBufferUpload} или {commandBufferDownload}. Требования ко времени жизни исходной памяти при загрузке и памяти назначения при считывании различаются:' +concepts.resources.transfers.item: 'Во время вызова загрузки библиотека копирует исходные данные во временную промежуточную память. Позже GPU читает данные именно из неё, поэтому исходный указатель приложения нужен только до возврата из вызова.' +concepts.resources.transfers.notes: 'При передаче текстур шаг строки — это расстояние в байтах между соседними строками данных CPU, а шаг среза — расстояние между соседними срезами по глубине. По этим значениям выполняется копирование между памятью CPU и хранилищем текстуры на GPU. Почему завершение GPU и запись в память назначения — разные этапы, объясняется в статье «{link}».' concepts.resources.transfers.notes.link: Синхронизация -concepts.resources.transfers.table.bufferDownload.transfer: "Для {cpuReadOnly} копирует непосредственно из отображённой памяти. В остальных случаях отправляет считывание в передающую очередь и дожидается его завершения." -concepts.resources.transfers.table.bufferUpload.transfer: "Для {cpuWriteOnly} копирует непосредственно в отображённую память. В остальных случаях отправляет загрузку в передающую очередь и дожидается её завершения." +concepts.resources.transfers.table.bufferDownload.transfer: 'Для {cpuReadOnly} копирует непосредственно из отображённой памяти. В остальных случаях отправляет считывание в передающую очередь и дожидается его завершения.' +concepts.resources.transfers.table.bufferUpload.transfer: 'Для {cpuWriteOnly} копирует непосредственно в отображённую память. В остальных случаях отправляет загрузку в передающую очередь и дожидается её завершения.' concepts.resources.transfers.table.headings.method: Метод -concepts.resources.transfers.table.headings.transfer: "Порядок передачи" -concepts.resources.transfers.table.textureTransfers.method: "{textureUpload} / {textureDownload}" -concepts.resources.transfers.table.textureTransfers.transfer: "Отправляет копирование и переходы состояния текстуры в графическую очередь, затем ожидает завершения. Выбранный подресурс остаётся в запрошенном конечном состоянии." -concepts.resources.transfers.title: "Немедленная и записываемая передача" -concepts.resources.usages.description: "{bufferUsages} и {textureUsages} — флаговые перечисления, объявляющие предполагаемые роли ресурса. Они задаются в полях {bufferDescUsages} и {textureDescUsages} соответственно. Если у ресурса несколько ролей, члены флагового перечисления можно объединить с помощью {value}." -concepts.resources.usages.title: "Назначения ресурсов" -concepts.resources.views.description: "{bufferView} описывает область буфера и интерпретацию её данных. {textureView} выбирает диапазон подресурсов, совместимые тип и формат текстуры. Оба представления ссылаются на существующую память с назначениями, объявленными при её создании. Диапазоны представлений описывают доступ, но не обеспечивают одинаковую проверку границ в шейдерах на всех бэкендах." -concepts.resources.views.details: "Собственный дескриптор ресурса предоставляет его представление по умолчанию. Для другой области или совместимого способа интерпретации создайте отдельное представление. Сохраняйте и представление, и исходный ресурс до завершения их использования на GPU: дескриптор сам по себе не удерживает ни один из объектов. При замене любого из них обновите константы, содержащие прежний {link}." -concepts.resources.views.details.link: "дескриптор ресурса" -concepts.resources.views.title: "Представления и исходные ресурсы" -concepts.shaders.binding.context: "В вычислительном примере {inputTextureSampledHandle} присваивается {input}, а {outputTextureStorageHandle} — {output}. В Slang параметр типа {descriptorHandle} определяет доступ шейдера к ресурсу:" -concepts.shaders.binding.description: "{setConstantBuffer} выбирает существующий буфер и смещение в байтах, с которого текущий конвейер читает константы. Загрузите параметры в эту память до обращения шейдера. Если ранее отправленная работа GPU ещё читает те же байты, дождитесь её завершения перед обновлением." -concepts.shaders.binding.details: "Подготовьте командный буфер, вычислительный конвейер, заполненный константный буфер и число групп потоков. Затем запишите запуск вычислений в следующем порядке. Сначала выберите конвейер, поскольку привязка константного буфера относится именно к нему:" -concepts.shaders.binding.guidance: "Здесь {commandBuffer} записывает запуск {computePipeline} с параметрами из {constantBuffer}. Буферу нужно назначение {bufferUsagesConstant}; смещение 0 выбирает его начало. Если в буфере несколько записей констант, начальное смещение каждой также должно удовлетворять выравниванию привязки, требуемому бэкендом. Это отдельное условие, не зависящее от размещения полей внутри записи." -concepts.shaders.binding.notes: "{resourceHandle} содержит два 32-битных поля, интерпретация которых зависит от бэкенда. Их значения действительны только в контексте, где создан ресурс." -concepts.shaders.binding.reference: "Сохраняйте ресурс и представление, из которого получен дескриптор, до завершения последнего обращения шейдера. При замене обновите константы со старым дескриптором. Правила владения изложены в статье «{link}»." +concepts.resources.transfers.table.headings.transfer: 'Порядок передачи' +concepts.resources.transfers.table.textureTransfers.method: '{textureUpload} / {textureDownload}' +concepts.resources.transfers.table.textureTransfers.transfer: 'Отправляет копирование и переходы состояния текстуры в графическую очередь, затем ожидает завершения. Выбранный подресурс остаётся в запрошенном конечном состоянии.' +concepts.resources.transfers.title: 'Немедленная и записываемая передача' +concepts.resources.usages.description: '{bufferUsages} и {textureUsages} — флаговые перечисления, объявляющие предполагаемые роли ресурса. Они задаются в полях {bufferDescUsages} и {textureDescUsages} соответственно. Если у ресурса несколько ролей, члены флагового перечисления можно объединить с помощью {value}.' +concepts.resources.usages.title: 'Назначения ресурсов' +concepts.resources.views.description: '{bufferView} описывает область буфера и интерпретацию её данных. {textureView} выбирает диапазон подресурсов, совместимые тип и формат текстуры. Оба представления ссылаются на существующую память с назначениями, объявленными при её создании. Диапазоны представлений описывают доступ, но не обеспечивают одинаковую проверку границ в шейдерах на всех бэкендах.' +concepts.resources.views.details: 'Собственный дескриптор ресурса предоставляет его представление по умолчанию. Для другой области или совместимого способа интерпретации создайте отдельное представление. Сохраняйте и представление, и исходный ресурс до завершения их использования на GPU: дескриптор сам по себе не удерживает ни один из объектов. При замене любого из них обновите константы, содержащие прежний {link}.' +concepts.resources.views.details.link: 'дескриптор ресурса' +concepts.resources.views.title: 'Представления и исходные ресурсы' +concepts.shaders.binding.context: 'В вычислительном примере {inputTextureSampledHandle} присваивается {input}, а {outputTextureStorageHandle} — {output}. В Slang параметр типа {descriptorHandle} определяет доступ шейдера к ресурсу:' +concepts.shaders.binding.description: '{setConstantBuffer} выбирает существующий буфер и смещение в байтах, с которого текущий конвейер читает константы. Загрузите параметры в эту память до обращения шейдера. Если ранее отправленная работа GPU ещё читает те же байты, дождитесь её завершения перед обновлением.' +concepts.shaders.binding.details: 'Подготовьте командный буфер, вычислительный конвейер, заполненный константный буфер и число групп потоков. Затем запишите запуск вычислений в следующем порядке. Сначала выберите конвейер, поскольку привязка константного буфера относится именно к нему:' +concepts.shaders.binding.guidance: 'Здесь {commandBuffer} записывает запуск {computePipeline} с параметрами из {constantBuffer}. Буферу нужно назначение {bufferUsagesConstant}; смещение 0 выбирает его начало. Если в буфере несколько записей констант, начальное смещение каждой также должно удовлетворять выравниванию привязки, требуемому бэкендом. Это отдельное условие, не зависящее от размещения полей внутри записи.' +concepts.shaders.binding.notes: '{resourceHandle} содержит два 32-битных поля, интерпретация которых зависит от бэкенда. Их значения действительны только в контексте, где создан ресурс.' +concepts.shaders.binding.reference: 'Сохраняйте ресурс и представление, из которого получен дескриптор, до завершения последнего обращения шейдера. При замене обновите константы со старым дескриптором. Правила владения изложены в статье «{link}».' concepts.shaders.binding.reference.link: Управление ресурсами -concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: "Чтение структурированных элементов шейдерного типа {t}" -concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: "Чтение и запись структурированных элементов шейдерного типа {t}" +concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: 'Чтение структурированных элементов шейдерного типа {t}' +concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: 'Чтение и запись структурированных элементов шейдерного типа {t}' concepts.shaders.binding.table.headings.access: Предполагаемый доступ -concepts.shaders.binding.table.headings.cHandle: "Дескриптор C#" +concepts.shaders.binding.table.headings.cHandle: 'Дескриптор C#' concepts.shaders.binding.table.headings.slangFieldType: Тип поля Slang -concepts.shaders.binding.table.samplerHandle.access: "Состояние выборки из текстур" -concepts.shaders.binding.table.textureSampledHandle.access: "Чтение текстур" -concepts.shaders.binding.table.textureStorageHandle.access: "Чтение и запись текстур хранения" -concepts.shaders.binding.title: "Буферы констант и дескрипторы ресурсов" -concepts.shaders.compilation.description: "{zenithCompiler} компилирует именованную точку входа Slang в {shaderDesc}. {graphicsApi} контекста определяет результат: DXIL для DirectX 12, библиотеку Metal для Metal или SPIR-V для Vulkan." -concepts.shaders.compilation.details: "Используя уже созданный графический контекст {context}, скомпилируйте шейдер треугольника из копии рядом с исполняемым файлом:" -concepts.shaders.compilation.guidance: "Имя точки входа {vSMain} должно совпадать с её объявлением в файле шейдера. Компилируйте шейдеры и создавайте конвейеры при инициализации, а во время рендеринга используйте готовые конвейеры повторно. После создания конвейера объекты шейдеров можно освободить, как показано в {link}." -concepts.shaders.compilation.guidance.link: "учебном примере треугольника" -concepts.shaders.compilation.title: "Компиляция шейдеров" -concepts.shaders.description: "Объявления C# и Slang должны согласованно определять, где хранится каждое значение и как шейдер к нему обращается. Описания вершинного ввода задают атрибуты вершин, объявления буферов в шейдерах — параметры и массивы, а дескрипторы указывают используемые шейдером ресурсы." -concepts.shaders.dispatch.description: "{dispatch} задаёт число выполняемых групп потоков. В вычислительном примере объявлено {numthreads}, поэтому каждая группа содержит 16 × 16 потоков. Чтобы обработать всё изображение, разделите ширину и высоту на 16 и округлите каждый результат вверх. Для изображения 17 × 19 пикселей нужны 2 × 2 группы. Шейдер проверяет координаты каждого потока и пропускает те, что выходят за границы изображения." -concepts.shaders.dispatch.details: "Объявленный размер группы доступен через {shaderDescThreadGroupSize}. По нему можно рассчитать число групп для {dispatch}; полный расчёт показан в {computeShaderRendererCs}. Последующие обращения к полученному изображению должны соблюдать требования из статьи «{link}»." +concepts.shaders.binding.table.samplerHandle.access: 'Состояние выборки из текстур' +concepts.shaders.binding.table.textureSampledHandle.access: 'Чтение текстур' +concepts.shaders.binding.table.textureStorageHandle.access: 'Чтение и запись текстур хранения' +concepts.shaders.binding.title: 'Буферы констант и дескрипторы ресурсов' +concepts.shaders.compilation.description: '{zenithCompiler} компилирует именованную точку входа Slang в {shaderDesc}. {graphicsApi} контекста определяет результат: DXIL для DirectX 12, библиотеку Metal для Metal или SPIR-V для Vulkan.' +concepts.shaders.compilation.details: 'Используя уже созданный графический контекст {context}, скомпилируйте шейдер треугольника из копии рядом с исполняемым файлом:' +concepts.shaders.compilation.guidance: 'Имя точки входа {vSMain} должно совпадать с её объявлением в файле шейдера. Компилируйте шейдеры и создавайте конвейеры при инициализации, а во время рендеринга используйте готовые конвейеры повторно. После создания конвейера объекты шейдеров можно освободить, как показано в {link}.' +concepts.shaders.compilation.guidance.link: 'учебном примере треугольника' +concepts.shaders.compilation.title: 'Компиляция шейдеров' +concepts.shaders.description: 'Объявления C# и Slang должны согласованно определять, где хранится каждое значение и как шейдер к нему обращается. Описания вершинного ввода задают атрибуты вершин, объявления буферов в шейдерах — параметры и массивы, а дескрипторы указывают используемые шейдером ресурсы.' +concepts.shaders.dispatch.description: '{dispatch} задаёт число выполняемых групп потоков. В вычислительном примере объявлено {numthreads}, поэтому каждая группа содержит 16 × 16 потоков. Чтобы обработать всё изображение, разделите ширину и высоту на 16 и округлите каждый результат вверх. Для изображения 17 × 19 пикселей нужны 2 × 2 группы. Шейдер проверяет координаты каждого потока и пропускает те, что выходят за границы изображения.' +concepts.shaders.dispatch.details: 'Объявленный размер группы доступен через {shaderDescThreadGroupSize}. По нему можно рассчитать число групп для {dispatch}; полный расчёт показан в {computeShaderRendererCs}. Последующие обращения к полученному изображению должны соблюдать требования из статьи «{link}».' concepts.shaders.dispatch.details.link: Синхронизация -concepts.shaders.dispatch.title: "Группы потоков" -concepts.shaders.layout.context: "Такая организация показана в {link}: они содержат размеры изображения и два дескриптора текстур. Явные смещения указывают начало каждого поля. Для объявления используются {systemRuntimeInteropServices} и {zenithNET}:" -concepts.shaders.layout.context.link: "константах C# примера вычислений" -concepts.shaders.layout.description: "Для вершинного ввода {inputLayout} задаёт формат, смещение и семантику каждого атрибута, а также шаг между вершинами. В треугольнике за позицией {float3} следует цвет {float4}: цвет начинается со смещения 12 байт, а вершина занимает 28 байт. {inputLayoutAdd} рассчитывает эту плотную раскладку по форматам элементов. Если структура C# содержит выравнивающие промежутки, учитывайте их в смещениях и шаге." -concepts.shaders.layout.details: "Константные буферы содержат параметры шейдера, а структурированные — массивы типизированных элементов. Их раскладка определяется объявлениями Slang, а не {inputLayout}. Смещения полей C#, размеры элементов и выравнивающие промежутки должны соответствовать раскладке скомпилированного шейдера. Неуправляемый тип C# можно скопировать как последовательность байтов, но его размещение в памяти не обязательно соответствует раскладке шейдера: плотно упакованный {float3} в вершине может требовать другого выравнивания в буфере шейдера." -concepts.shaders.layout.guidance: "Параметры шейдера могут содержать дескрипторы ресурсов наряду с обычными значениями. Дескриптор указывает на уже существующую память, поэтому его копирование в константный буфер не копирует содержимое ресурса." -concepts.shaders.layout.notes: "Соответствующее объявление в {computeShaderSlang}:" -concepts.shaders.layout.reference: "Два размера занимают первые восемь байт, за ними следуют два дескриптора по восемь байт каждый. В примере C# под всю запись отведено 256 байт. Размер другой записи следует определять по её собственным полям, требуемой раскладке и выравниванию." -concepts.shaders.layout.title: "Размещение данных" -concepts.shaders.matrices.description: "Компилятор использует построчное хранение матриц: элементы каждой строки расположены подряд. В {link} три значения {matrix4x4} находятся по смещениям 0, 64 и 128 байт. Его {detail} применяет {mulVectorMatrix} в порядке модели, вида и проекции." -concepts.shaders.matrices.description.detail: "шейдер" -concepts.shaders.matrices.description.link: "рендерере вращающегося куба" -concepts.shaders.matrices.details: "Порядок хранения определяет размещение элементов матрицы в памяти; порядок умножения — преобразование. Используйте согласованные соглашения в C# и Slang." -concepts.shaders.matrices.title: "Соглашения о матрицах" +concepts.shaders.dispatch.title: 'Группы потоков' +concepts.shaders.layout.context: 'Такая организация показана в {link}: они содержат размеры изображения и два дескриптора текстур. Явные смещения указывают начало каждого поля. Для объявления используются {systemRuntimeInteropServices} и {zenithNET}:' +concepts.shaders.layout.context.link: 'константах C# примера вычислений' +concepts.shaders.layout.description: 'Для вершинного ввода {inputLayout} задаёт формат, смещение и семантику каждого атрибута, а также шаг между вершинами. В треугольнике за позицией {float3} следует цвет {float4}: цвет начинается со смещения 12 байт, а вершина занимает 28 байт. {inputLayoutAdd} рассчитывает эту плотную раскладку по форматам элементов. Если структура C# содержит выравнивающие промежутки, учитывайте их в смещениях и шаге.' +concepts.shaders.layout.details: 'Константные буферы содержат параметры шейдера, а структурированные — массивы типизированных элементов. Их раскладка определяется объявлениями Slang, а не {inputLayout}. Смещения полей C#, размеры элементов и выравнивающие промежутки должны соответствовать раскладке скомпилированного шейдера. Неуправляемый тип C# можно скопировать как последовательность байтов, но его размещение в памяти не обязательно соответствует раскладке шейдера: плотно упакованный {float3} в вершине может требовать другого выравнивания в буфере шейдера.' +concepts.shaders.layout.guidance: 'Параметры шейдера могут содержать дескрипторы ресурсов наряду с обычными значениями. Дескриптор указывает на уже существующую память, поэтому его копирование в константный буфер не копирует содержимое ресурса.' +concepts.shaders.layout.notes: 'Соответствующее объявление в {computeShaderSlang}:' +concepts.shaders.layout.reference: 'Два размера занимают первые восемь байт, за ними следуют два дескриптора по восемь байт каждый. В примере C# под всю запись отведено 256 байт. Размер другой записи следует определять по её собственным полям, требуемой раскладке и выравниванию.' +concepts.shaders.layout.title: 'Размещение данных' +concepts.shaders.matrices.description: 'Компилятор использует построчное хранение матриц: элементы каждой строки расположены подряд. В {link} три значения {matrix4x4} находятся по смещениям 0, 64 и 128 байт. Его {detail} применяет {mulVectorMatrix} в порядке модели, вида и проекции.' +concepts.shaders.matrices.description.detail: 'шейдер' +concepts.shaders.matrices.description.link: 'рендерере вращающегося куба' +concepts.shaders.matrices.details: 'Порядок хранения определяет размещение элементов матрицы в памяти; порядок умножения — преобразование. Используйте согласованные соглашения в C# и Slang.' +concepts.shaders.matrices.title: 'Соглашения о матрицах' concepts.shaders.title: Данные шейдеров и привязка -concepts.synchronization.backends.description: "DirectX 12 и Vulkan кодируют переходы текстур как изменения состояния и доступа. В реализации {transition} для Metal в Zenith.NET нет эквивалентной операции. Вместо этого бэкенд Metal объединяет команды в графические и вычислительные кодировщики и вставляет барьеры видимости при завершении кодировщика. Для зависимых операций внутри одного кодировщика, например последовательных вычислительных запусков, нужны явные вызовы {barrier}." -concepts.synchronization.backends.details: "В {link} начало графического прохода завершает вычислительный кодировщик и делает его результат видимым графическим командам. Два последовательных вычислительных запуска остаются в одном кодировщике, поэтому их зависимость требует барьера, даже если между ними записан переход состояния текстуры. Переносимая последовательность команд должна учитывать и зависимости обращений, и состояния текстур." +concepts.synchronization.backends.description: 'DirectX 12 и Vulkan кодируют переходы текстур как изменения состояния и доступа. В реализации {transition} для Metal в Zenith.NET нет эквивалентной операции. Вместо этого бэкенд Metal объединяет команды в графические и вычислительные кодировщики и вставляет барьеры видимости при завершении кодировщика. Для зависимых операций внутри одного кодировщика, например последовательных вычислительных запусков, нужны явные вызовы {barrier}.' +concepts.synchronization.backends.details: 'В {link} начало графического прохода завершает вычислительный кодировщик и делает его результат видимым графическим командам. Два последовательных вычислительных запуска остаются в одном кодировщике, поэтому их зависимость требует барьера, даже если между ними записан переход состояния текстуры. Переносимая последовательность команд должна учитывать и зависимости обращений, и состояния текстур.' concepts.synchronization.backends.details.link: примере вычислений -concepts.synchronization.backends.title: "Поведение бэкендов" -concepts.synchronization.barriers.context: "Выбирайте стадии, которые охватывают нужные обращения и поддерживаются очередью. {barrierStagesAll} включает все поддерживаемые стадии. Если зависимость затрагивает лишь часть из них, можно указать более узкий набор." -concepts.synchronization.barriers.description: "Рассмотрим два запуска вычислений в одном командном буфере: первый записывает данные симуляции, второй их читает. Барьер между ними позволяет второму запуску увидеть результаты завершённых записей. Для буфера хранения он упорядочивает обращения без перехода состояния текстуры:" -concepts.synchronization.barriers.details: "Первый аргумент указывает стадии, которые произвели данные, второй — стадии, которым они понадобятся. Вместе они описывают порядок выполнения и видимость памяти, необходимые между двумя запусками." -concepts.synchronization.barriers.guidance: "Этот порядок используется в {link} между шагами симуляции. Каждый барьер следует за запуском, который производит данные, и предшествует запуску, который их использует." +concepts.synchronization.backends.title: 'Поведение бэкендов' +concepts.synchronization.barriers.context: 'Выбирайте стадии, которые охватывают нужные обращения и поддерживаются очередью. {barrierStagesAll} включает все поддерживаемые стадии. Если зависимость затрагивает лишь часть из них, можно указать более узкий набор.' +concepts.synchronization.barriers.description: 'Рассмотрим два запуска вычислений в одном командном буфере: первый записывает данные симуляции, второй их читает. Барьер между ними позволяет второму запуску увидеть результаты завершённых записей. Для буфера хранения он упорядочивает обращения без перехода состояния текстуры:' +concepts.synchronization.barriers.details: 'Первый аргумент указывает стадии, которые произвели данные, второй — стадии, которым они понадобятся. Вместе они описывают порядок выполнения и видимость памяти, необходимые между двумя запусками.' +concepts.synchronization.barriers.guidance: 'Этот порядок используется в {link} между шагами симуляции. Каждый барьер следует за запуском, который производит данные, и предшествует запуску, который их использует.' concepts.synchronization.barriers.guidance.link: симуляции FluidTank -concepts.synchronization.barriers.title: "Барьеры конвейера" -concepts.synchronization.dependencies.description: "Для каждого ресурса определите обращения к одним и тем же данным. Если хотя бы одно из них записывает, сохраните необходимый порядок. Два чтения не конфликтуют, хотя требования к состоянию текстуры и выводу изображения продолжают действовать. Обновление данных с CPU и освобождение ресурсов тоже должны ждать, пока GPU закончит использовать соответствующую память." -concepts.synchronization.dependencies.details: "Выбор механизма зависит от места выполнения операций:" -concepts.synchronization.dependencies.guidance: "Одной задаче может потребоваться несколько механизмов. Например, текстуре, созданной вычислениями в другой очереди, нужны зависимость между отправками и подходящее состояние для следующего обращения. Блокировать CPU при этом нужно только тогда, когда он сам должен обратиться к данным или освободить их память." +concepts.synchronization.barriers.title: 'Барьеры конвейера' +concepts.synchronization.dependencies.description: 'Для каждого ресурса определите обращения к одним и тем же данным. Если хотя бы одно из них записывает, сохраните необходимый порядок. Два чтения не конфликтуют, хотя требования к состоянию текстуры и выводу изображения продолжают действовать. Обновление данных с CPU и освобождение ресурсов тоже должны ждать, пока GPU закончит использовать соответствующую память.' +concepts.synchronization.dependencies.details: 'Выбор механизма зависит от места выполнения операций:' +concepts.synchronization.dependencies.guidance: 'Одной задаче может потребоваться несколько механизмов. Например, текстуре, созданной вычислениями в другой очереди, нужны зависимость между отправками и подходящее состояние для следующего обращения. Блокировать CPU при этом нужно только тогда, когда он сам должен обратиться к данным или освободить их память.' concepts.synchronization.dependencies.table.cpuAccess.mechanism: Вызов {wait} для соответствующего значения завершения. -concepts.synchronization.dependencies.table.cpuAccess.situation: "Доступ CPU или освобождение ресурса требует завершения работы GPU" -concepts.synchronization.dependencies.table.crossQueue.mechanism: "Передайте {timelineValue} производителя в вызов {submit} потребителя." -concepts.synchronization.dependencies.table.crossQueue.situation: "Одна очередь использует данные, полученные в другой" +concepts.synchronization.dependencies.table.cpuAccess.situation: 'Доступ CPU или освобождение ресурса требует завершения работы GPU' +concepts.synchronization.dependencies.table.crossQueue.mechanism: 'Передайте {timelineValue} производителя в вызов {submit} потребителя.' +concepts.synchronization.dependencies.table.crossQueue.situation: 'Одна очередь использует данные, полученные в другой' concepts.synchronization.dependencies.table.headings.mechanism: Механизм concepts.synchronization.dependencies.table.headings.situation: Ситуация -concepts.synchronization.dependencies.table.layoutChange.mechanism: "{commandBufferTransition} с предыдущим и следующим состоянием текстуры." +concepts.synchronization.dependencies.table.layoutChange.mechanism: '{commandBufferTransition} с предыдущим и следующим состоянием текстуры.' concepts.synchronization.dependencies.table.layoutChange.situation: Изменение способа использования подресурса текстуры concepts.synchronization.dependencies.table.pipelineStages.mechanism: Вызов {commandBufferBarrier} с указанием стадий производителя и потребителя. concepts.synchronization.dependencies.table.pipelineStages.situation: Зависимые стадии GPU в потоке команд -concepts.synchronization.dependencies.title: "Зависимости обращений" -concepts.synchronization.description: "Синхронизация задаёт порядок обращений к общим данным и обеспечивает доступ последующих операций к нужным результатам. В зависимости между записью и чтением записывающая операция производит данные, а читающая их потребляет. Барьеры и переходы состояния текстур координируют обращения GPU; временные шкалы связывают отправки и позволяют CPU дождаться завершения работы GPU." -concepts.synchronization.layouts.context: "Указывайте {undefined} как предыдущее состояние, когда существующее содержимое можно отбросить, например для нового изображения или вложения, которое будет заполнено целиком. Если содержимое нужно сохранить для загрузки, выборки или накопления, используйте состояние предыдущего обращения." -concepts.synchronization.layouts.description: "Флаги назначения текстуры объявляют допустимые способы её использования. {textureLayout} описывает доступ к конкретному подресурсу в определённой точке последовательности команд. Подресурс задаётся mip-уровнем и слоем массива. При смене способа доступа запишите переход. Например, вычислительный пример записывает выходную текстуру в состоянии {storage}, затем подготавливает её к выборке в графическом проходе:" -concepts.synchronization.layouts.details: "Здесь {outputTexture} создана с назначением {sampledStorage}, а выбранный подресурс находится в {storage}. {default} выбирает уровень mip 0 и слой 0. Остальные уровни и слои переход не затрагивает." -concepts.synchronization.layouts.guidance: "В {transition} передавайте состояние предыдущего использования подресурса. Приложение отслеживает это состояние при записи команд и передаче текстур между этапами рендеринга." -concepts.synchronization.layouts.title: "Состояния текстур" -concepts.synchronization.readback.description: "{isCompleted} сообщает о завершении работы GPU. У записанного считывания есть ещё один этап: копирование результата из внутренней промежуточной памяти в память назначения приложения." -concepts.synchronization.readback.details: "{commandBufferDownload} записывает копирование на GPU во внутреннюю память. После завершения отправки библиотека выполняет копию на CPU, возвращая командный буфер для повторного использования. Вызов {wait} для значения этой отправки дожидается GPU и обрабатывает завершённые буферы той же очереди, тем самым завершая оба этапа. До возврата память назначения должна оставаться выделенной, а управляемая память — закреплённой." -concepts.synchronization.readback.guidance: "Один лишь опрос {isCompleted} не выполняет заключительную копию на CPU. Ожидание другой очереди тоже не возвращает завершённые буферы очереди считывания. Когда загрузка и считывание используют прямой доступ к памяти, а когда промежуточное хранилище, описано в статье «{link}»." +concepts.synchronization.dependencies.title: 'Зависимости обращений' +concepts.synchronization.description: 'Синхронизация задаёт порядок обращений к общим данным и обеспечивает доступ последующих операций к нужным результатам. В зависимости между записью и чтением записывающая операция производит данные, а читающая их потребляет. Барьеры и переходы состояния текстур координируют обращения GPU; временные шкалы связывают отправки и позволяют CPU дождаться завершения работы GPU.' +concepts.synchronization.layouts.context: 'Указывайте {undefined} как предыдущее состояние, когда существующее содержимое можно отбросить, например для нового изображения или вложения, которое будет заполнено целиком. Если содержимое нужно сохранить для загрузки, выборки или накопления, используйте состояние предыдущего обращения.' +concepts.synchronization.layouts.description: 'Флаги назначения текстуры объявляют допустимые способы её использования. {textureLayout} описывает доступ к конкретному подресурсу в определённой точке последовательности команд. Подресурс задаётся mip-уровнем и слоем массива. При смене способа доступа запишите переход. Например, вычислительный пример записывает выходную текстуру в состоянии {storage}, затем подготавливает её к выборке в графическом проходе:' +concepts.synchronization.layouts.details: 'Здесь {outputTexture} создана с назначением {sampledStorage}, а выбранный подресурс находится в {storage}. {default} выбирает уровень mip 0 и слой 0. Остальные уровни и слои переход не затрагивает.' +concepts.synchronization.layouts.guidance: 'В {transition} передавайте состояние предыдущего использования подресурса. Приложение отслеживает это состояние при записи команд и передаче текстур между этапами рендеринга.' +concepts.synchronization.layouts.title: 'Состояния текстур' +concepts.synchronization.readback.description: '{isCompleted} сообщает о завершении работы GPU. У записанного считывания есть ещё один этап: копирование результата из внутренней промежуточной памяти в память назначения приложения.' +concepts.synchronization.readback.details: '{commandBufferDownload} записывает копирование на GPU во внутреннюю память. После завершения отправки библиотека выполняет копию на CPU, возвращая командный буфер для повторного использования. Вызов {wait} для значения этой отправки дожидается GPU и обрабатывает завершённые буферы той же очереди, тем самым завершая оба этапа. До возврата память назначения должна оставаться выделенной, а управляемая память — закреплённой.' +concepts.synchronization.readback.guidance: 'Один лишь опрос {isCompleted} не выполняет заключительную копию на CPU. Ожидание другой очереди тоже не возвращает завершённые буферы очереди считывания. Когда загрузка и считывание используют прямой доступ к памяти, а когда промежуточное хранилище, описано в статье «{link}».' concepts.synchronization.readback.guidance.link: Управление ресурсами -concepts.synchronization.readback.title: "Готовность данных к чтению" -concepts.synchronization.reuse.description: "Треугольник дожидается завершения каждого кадра перед повторным использованием данных. Чтобы выполнение кадров перекрывалось, выделите каждому ещё выполняющемуся кадру собственную изменяемую память и отслеживайте, когда она снова станет доступной. Перед изменением данных дождитесь обращений GPU к тем же байтам, а перед освобождением ресурса — всех его незавершённых использований." -concepts.synchronization.reuse.details: "Изменение размера и завершение приложения подчиняются тому же правилу: прекратить новые обращения, дождаться текущих, затем заменить или освободить ресурсы. Соблюдайте этот порядок перед {swapChainResize} и перед освобождением ресурсов или контекста. Треугольник уже ждёт каждый кадр, поэтому может менять размер между вызовами обработчиков." -concepts.synchronization.reuse.guidance: "После вывода изображения {swapChainPresent} устанавливает точку завершения в графической очереди и ожидает её. Поэтому треугольник всё равно ждёт при выводе, даже если удалить явное ожидание после отправки команд. Работа, независимо отправленная в другие очереди, требует отдельного отслеживания завершения." -concepts.synchronization.reuse.title: "Повторное использование ресурсов" -concepts.synchronization.timelines.context: "Если после потребителя CPU должен прочитать результат, перезаписать общие данные или освободить ресурсы, дождитесь этой отправки:" -concepts.synchronization.timelines.description: "Временная шкала отмечает завершение в очереди возрастающими значениями. {submit} возвращает {timelineValue} со шкалой и значением отправки. Числовые поля {value} разных шкал нельзя сравнивать напрямую." -concepts.synchronization.timelines.details: "Пусть {producer} и {consumer} — записанные буферы двух очередей одного контекста, причём потребитель читает результат производителя. Отправьте их с такой зависимостью:" -concepts.synchronization.timelines.guidance: "Очередь-потребитель ждёт указанного значения завершения перед выполнением своих команд. CPU может продолжать работу без вызова {producedWait}. Сохраняйте общие ресурсы до завершения {consumed} и записывайте переходы состояния текстур, необходимые для доступа потребителя." -concepts.synchronization.timelines.notes: "Значение, возвращённое {queueTimelineSignal}, также можно ожидать через {wait} или передать как зависимость другой очереди. {signal} помещает точку завершения после ранее отправленной работы; GPU достигает её, когда эта работа закончена." -concepts.synchronization.timelines.title: "Временные шкалы и зависимости очередей" +concepts.synchronization.readback.title: 'Готовность данных к чтению' +concepts.synchronization.reuse.description: 'Треугольник дожидается завершения каждого кадра перед повторным использованием данных. Чтобы выполнение кадров перекрывалось, выделите каждому ещё выполняющемуся кадру собственную изменяемую память и отслеживайте, когда она снова станет доступной. Перед изменением данных дождитесь обращений GPU к тем же байтам, а перед освобождением ресурса — всех его незавершённых использований.' +concepts.synchronization.reuse.details: 'Изменение размера и завершение приложения подчиняются тому же правилу: прекратить новые обращения, дождаться текущих, затем заменить или освободить ресурсы. Соблюдайте этот порядок перед {swapChainResize} и перед освобождением ресурсов или контекста. Треугольник уже ждёт каждый кадр, поэтому может менять размер между вызовами обработчиков.' +concepts.synchronization.reuse.guidance: 'После вывода изображения {swapChainPresent} устанавливает точку завершения в графической очереди и ожидает её. Поэтому треугольник всё равно ждёт при выводе, даже если удалить явное ожидание после отправки команд. Работа, независимо отправленная в другие очереди, требует отдельного отслеживания завершения.' +concepts.synchronization.reuse.title: 'Повторное использование ресурсов' +concepts.synchronization.timelines.context: 'Если после потребителя CPU должен прочитать результат, перезаписать общие данные или освободить ресурсы, дождитесь этой отправки:' +concepts.synchronization.timelines.description: 'Временная шкала отмечает завершение в очереди возрастающими значениями. {submit} возвращает {timelineValue} со шкалой и значением отправки. Числовые поля {value} разных шкал нельзя сравнивать напрямую.' +concepts.synchronization.timelines.details: 'Пусть {producer} и {consumer} — записанные буферы двух очередей одного контекста, причём потребитель читает результат производителя. Отправьте их с такой зависимостью:' +concepts.synchronization.timelines.guidance: 'Очередь-потребитель ждёт указанного значения завершения перед выполнением своих команд. CPU может продолжать работу без вызова {producedWait}. Сохраняйте общие ресурсы до завершения {consumed} и записывайте переходы состояния текстур, необходимые для доступа потребителя.' +concepts.synchronization.timelines.notes: 'Значение, возвращённое {queueTimelineSignal}, также можно ожидать через {wait} или передать как зависимость другой очереди. {signal} помещает точку завершения после ранее отправленной работы; GPU достигает её, когда эта работа закончена.' +concepts.synchronization.timelines.title: 'Временные шкалы и зависимости очередей' concepts.synchronization.title: Синхронизация home.actions.reference: Справочник API home.actions.tutorial: Начать с треугольника -home.entries.description: "Учебные материалы, примеры и справочник API" -home.entries.label: "Разделы документации" +home.entries.description: 'Учебные материалы, примеры и справочник API' +home.entries.label: 'Разделы документации' home.entries.reference.action: Изучить API home.entries.reference.category: Справочник -home.entries.reference.description: "Справка по типам, членам и объявлениям API" +home.entries.reference.description: 'Справка по типам, членам и объявлениям API' home.entries.reference.title: Справочник API home.entries.samples.action: Обзор примеров home.entries.samples.category: Примеры -home.entries.samples.description: "Рабочие примеры графических и вычислительных методов" +home.entries.samples.description: 'Рабочие примеры графических и вычислительных методов' home.entries.samples.title: Примеры -home.entries.title: "Документация" -home.entries.tutorial.action: "Начать урок" -home.entries.tutorial.category: "Урок" -home.entries.tutorial.description: "От пустого проекта до первого треугольника на экране" +home.entries.title: 'Документация' +home.entries.tutorial.action: 'Начать урок' +home.entries.tutorial.category: 'Урок' +home.entries.tutorial.description: 'От пустого проекта до первого треугольника на экране' home.entries.tutorial.title: Первый треугольник -home.introduction.accent: "на разных платформах" -home.introduction.description: "Zenith.NET объединяет работу с DirectX, Metal и Vulkan в одном API для графики и вычислений" -home.introduction.title: "Графика для .NET{lineBreak}{accent}" -home.meta.description: "Кроссплатформенная графика и вычисления в .NET с единым API для DirectX, Metal и Vulkan" -home.scene.description: "Интерактивная вращающаяся геометрия. Перетаскивайте изображение или используйте клавиши со стрелками для изменения ракурса." +home.introduction.accent: 'на разных платформах' +home.introduction.description: 'Zenith.NET объединяет работу с DirectX, Metal и Vulkan в одном API для графики и вычислений' +home.introduction.title: 'Графика для .NET{lineBreak}{accent}' +home.meta.description: 'Кроссплатформенная графика и вычисления в .NET с единым API для DirectX, Metal и Vulkan' +home.scene.description: 'Интерактивная вращающаяся геометрия. Перетаскивайте изображение или используйте клавиши со стрелками для изменения ракурса.' home.scene.label: Отображение геометрии home.scene.surface: Поверхность home.scene.wireframe: Каркас -home.title: "Графический API для .NET" -learning.concepts.description: "Выбор назначений ресурсов, описание данных шейдеров и координация работы GPU" -learning.concepts.execution.description: "Запись команд, отправка и время жизни ресурсов" -learning.concepts.platforms.description: "Нативный вывод и графические элементы интерфейса" -learning.concepts.resources.description: "Назначения ресурсов, размещение памяти и представления" -learning.concepts.shaders.description: "Соглашения о размещении и привязке данных C# и Slang" -learning.concepts.synchronization.description: "Зависимости, видимость и завершение" +home.title: 'Графический API для .NET' +learning.concepts.description: 'Выбор назначений ресурсов, описание данных шейдеров и координация работы GPU' +learning.concepts.execution.description: 'Запись команд, отправка и время жизни ресурсов' +learning.concepts.platforms.description: 'Нативный вывод и графические элементы интерфейса' +learning.concepts.resources.description: 'Назначения ресурсов, размещение памяти и представления' +learning.concepts.shaders.description: 'Соглашения о размещении и привязке данных C# и Slang' +learning.concepts.synchronization.description: 'Зависимости, видимость и завершение' learning.concepts.title: Основные концепции -learning.description: "Начните с урока о треугольнике и создайте первое приложение. Затем изучите управление ресурсами, данные шейдеров и синхронизацию в статьях об основных понятиях или выберите пример нужного графического метода." +learning.description: 'Начните с урока о треугольнике и создайте первое приложение. Затем изучите управление ресурсами, данные шейдеров и синхронизацию в статьях об основных понятиях или выберите пример нужного графического метода.' learning.entries.samples.action: Обзор примеров -learning.entries.samples.description: "Примеры на C# и Slang: геометрия, вычисления, запросы лучей и меш-шейдинг" -learning.entries.tutorial.action: "Открыть урок" -learning.entries.tutorial.description: "Консольное приложение, которое открывает окно и рисует треугольник" -learning.meta.description: "Учебные материалы и основы модели программирования Zenith.NET" +learning.entries.samples.description: 'Примеры на C# и Slang: геометрия, вычисления, запросы лучей и меш-шейдинг' +learning.entries.tutorial.action: 'Открыть урок' +learning.entries.tutorial.description: 'Консольное приложение, которое открывает окно и рисует треугольник' +learning.meta.description: 'Учебные материалы и основы модели программирования Zenith.NET' learning.title: Обучение -reference.description: "Справочник ресурсов, команд и платформенных интеграций" -reference.entries.commands.description: "Графические, вычислительные и передающие команды" +reference.description: 'Справочник ресурсов, команд и платформенных интеграций' +reference.entries.commands.description: 'Графические, вычислительные и передающие команды' reference.entries.commands.label: Запись команд -reference.entries.context.description: "Создание ресурсов GPU для выбранного бэкенда" +reference.entries.context.description: 'Создание ресурсов GPU для выбранного бэкенда' reference.entries.context.label: Начало работы -reference.meta.description: "Пространства имён, типы и члены Zenith.NET" -reference.navigation.core: "Справочник основного API" +reference.meta.description: 'Пространства имён, типы и члены Zenith.NET' +reference.navigation.core: 'Справочник основного API' reference.title: Справочник API -samples.computeShader.description: "Пример загружает {assetsTexturesShokoPng}, преобразует изображение в оттенки серого на GPU и показывает выходную текстуру. Преобразование выполняется один раз; следующие кадры показывают тот же результат. Рендерер демонстрирует привязку текстур для выборки и записи, округление числа групп потоков вверх для обработки всего изображения и проверку его границ в шейдере." -samples.computeShader.details: "{computeShaderRendererCs} · {computeShaderSlang}" +samples.computeShader.description: 'Пример загружает {assetsTexturesShokoPng}, преобразует изображение в оттенки серого на GPU и показывает выходную текстуру. Преобразование выполняется один раз; следующие кадры показывают тот же результат. Рендерер демонстрирует привязку текстур для выборки и записи, округление числа групп потоков вверх для обработки всего изображения и проверку его границ в шейдере.' +samples.computeShader.details: '{computeShaderRendererCs} · {computeShaderSlang}' samples.computeShader.title: Вычислительный шейдер -samples.cube.description: "Куб добавляет индексированное рисование, матрицы модели, вида и проекции в буфере констант и проверку глубины. Текстура глубины и трафарета {d32FloatS8UInt} пересоздаётся при изменении размера." -samples.cube.details: "{spinningCubeRendererCs} · {spinningCubeSlang}" +samples.cube.description: 'Куб добавляет индексированное рисование, матрицы модели, вида и проекции в буфере констант и проверку глубины. Текстура глубины и трафарета {d32FloatS8UInt} пересоздаётся при изменении размера.' +samples.cube.details: '{spinningCubeRendererCs} · {spinningCubeSlang}' samples.cube.title: Вращающийся куб -samples.description: "Каждый пример объединяет рендерер C# и шейдер Slang для определённого метода. Полную настройку приложения и порядок рендеринга разбирает урок «{link}»." +samples.description: 'Каждый пример объединяет рендерер C# и шейдер Slang для определённого метода. Полную настройку приложения и порядок рендеринга разбирает урок «{link}».' samples.description.link: Первый треугольник -samples.execution.description: "Запустите проект {link} и выберите пример в меню консоли." +samples.execution.description: 'Запустите проект {link} и выберите пример в меню консоли.' samples.execution.description.link: ZenithTutorials -samples.execution.title: "Запуск примеров" -samples.host.description: "{appCs} инициализирует контекст, окно и цепочку обмена. На каждом кадре он получает буфер команд, вызывает выбранный рендерер, отправляет команды и выводит изображение. {iRendererCs} задаёт операции обновления, рисования, изменения размера и освобождения ресурсов." -samples.host.details: "Вычислительный рендерер и рендерер трассировки лучей создают внеэкранные текстуры. {texturePresenterCs} и {presentTextureSlang} рисуют их в текущую выходную текстуру, после чего общая оболочка отправляет команды и выводит кадр." -samples.host.title: "Оболочка приложения и вывод" -samples.indirectDrawing.description: "Косвенное рисование выводит несколько экземпляров куба по буферу аргументов индексированного рисования и структурированному буферу данных экземпляров. CPU задаёт аргументы и обновляет преобразования." -samples.indirectDrawing.details: "{indirectDrawingRendererCs} · {indirectDrawingSlang}" -samples.indirectDrawing.title: "Косвенное рисование" -samples.meshShading.description: "Шейдер задач отбрасывает невидимые экземпляры сфер и передаёт оставшиеся индексы меш-шейдеру, который создаёт геометрию. До создания конвейера рендерер проверяет {contextCapabilitiesMeshShadingSupported}." -samples.meshShading.details: "{meshShadingRendererCs} · {meshShadingSlang}" -samples.meshShading.title: "Меш-шейдинг" -samples.rayTracing.description: "Пример строит структуры ускорения нижнего и верхнего уровней для пола и процедурных сфер, затем выполняет встроенные запросы лучей в вычислительном шейдере. До инициализации проверяется {contextCapabilitiesRayTracingSupported}." -samples.rayTracing.details: "{rayTracingRendererCs} · {rayTracingSlang}" +samples.execution.title: 'Запуск примеров' +samples.host.description: '{appCs} инициализирует контекст, окно и цепочку обмена. На каждом кадре он получает буфер команд, вызывает выбранный рендерер, отправляет команды и выводит изображение. {iRendererCs} задаёт операции обновления, рисования, изменения размера и освобождения ресурсов.' +samples.host.details: 'Вычислительный рендерер и рендерер трассировки лучей создают внеэкранные текстуры. {texturePresenterCs} и {presentTextureSlang} рисуют их в текущую выходную текстуру, после чего общая оболочка отправляет команды и выводит кадр.' +samples.host.title: 'Оболочка приложения и вывод' +samples.indirectDrawing.description: 'Косвенное рисование выводит несколько экземпляров куба по буферу аргументов индексированного рисования и структурированному буферу данных экземпляров. CPU задаёт аргументы и обновляет преобразования.' +samples.indirectDrawing.details: '{indirectDrawingRendererCs} · {indirectDrawingSlang}' +samples.indirectDrawing.title: 'Косвенное рисование' +samples.meshShading.description: 'Шейдер задач отбрасывает невидимые экземпляры сфер и передаёт оставшиеся индексы меш-шейдеру, который создаёт геометрию. До создания конвейера рендерер проверяет {contextCapabilitiesMeshShadingSupported}.' +samples.meshShading.details: '{meshShadingRendererCs} · {meshShadingSlang}' +samples.meshShading.title: 'Меш-шейдинг' +samples.rayTracing.description: 'Пример строит структуры ускорения нижнего и верхнего уровней для пола и процедурных сфер, затем выполняет встроенные запросы лучей в вычислительном шейдере. До инициализации проверяется {contextCapabilitiesRayTracingSupported}.' +samples.rayTracing.details: '{rayTracingRendererCs} · {rayTracingSlang}' samples.rayTracing.title: Трассировка лучей samples.title: Примеры -samples.triangle.description: "Треугольник связывает буфер вершин с соответствующим описанием входа и рисует три вершины через графический конвейер." -samples.triangle.details: "{helloTriangleRendererCs} · {helloTriangleSlang} · {link}" -samples.triangle.details.link: "Полный урок" -samples.triangle.title: "Треугольник" -samples.workloads.description: "Каталог {link} основного репозитория содержит более сложные приложения, использующие исходный код библиотеки." -samples.workloads.description.link: "Experiments" -samples.workloads.details: "Оконные эксперименты используют те же пути вывода для Windows, macOS и Linux/X11. Интеграции Avalonia, WinForms, WPF, WinUI/Uno и MAUI, их цикл кадров и исходный код описаны в статье «{link}»." +samples.triangle.description: 'Треугольник связывает буфер вершин с соответствующим описанием входа и рисует три вершины через графический конвейер.' +samples.triangle.details: '{helloTriangleRendererCs} · {helloTriangleSlang} · {link}' +samples.triangle.details.link: 'Полный урок' +samples.triangle.title: 'Треугольник' +samples.workloads.description: 'Каталог {link} основного репозитория содержит более сложные приложения, использующие исходный код библиотеки.' +samples.workloads.description.link: 'Experiments' +samples.workloads.details: 'Оконные эксперименты используют те же пути вывода для Windows, macOS и Linux/X11. Интеграции Avalonia, WinForms, WPF, WinUI/Uno и MAUI, их цикл кадров и исходный код описаны в статье «{link}».' samples.workloads.details.link: Интеграция с платформами -samples.workloads.table.cornellBox.example: "{link}" +samples.workloads.table.cornellBox.example: '{link}' samples.workloads.table.cornellBox.example.link: CornellBox -samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: "Трассировка путей, шумоподавление, тональная компрессия, увеличение разрешения и элементы управления ImGui. Требуется поддержка трассировки лучей." -samples.workloads.table.fluidTank.example: "{link}" +samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: 'Трассировка путей, шумоподавление, тональная компрессия, увеличение разрешения и элементы управления ImGui. Требуется поддержка трассировки лучей.' +samples.workloads.table.fluidTank.example: '{link}' samples.workloads.table.fluidTank.example.link: FluidTank -samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: "Вычислительное моделирование жидкости, зависимости между стадиями симуляции и многопроходный рендеринг поверхности." +samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: 'Вычислительное моделирование жидкости, зависимости между стадиями симуляции и многопроходный рендеринг поверхности.' samples.workloads.table.headings.example: Пример -samples.workloads.table.headings.whatItDemonstratesAndRequires: "Методы и требования" -samples.workloads.table.inkCanvas.example: "{link}" +samples.workloads.table.headings.whatItDemonstratesAndRequires: 'Методы и требования' +samples.workloads.table.inkCanvas.example: '{link}' samples.workloads.table.inkCanvas.example.link: InkCanvas samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: Отрисовка с помощью Skia и обработка ввода в нативном окне. Требуется бэкенд и нативная библиотека Skia для целевой платформы. -samples.workloads.table.platformDetection.example: "{link}" +samples.workloads.table.platformDetection.example: '{link}' samples.workloads.table.platformDetection.example.link: PlatformDetection -samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: "Пытается создать контекст для каждого бэкенда и сообщает возможности устройства. Неудачная попытка отмечается как отсутствие поддержки; причиной может быть устройство, драйвер или недостающая зависимость среды выполнения." -samples.workloads.title: "Более сложные приложения" -tutorial.context.description: "{graphicsContext} связывает приложение с GPU через выбранный бэкенд и предоставляет методы создания ресурсов для рендеринга." -tutorial.context.details: "Вставьте инициализацию контекста {emphasis}:" +samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: 'Пытается создать контекст для каждого бэкенда и сообщает возможности устройства. Неудачная попытка отмечается как отсутствие поддержки; причиной может быть устройство, драйвер или недостающая зависимость среды выполнения.' +samples.workloads.title: 'Более сложные приложения' +tutorial.context.description: '{graphicsContext} связывает приложение с GPU через выбранный бэкенд и предоставляет методы создания ресурсов для рендеринга.' +tutorial.context.details: 'Вставьте инициализацию контекста {emphasis}:' tutorial.context.details.emphasis: после директив using, перед {iWindowWindow} -tutorial.context.guidance: "Каждая ветвь выбирает бэкенд текущей платформы и запрашивает валидацию. Сообщения {validationMessage} выводятся в консоль." -tutorial.context.imports: "Добавьте следующие директивы using в начало {programCs}:" -tutorial.context.title: "Графический контекст" -tutorial.description: "В этом уроке из пустого консольного проекта .NET получится приложение, которое открывает окно и рисует цветной треугольник." -tutorial.details: "В уроке три проверочных этапа: пустое окно, однотонный фон и цветной треугольник. Запускайте приложение после каждого этапа, прежде чем добавлять следующую часть." -tutorial.draw.context: "Аргументы метода {draw}:" -tutorial.draw.description: "В обработчике {windowRender} замените {addTheTriangleDrawCommandsHereLater} следующими командами между {beginRenderPass} и {endRenderPass}:" -tutorial.draw.details: "{setPipeline} выбирает шейдеры и состояние рендеринга. Этот вызов должен предшествовать привязке вершинного буфера, поскольку бэкенд интерпретирует его данные по описанию вершинного ввода выбранного конвейера." -tutorial.draw.guidance: "{setVertexBufferVertexBuffer} привязывает загруженные вершинные данные со смещения 0 байт к входному слоту 0, соответствующему единственной записи {inputLayouts}." -tutorial.draw.notes: "Эти вызовы записывают команды рисования. Уже добавленный вызов {submitWait} отправляет их и дожидается завершения на GPU; затем {present} запрашивает вывод готового изображения. Сохраните заполнение фоном в начале прохода, чтобы область за пределами треугольника тоже имела определённый цвет." +tutorial.context.guidance: 'Каждая ветвь выбирает бэкенд текущей платформы и запрашивает валидацию. Сообщения {validationMessage} выводятся в консоль.' +tutorial.context.imports: 'Добавьте следующие директивы using в начало {programCs}:' +tutorial.context.title: 'Графический контекст' +tutorial.description: 'В этом уроке из пустого консольного проекта .NET получится приложение, которое открывает окно и рисует цветной треугольник.' +tutorial.details: 'В уроке три проверочных этапа: пустое окно, однотонный фон и цветной треугольник. Запускайте приложение после каждого этапа, прежде чем добавлять следующую часть.' +tutorial.draw.context: 'Аргументы метода {draw}:' +tutorial.draw.description: 'В обработчике {windowRender} замените {addTheTriangleDrawCommandsHereLater} следующими командами между {beginRenderPass} и {endRenderPass}:' +tutorial.draw.details: '{setPipeline} выбирает шейдеры и состояние рендеринга. Этот вызов должен предшествовать привязке вершинного буфера, поскольку бэкенд интерпретирует его данные по описанию вершинного ввода выбранного конвейера.' +tutorial.draw.guidance: '{setVertexBufferVertexBuffer} привязывает загруженные вершинные данные со смещения 0 байт к входному слоту 0, соответствующему единственной записи {inputLayouts}.' +tutorial.draw.notes: 'Эти вызовы записывают команды рисования. Уже добавленный вызов {submitWait} отправляет их и дожидается завершения на GPU; затем {present} запрашивает вывод готового изображения. Сохраните заполнение фоном в начале прохода, чтобы область за пределами треугольника тоже имела определённый цвет.' tutorial.draw.table.firstInstance.meaning: Начать нумерацию экземпляров с нуля. tutorial.draw.table.firstVertex.meaning: Начать с первой вершины в буфере. tutorial.draw.table.headings.argument: Аргумент @@ -362,152 +362,152 @@ tutorial.draw.table.headings.description: Значение tutorial.draw.table.headings.meaning: Назначение tutorial.draw.table.instanceCount.meaning: Нарисовать одну копию треугольника. tutorial.draw.table.vertexCount.meaning: Считать три вершины. -tutorial.draw.title: "Команды рисования" -tutorial.execution.description: "Соберите и запустите проект {firstTriangle}." -tutorial.execution.details: "На тёмном фоне должен появиться треугольник: красный сверху, зелёный справа внизу и синий слева внизу. Интерполяция цветов вершин создаёт плавные переходы внутри треугольника." -tutorial.execution.guidance: "При изменении размера окна меняются размеры изображения в пикселях, но координаты вершин остаются прежними. Область вывода преобразует эти координаты с учётом новой ширины и высоты. Поэтому изменение соотношения сторон окна растягивает треугольник." -tutorial.execution.title: "Запуск приложения" -tutorial.frame.commands.context: "После {endRenderPass} второй переход подготавливает выходную текстуру к выводу. {submit} завершает запись и отправляет командный буфер; {wait} блокирует поток до завершения этой работы. Затем {present} запрашивает отображение готового изображения." -tutorial.frame.commands.description: "Проход рендеринга объединяет команды рисования, которые записывают результаты в одни и те же вложения. В этом проходе цвет записывается в выходную текстуру цепочки обмена. {colorAttachmentClear} задаёт её начальное заполнение цветом RGBA и сохранение содержимого после прохода. {beginRenderPass} записывает начало прохода с этими настройками." -tutorial.frame.commands.details: "Коллекция содержит одно цветовое вложение. {null} означает, что у прохода нет вложения глубины и трафарета." -tutorial.frame.commands.guidance: "{beginRenderPass} задаёт область вывода и прямоугольник отсечения по размеру всего вложения. Область вывода преобразует координаты рендеринга в позиции пикселей, а прямоугольник отсечения ограничивает область, в которую разрешена запись." -tutorial.frame.commands.title: "Очистка, отправка и вывод" -tutorial.frame.description: "Для начала заполните окно одним цветом фона. Эта операция называется очисткой. Когда фон появился, поверхность, отправка команд и вывод уже работают вместе — можно добавлять вершины и шейдеры треугольника." -tutorial.frame.details: "Silk.NET вызывает обработчик, когда нужно отрисовать кадр. Пример не использует аргумент прошедшего времени, поэтому параметр назван {value}. Зарегистрируйте обработчик {emphasis}:" +tutorial.draw.title: 'Команды рисования' +tutorial.execution.description: 'Соберите и запустите проект {firstTriangle}.' +tutorial.execution.details: 'На тёмном фоне должен появиться треугольник: красный сверху, зелёный справа внизу и синий слева внизу. Интерполяция цветов вершин создаёт плавные переходы внутри треугольника.' +tutorial.execution.guidance: 'При изменении размера окна меняются размеры изображения в пикселях, но координаты вершин остаются прежними. Область вывода преобразует эти координаты с учётом новой ширины и высоты. Поэтому изменение соотношения сторон окна растягивает треугольник.' +tutorial.execution.title: 'Запуск приложения' +tutorial.frame.commands.context: 'После {endRenderPass} второй переход подготавливает выходную текстуру к выводу. {submit} завершает запись и отправляет командный буфер; {wait} блокирует поток до завершения этой работы. Затем {present} запрашивает отображение готового изображения.' +tutorial.frame.commands.description: 'Проход рендеринга объединяет команды рисования, которые записывают результаты в одни и те же вложения. В этом проходе цвет записывается в выходную текстуру цепочки обмена. {colorAttachmentClear} задаёт её начальное заполнение цветом RGBA и сохранение содержимого после прохода. {beginRenderPass} записывает начало прохода с этими настройками.' +tutorial.frame.commands.details: 'Коллекция содержит одно цветовое вложение. {null} означает, что у прохода нет вложения глубины и трафарета.' +tutorial.frame.commands.guidance: '{beginRenderPass} задаёт область вывода и прямоугольник отсечения по размеру всего вложения. Область вывода преобразует координаты рендеринга в позиции пикселей, а прямоугольник отсечения ограничивает область, в которую разрешена запись.' +tutorial.frame.commands.title: 'Очистка, отправка и вывод' +tutorial.frame.description: 'Для начала заполните окно одним цветом фона. Эта операция называется очисткой. Когда фон появился, поверхность, отправка команд и вывод уже работают вместе — можно добавлять вершины и шейдеры треугольника.' +tutorial.frame.details: 'Silk.NET вызывает обработчик, когда нужно отрисовать кадр. Пример не использует аргумент прошедшего времени, поэтому параметр назван {value}. Зарегистрируйте обработчик {emphasis}:' tutorial.frame.details.emphasis: перед {windowRun} -tutorial.frame.target.description: "{graphicsQueueCommandBuffer} возвращает буфер, готовый к записи. Запись определяет работу GPU; выполнение начинается только после отправки." -tutorial.frame.target.details: "Состояние доступа к текстуре определяет, как операция будет её использовать. Первый вызов {transition} подготавливает выходную текстуру к записи цвета. Значение {default} выбирает mip-уровень 0 и слой массива 0 — базовое изображение этой текстуры. Поскольку проход заполняет всё изображение цветом фона, {undefined} разрешает отбросить прежнее содержимое." -tutorial.frame.target.guidance: "Для каждого кадра используйте текущую выходную текстуру: при выводе изображения цепочка обмена может перейти к следующей." -tutorial.frame.target.title: "Подготовка выходной текстуры" -tutorial.frame.title: "Первый кадр" -tutorial.geometry.data.description: "Добавьте массив вершин {emphasis}. Последующую инициализацию ресурсов также размещайте перед этим обработчиком в указанном порядке." +tutorial.frame.target.description: '{graphicsQueueCommandBuffer} возвращает буфер, готовый к записи. Запись определяет работу GPU; выполнение начинается только после отправки.' +tutorial.frame.target.details: 'Состояние доступа к текстуре определяет, как операция будет её использовать. Первый вызов {transition} подготавливает выходную текстуру к записи цвета. Значение {default} выбирает mip-уровень 0 и слой массива 0 — базовое изображение этой текстуры. Поскольку проход заполняет всё изображение цветом фона, {undefined} разрешает отбросить прежнее содержимое.' +tutorial.frame.target.guidance: 'Для каждого кадра используйте текущую выходную текстуру: при выводе изображения цепочка обмена может перейти к следующей.' +tutorial.frame.target.title: 'Подготовка выходной текстуры' +tutorial.frame.title: 'Первый кадр' +tutorial.geometry.data.description: 'Добавьте массив вершин {emphasis}. Последующую инициализацию ресурсов также размещайте перед этим обработчиком в указанном порядке.' tutorial.geometry.data.description.emphasis: перед {windowRender} -tutorial.geometry.data.details: "Каждая запись создаёт {vertex}; два внутренних выражения {new} задают позицию {vector3} и цвет {vector4}. Позиции соответствуют верхней, нижней правой и нижней левой вершинам. Вершинный шейдер добавляет четвёртую координату {w}. При w = 1 значения x и y также являются нормализованными координатами устройства: -1 и +1 обозначают края изображения, а 0 — центр. Эти координаты не зависят от числа пикселей." -tutorial.geometry.data.guidance: "Цвет задаётся красной, зелёной, синей и альфа-компонентами; альфа равна 1. Все три вершины находятся в одной плоскости при z = 0." -tutorial.geometry.data.title: "Позиции и цвета вершин" -tutorial.geometry.description: "У каждой из трёх вершин есть позиция и цвет. По позициям GPU определяет форму треугольника, а его внутренние цвета получает интерполяцией цветов вершин." -tutorial.geometry.format.description: "Добавьте объявление вершины {emphasis}:" -tutorial.geometry.format.description.emphasis: "в конце {programCs}, после кода освобождения ресурсов" -tutorial.geometry.format.details: "{file} ограничивает использование типа файлом {programCs}, а {layoutKindSequential} сохраняет порядок объявления полей. Поле {position} содержит три 32-битных числа с плавающей точкой и начинается со смещения 0 байт; поле {color} содержит четыре таких числа и начинается со смещения 12 байт. Одна вершина занимает 28 байт. Далее описание входных данных укажет GPU, как читать эти поля." -tutorial.geometry.format.imports: "Добавьте в начало {programCs} следующие директивы using для векторных типов и атрибута размещения полей структуры:" -tutorial.geometry.format.title: "Представление вершины" -tutorial.geometry.title: "Вершинные данные" -tutorial.geometry.upload.context: "{fixed} не позволяет сборщику мусора перемещать массив, пока используется его адрес. Для этого буфера с доступом CPU на запись метод {upload} отображает память, копирует данные и отменяет отображение до возврата. Поэтому массив достаточно закрепить на время вызова. Загрузите вершины один раз при инициализации и сохраняйте буфер до завершения рендеринга." -tutorial.geometry.upload.description: "Поместите вершины в {buffer}, чтобы GPU мог читать их при рисовании. Добавьте выделение памяти и загрузку данных сразу после массива:" -tutorial.geometry.upload.details: "Размер выделения — {sizeofVertexVerticesLength}: три вершины по 28 байт, всего 84 байта. {bufferUsagesVertex} объявляет вершинный ввод, {cpuWriteOnly} разрешает начальное заполнение с CPU. Шаг в описании буфера фиксирует размер элемента. Описание входа ниже определит интерпретацию каждого атрибута." -tutorial.geometry.upload.guidance: "Выделение памяти не заполняет буфер. {upload} копирует массив в начало буфера, используя исходный указатель и число байтов из описания данных." -tutorial.geometry.upload.imports: "В {programCs} добавьте {bufferAlias} к директивам using, чтобы отличить тип буфера Zenith.NET от {systemBuffer}." -tutorial.geometry.upload.notes: "В коде освобождения в конце {programCs} вставьте {vertexBufferDispose} непосредственно перед {swapChainDispose}. Память только для GPU и загрузка крупной статической геометрии рассмотрены в статье «{link}»." +tutorial.geometry.data.details: 'Каждая запись создаёт {vertex}; два внутренних выражения {new} задают позицию {vector3} и цвет {vector4}. Позиции соответствуют верхней, нижней правой и нижней левой вершинам. Вершинный шейдер добавляет четвёртую координату {w}. При w = 1 значения x и y также являются нормализованными координатами устройства: -1 и +1 обозначают края изображения, а 0 — центр. Эти координаты не зависят от числа пикселей.' +tutorial.geometry.data.guidance: 'Цвет задаётся красной, зелёной, синей и альфа-компонентами; альфа равна 1. Все три вершины находятся в одной плоскости при z = 0.' +tutorial.geometry.data.title: 'Позиции и цвета вершин' +tutorial.geometry.description: 'У каждой из трёх вершин есть позиция и цвет. По позициям GPU определяет форму треугольника, а его внутренние цвета получает интерполяцией цветов вершин.' +tutorial.geometry.format.description: 'Добавьте объявление вершины {emphasis}:' +tutorial.geometry.format.description.emphasis: 'в конце {programCs}, после кода освобождения ресурсов' +tutorial.geometry.format.details: '{file} ограничивает использование типа файлом {programCs}, а {layoutKindSequential} сохраняет порядок объявления полей. Поле {position} содержит три 32-битных числа с плавающей точкой и начинается со смещения 0 байт; поле {color} содержит четыре таких числа и начинается со смещения 12 байт. Одна вершина занимает 28 байт. Далее описание входных данных укажет GPU, как читать эти поля.' +tutorial.geometry.format.imports: 'Добавьте в начало {programCs} следующие директивы using для векторных типов и атрибута размещения полей структуры:' +tutorial.geometry.format.title: 'Представление вершины' +tutorial.geometry.title: 'Вершинные данные' +tutorial.geometry.upload.context: '{fixed} не позволяет сборщику мусора перемещать массив, пока используется его адрес. Для этого буфера с доступом CPU на запись метод {upload} отображает память, копирует данные и отменяет отображение до возврата. Поэтому массив достаточно закрепить на время вызова. Загрузите вершины один раз при инициализации и сохраняйте буфер до завершения рендеринга.' +tutorial.geometry.upload.description: 'Поместите вершины в {buffer}, чтобы GPU мог читать их при рисовании. Добавьте выделение памяти и загрузку данных сразу после массива:' +tutorial.geometry.upload.details: 'Размер выделения — {sizeofVertexVerticesLength}: три вершины по 28 байт, всего 84 байта. {bufferUsagesVertex} объявляет вершинный ввод, {cpuWriteOnly} разрешает начальное заполнение с CPU. Шаг в описании буфера фиксирует размер элемента. Описание входа ниже определит интерпретацию каждого атрибута.' +tutorial.geometry.upload.guidance: 'Выделение памяти не заполняет буфер. {upload} копирует массив в начало буфера, используя исходный указатель и число байтов из описания данных.' +tutorial.geometry.upload.imports: 'В {programCs} добавьте {bufferAlias} к директивам using, чтобы отличить тип буфера Zenith.NET от {systemBuffer}.' +tutorial.geometry.upload.notes: 'В коде освобождения в конце {programCs} вставьте {vertexBufferDispose} непосредственно перед {swapChainDispose}. Память только для GPU и загрузка крупной статической геометрии рассмотрены в статье «{link}».' tutorial.geometry.upload.notes.link: Управление ресурсами -tutorial.geometry.upload.title: "Создание и заполнение буфера" -tutorial.input.description: "GPU нужно знать, где хранятся атрибуты вершины, например позиция и цвет. Описание входа задаёт их формат и смещение, а также шаг — расстояние в байтах до следующей вершины. Добавьте этот код после создания шейдеров:" -tutorial.input.details: "{inputLayoutAdd} размещает каждый атрибут сразу после предыдущего и увеличивает шаг между вершинами на размер добавленного атрибута. Смещения рассчитываются по указанным форматам, без анализа структуры C#. Для этих двух полей получается следующая раскладка:" -tutorial.input.guidance: "Значение {semanticIndex} по умолчанию равно нулю и соответствует {pOSITION0} и {cOLOR0} в шейдере. Позиция и цвет хранятся вместе в одном вершинном буфере, поэтому конвейер использует одно описание входных данных в слоте 0. Если порядок полей или выравнивающие промежутки в структуре C# изменятся, измените и это описание." +tutorial.geometry.upload.title: 'Создание и заполнение буфера' +tutorial.input.description: 'GPU нужно знать, где хранятся атрибуты вершины, например позиция и цвет. Описание входа задаёт их формат и смещение, а также шаг — расстояние в байтах до следующей вершины. Добавьте этот код после создания шейдеров:' +tutorial.input.details: '{inputLayoutAdd} размещает каждый атрибут сразу после предыдущего и увеличивает шаг между вершинами на размер добавленного атрибута. Смещения рассчитываются по указанным форматам, без анализа структуры C#. Для этих двух полей получается следующая раскладка:' +tutorial.input.guidance: 'Значение {semanticIndex} по умолчанию равно нулю и соответствует {pOSITION0} и {cOLOR0} в шейдере. Позиция и цвет хранятся вместе в одном вершинном буфере, поэтому конвейер использует одно описание входных данных в слоте 0. Если порядок полей или выравнивающие промежутки в структуре C# изменятся, измените и это описание.' tutorial.input.table.headings.byteOffset: Байтовое смещение -tutorial.input.table.headings.cField: "Поле C#" +tutorial.input.table.headings.cField: 'Поле C#' tutorial.input.table.headings.format: Формат tutorial.input.table.headings.shaderInput: Вход шейдера tutorial.input.table.nextVertex.cField: Следующая вершина -tutorial.input.table.nextVertex.format: "Полный шаг: 28 байт" +tutorial.input.table.nextVertex.format: 'Полный шаг: 28 байт' tutorial.input.table.nextVertex.shaderInput: Следующая входная запись -tutorial.input.table.vertexColor.format: "{float4} (16 байт)" -tutorial.input.table.vertexPosition.format: "{float3} (12 байт)" -tutorial.input.title: "Описание вершинного входа" -tutorial.lifecycle.description: "Каждый кадр выполняется в таком порядке:" -tutorial.lifecycle.details: "После закрытия окна {run} возвращает управление, и выполнение продолжается в коде освобождения ресурсов. Каждый кадр уже дождался завершения своих команд, поэтому использованные ими ресурсы можно освободить. Полный код после {windowRun} выглядит так:" -tutorial.lifecycle.guidance: "Освободите цепочку обмена перед уничтожением её окна, а контекст — после его ресурсов. Очередь повторно использует отправленные командные буферы, а цепочка обмена управляет своей выходной текстурой. Отдельный вызов {dispose} для этих объектов не нужен." -tutorial.lifecycle.title: "Цикл кадра и освобождение ресурсов" -tutorial.pipeline.behavior: "После описания входа создайте конвейер:" -tutorial.pipeline.context: "{cullNone} отключает отбрасывание граней. Треугольник будет нарисован независимо от того, расположены ли его вершины на экране по часовой стрелке или против неё." -tutorial.pipeline.description: "{graphicsPipeline} объединяет описание вершин, два шейдера и настройки сборки примитивов и записи во вложения." -tutorial.pipeline.details: "Шейдеры обрабатывают вершины и фрагменты. Остальные настройки конвейера управляют сборкой примитивов, отбрасыванием граней, проверкой глубины и смешиванием цветов:" -tutorial.pipeline.guidance: "Цветовой формат конвейера должен совпадать с вложением прохода, поэтому берётся из {swapChainDescFormat}. {count1} задаёт одну выборку на пиксель." -tutorial.pipeline.item: "{triangleList} собирает каждую последовательную тройку вершин в треугольник." -tutorial.pipeline.notes: "{depthNone} отключает проверку и запись глубины, что соответствует отсутствию вложения глубины." -tutorial.pipeline.reference: "{opaque} отключает смешивание. Поэтому результат фрагментного шейдера заменяет фон внутри треугольника." -tutorial.pipeline.title: "Графический конвейер" -tutorial.pipeline.usage: "Объекты шейдеров можно освободить после создания конвейера. Сам конвейер сохраняйте на время рендеринга; в коде освобождения добавьте {pipelineDispose} перед {vertexBufferDispose}." -tutorial.presentation.title: "Графический контекст и вывод" -tutorial.project.context: "В настройках сборки включите «{emphasis}» ({allowUnsafeBlocks}). Небезопасный код нужен для нативных вызовов вспомогательного оконного кода и загрузки вершин." +tutorial.input.table.vertexColor.format: '{float4} (16 байт)' +tutorial.input.table.vertexPosition.format: '{float3} (12 байт)' +tutorial.input.title: 'Описание вершинного входа' +tutorial.lifecycle.description: 'Каждый кадр выполняется в таком порядке:' +tutorial.lifecycle.details: 'После закрытия окна {run} возвращает управление, и выполнение продолжается в коде освобождения ресурсов. Каждый кадр уже дождался завершения своих команд, поэтому использованные ими ресурсы можно освободить. Полный код после {windowRun} выглядит так:' +tutorial.lifecycle.guidance: 'Освободите цепочку обмена перед уничтожением её окна, а контекст — после его ресурсов. Очередь повторно использует отправленные командные буферы, а цепочка обмена управляет своей выходной текстурой. Отдельный вызов {dispose} для этих объектов не нужен.' +tutorial.lifecycle.title: 'Цикл кадра и освобождение ресурсов' +tutorial.pipeline.behavior: 'После описания входа создайте конвейер:' +tutorial.pipeline.context: '{cullNone} отключает отбрасывание граней. Треугольник будет нарисован независимо от того, расположены ли его вершины на экране по часовой стрелке или против неё.' +tutorial.pipeline.description: '{graphicsPipeline} объединяет описание вершин, два шейдера и настройки сборки примитивов и записи во вложения.' +tutorial.pipeline.details: 'Шейдеры обрабатывают вершины и фрагменты. Остальные настройки конвейера управляют сборкой примитивов, отбрасыванием граней, проверкой глубины и смешиванием цветов:' +tutorial.pipeline.guidance: 'Цветовой формат конвейера должен совпадать с вложением прохода, поэтому берётся из {swapChainDescFormat}. {count1} задаёт одну выборку на пиксель.' +tutorial.pipeline.item: '{triangleList} собирает каждую последовательную тройку вершин в треугольник.' +tutorial.pipeline.notes: '{depthNone} отключает проверку и запись глубины, что соответствует отсутствию вложения глубины.' +tutorial.pipeline.reference: '{opaque} отключает смешивание. Поэтому результат фрагментного шейдера заменяет фон внутри треугольника.' +tutorial.pipeline.title: 'Графический конвейер' +tutorial.pipeline.usage: 'Объекты шейдеров можно освободить после создания конвейера. Сам конвейер сохраняйте на время рендеринга; в коде освобождения добавьте {pipelineDispose} перед {vertexBufferDispose}.' +tutorial.presentation.title: 'Графический контекст и вывод' +tutorial.project.context: 'В настройках сборки включите «{emphasis}» ({allowUnsafeBlocks}). Небезопасный код нужен для нативных вызовов вспомогательного оконного кода и загрузки вершин.' tutorial.project.context.emphasis: Разрешить небезопасный код -tutorial.project.description: "Создайте консольный проект C# с именем {firstTriangle} для .NET 10." -tutorial.project.details: "Добавьте в проект следующие пакеты NuGet:" -tutorial.project.guidance: "{zenithNET} предоставляет общий API рендеринга, а три пакета бэкендов — его платформенные реализации. {zenithNETCompiler} компилирует шейдеры Slang для выбранного бэкенда. Silk.NET создаёт окно и обрабатывает события." -tutorial.project.title: "Настройка проекта" -tutorial.requirements.context: "Образцы кода для этого урока — {link} и его {detail}." -tutorial.requirements.context.detail: "общая оболочка" -tutorial.requirements.context.link: "пример Hello Triangle" -tutorial.requirements.description: "Нужны {emphasis} и базовое знание C#. Приложение предназначено для {net10}. GPU и драйвер должны поддерживать бэкенд, выбранный для вашей платформы:" +tutorial.project.description: 'Создайте консольный проект C# с именем {firstTriangle} для .NET 10.' +tutorial.project.details: 'Добавьте в проект следующие пакеты NuGet:' +tutorial.project.guidance: '{zenithNET} предоставляет общий API рендеринга, а три пакета бэкендов — его платформенные реализации. {zenithNETCompiler} компилирует шейдеры Slang для выбранного бэкенда. Silk.NET создаёт окно и обрабатывает события.' +tutorial.project.title: 'Настройка проекта' +tutorial.requirements.context: 'Образцы кода для этого урока — {link} и его {detail}.' +tutorial.requirements.context.detail: 'общая оболочка' +tutorial.requirements.context.link: 'пример Hello Triangle' +tutorial.requirements.description: 'Нужны {emphasis} и базовое знание C#. Приложение предназначено для {net10}. GPU и драйвер должны поддерживать бэкенд, выбранный для вашей платформы:' tutorial.requirements.description.emphasis: .NET 10 SDK -tutorial.requirements.guidance: "Zenith.NET выполняет рендеринг на нативной поверхности, предоставленной приложением. Silk.NET.Windowing создаёт окно и обрабатывает его события. На macOS для вывода используется слой Metal, представленный в {cAMetalLayerCs}; вспомогательный код связывает его с окном." +tutorial.requirements.guidance: 'Zenith.NET выполняет рендеринг на нативной поверхности, предоставленной приложением. Silk.NET.Windowing создаёт окно и обрабатывает его события. На macOS для вывода используется слой Metal, представленный в {cAMetalLayerCs}; вспомогательный код связывает его с окном.' tutorial.requirements.table.headings.graphicsBackend: Графический бэкенд tutorial.requirements.table.headings.platform: Платформа tutorial.requirements.table.linux.graphicsBackend: Vulkan 1.4 -tutorial.requirements.table.linux.platform: "Linux (X11 или XWayland)" +tutorial.requirements.table.linux.platform: 'Linux (X11 или XWayland)' tutorial.requirements.table.macOS.graphicsBackend: Metal 4 tutorial.requirements.table.macOS.platform: macOS tutorial.requirements.table.windows.graphicsBackend: DirectX 12 tutorial.requirements.table.windows.platform: Windows -tutorial.requirements.title: "Необходимые условия" -tutorial.resize.context: "Снова соберите и запустите приложение. Фон должен заполнять всё окно и после изменения его размера: каждый новый проход задаёт область вывода и прямоугольник отсечения по размерам вложения. Сохраните обработчик рендеринга — в его проход будет добавлено рисование треугольника." -tutorial.resize.description: "Размер изображений цепочки обмена должен соответствовать кадровому буферу. Зарегистрируйте обработчик {framebufferResize} после обработчика рендеринга и перед {windowRun}:" -tutorial.resize.details: "Отслеживайте {link}, измеряемые в пикселях, а не изменения логических размеров окна. Если при сворачивании окна ширина или высота кадрового буфера становится нулевой, обработчик изменения размера оставляет цепочку обмена без изменений. Обработчик рендеринга тоже сразу возвращается, пока хотя бы один размер равен нулю. Рендеринг возобновляется, когда размеры снова позволяют вывести изображение." -tutorial.resize.details.link: "изменения размера кадрового буфера" -tutorial.resize.guidance: "Перед вызовом {present} обработчик рендеринга дожидается завершения команд текущего кадра. Поэтому обработчик изменения размера может заменить изображения цепочки обмена, не прерывая работу предыдущего кадра. Связь завершения команд со временем жизни ресурсов подробнее описана в статье «{link}»." +tutorial.requirements.title: 'Необходимые условия' +tutorial.resize.context: 'Снова соберите и запустите приложение. Фон должен заполнять всё окно и после изменения его размера: каждый новый проход задаёт область вывода и прямоугольник отсечения по размерам вложения. Сохраните обработчик рендеринга — в его проход будет добавлено рисование треугольника.' +tutorial.resize.description: 'Размер изображений цепочки обмена должен соответствовать кадровому буферу. Зарегистрируйте обработчик {framebufferResize} после обработчика рендеринга и перед {windowRun}:' +tutorial.resize.details: 'Отслеживайте {link}, измеряемые в пикселях, а не изменения логических размеров окна. Если при сворачивании окна ширина или высота кадрового буфера становится нулевой, обработчик изменения размера оставляет цепочку обмена без изменений. Обработчик рендеринга тоже сразу возвращается, пока хотя бы один размер равен нулю. Рендеринг возобновляется, когда размеры снова позволяют вывести изображение.' +tutorial.resize.details.link: 'изменения размера кадрового буфера' +tutorial.resize.guidance: 'Перед вызовом {present} обработчик рендеринга дожидается завершения команд текущего кадра. Поэтому обработчик изменения размера может заменить изображения цепочки обмена, не прерывая работу предыдущего кадра. Связь завершения команд со временем жизни ресурсов подробнее описана в статье «{link}».' tutorial.resize.guidance.link: Синхронизация -tutorial.resize.title: "Изменение размера" -tutorial.shaders.compilation.context: "{appContextBaseDirectory} позволяет загрузить копию шейдера из выходного каталога приложения. Поэтому запуск из другого рабочего каталога не меняет место поиска файла." -tutorial.shaders.compilation.description: "В свойствах {triangleSlang} задайте параметру «{emphasis}» значение «{detail}». При сборке шейдер будет скопирован рядом с исполняемым файлом." +tutorial.resize.title: 'Изменение размера' +tutorial.shaders.compilation.context: '{appContextBaseDirectory} позволяет загрузить копию шейдера из выходного каталога приложения. Поэтому запуск из другого рабочего каталога не меняет место поиска файла.' +tutorial.shaders.compilation.description: 'В свойствах {triangleSlang} задайте параметру «{emphasis}» значение «{detail}». При сборке шейдер будет скопирован рядом с исполняемым файлом.' tutorial.shaders.compilation.description.detail: Копировать более позднюю версию tutorial.shaders.compilation.description.emphasis: Копировать в выходной каталог -tutorial.shaders.compilation.details: "В {programCs} добавьте инициализацию шейдеров после загрузки вершин и до обработчика рендеринга:" -tutorial.shaders.compilation.guidance: "{zenithCompiler} компилирует исходный код для {contextGraphicsApi}, а {createShader} создаёт объект шейдера из полученного описания. Имена точек входа {vSMain} и {fSMain} выбирают две функции, определённые в файле Slang." -tutorial.shaders.compilation.title: "Компиляция шейдеров" -tutorial.shaders.context: "{fSInput} связывает две шейдерные стадии. Вершинный шейдер записывает в {sVPOSITION} позицию в пространстве отсечения; по ней GPU определяет видимую часть треугольника. Поле {cOLOR0} передаёт цвет вершины, который интерполируется по треугольнику перед поступлением во фрагментный шейдер. Тип и семантика этого поля должны совпадать между стадиями." -tutorial.shaders.description: "Шейдеры — программы, выполняемые на GPU. Вершинный шейдер определяет положение каждой вершины, а фрагментный — цвет в точках изображения, покрытых треугольником. Обе стадии будут записаны в одном файле Slang. Для каждой задаётся отдельная точка входа — функция, с которой начинается выполнение." -tutorial.shaders.details: "Создайте {triangleSlang} с этими структурами входа и выхода:" -tutorial.shaders.fragment.description: "Добавьте в тот же файл точку входа фрагментного шейдера:" -tutorial.shaders.fragment.details: "Растеризация определяет, какие точки изображения покрывает треугольник, и создаёт для них фрагменты. Каждый фрагмент получает цвет, интерполированный из цветов трёх вершин. {fSMain} возвращает этот цвет, а {sVTARGET} направляет результат в первое цветовое вложение." -tutorial.shaders.fragment.title: "Фрагментный шейдер" -tutorial.shaders.guidance: "{vSInput} задаёт вход вершинного шейдера. {pOSITION0} и {cOLOR0} связывают атрибуты по семантикам; одних имён полей C# для этого недостаточно." -tutorial.shaders.title: "Стадии шейдеров" -tutorial.shaders.vertex.description: "Добавьте в {triangleSlang} точку входа вершинного шейдера:" -tutorial.shaders.vertex.details: "GPU вызывает её для каждой входной вершины. Функция добавляет однородную координату {w} и передаёт цвет. После обработки вершин позиция делится на w. Здесь w = 1, поэтому x, y и z не меняются и непосредственно задают нормализованные координаты устройства." -tutorial.shaders.vertex.title: "Вершинный шейдер" -tutorial.surface.description: "Задайте нативную поверхность вывода {emphasis}:" +tutorial.shaders.compilation.details: 'В {programCs} добавьте инициализацию шейдеров после загрузки вершин и до обработчика рендеринга:' +tutorial.shaders.compilation.guidance: '{zenithCompiler} компилирует исходный код для {contextGraphicsApi}, а {createShader} создаёт объект шейдера из полученного описания. Имена точек входа {vSMain} и {fSMain} выбирают две функции, определённые в файле Slang.' +tutorial.shaders.compilation.title: 'Компиляция шейдеров' +tutorial.shaders.context: '{fSInput} связывает две шейдерные стадии. Вершинный шейдер записывает в {sVPOSITION} позицию в пространстве отсечения; по ней GPU определяет видимую часть треугольника. Поле {cOLOR0} передаёт цвет вершины, который интерполируется по треугольнику перед поступлением во фрагментный шейдер. Тип и семантика этого поля должны совпадать между стадиями.' +tutorial.shaders.description: 'Шейдеры — программы, выполняемые на GPU. Вершинный шейдер определяет положение каждой вершины, а фрагментный — цвет в точках изображения, покрытых треугольником. Обе стадии будут записаны в одном файле Slang. Для каждой задаётся отдельная точка входа — функция, с которой начинается выполнение.' +tutorial.shaders.details: 'Создайте {triangleSlang} с этими структурами входа и выхода:' +tutorial.shaders.fragment.description: 'Добавьте в тот же файл точку входа фрагментного шейдера:' +tutorial.shaders.fragment.details: 'Растеризация определяет, какие точки изображения покрывает треугольник, и создаёт для них фрагменты. Каждый фрагмент получает цвет, интерполированный из цветов трёх вершин. {fSMain} возвращает этот цвет, а {sVTARGET} направляет результат в первое цветовое вложение.' +tutorial.shaders.fragment.title: 'Фрагментный шейдер' +tutorial.shaders.guidance: '{vSInput} задаёт вход вершинного шейдера. {pOSITION0} и {cOLOR0} связывают атрибуты по семантикам; одних имён полей C# для этого недостаточно.' +tutorial.shaders.title: 'Стадии шейдеров' +tutorial.shaders.vertex.description: 'Добавьте в {triangleSlang} точку входа вершинного шейдера:' +tutorial.shaders.vertex.details: 'GPU вызывает её для каждой входной вершины. Функция добавляет однородную координату {w} и передаёт цвет. После обработки вершин позиция делится на w. Здесь w = 1, поэтому x, y и z не меняются и непосредственно задают нормализованные координаты устройства.' +tutorial.shaders.vertex.title: 'Вершинный шейдер' +tutorial.surface.description: 'Задайте нативную поверхность вывода {emphasis}:' tutorial.surface.description.emphasis: после {windowCenter} и перед {windowRun} -tutorial.surface.details: "Кадровый буфер — изображение окна в пикселях. {surface} описывает нативный объект вывода и его размеры; {framebufferSize} сообщает размер в пикселях. При масштабировании экрана он может отличаться от логического размера окна." -tutorial.surface.guidance: "Поверхность предоставляет нативные дескрипторы выбранного бэкенда: окно Win32 в Windows, дисплей и окно X11 в Linux или прикреплённый слой Metal в macOS." -tutorial.surface.title: "Нативная поверхность" -tutorial.swapChain.context: "Цепочка обмена зависит от контекста и окна. Замените {windowDispose} в конце {programCs} следующим порядком освобождения:" -tutorial.swapChain.description: "Создайте цепочку обмена сразу после описания поверхности:" -tutorial.swapChain.details: "{swapChain} управляет изображениями, выводимыми в окно. {drawable} предоставляет текущее изображение в виде {texture} — ресурса для хранения изображения в API. После рендеринга {present} запрашивает его вывод и переходит к следующей выходной текстуре." -tutorial.swapChain.guidance: "{b8G8R8A8UNorm} хранит четыре 8-битных канала в порядке синий, зелёный, красный, альфа. {uNorm} отображает целые 0–255 в значения 0–1. Выход шейдера остаётся логическим RGBA; формат задаёт представление в памяти. Конвейер использует {swapChainDescFormat} для соответствия вложению." -tutorial.swapChain.title: "Цепочка обмена" +tutorial.surface.details: 'Кадровый буфер — изображение окна в пикселях. {surface} описывает нативный объект вывода и его размеры; {framebufferSize} сообщает размер в пикселях. При масштабировании экрана он может отличаться от логического размера окна.' +tutorial.surface.guidance: 'Поверхность предоставляет нативные дескрипторы выбранного бэкенда: окно Win32 в Windows, дисплей и окно X11 в Linux или прикреплённый слой Metal в macOS.' +tutorial.surface.title: 'Нативная поверхность' +tutorial.swapChain.context: 'Цепочка обмена зависит от контекста и окна. Замените {windowDispose} в конце {programCs} следующим порядком освобождения:' +tutorial.swapChain.description: 'Создайте цепочку обмена сразу после описания поверхности:' +tutorial.swapChain.details: '{swapChain} управляет изображениями, выводимыми в окно. {drawable} предоставляет текущее изображение в виде {texture} — ресурса для хранения изображения в API. После рендеринга {present} запрашивает его вывод и переходит к следующей выходной текстуре.' +tutorial.swapChain.guidance: '{b8G8R8A8UNorm} хранит четыре 8-битных канала в порядке синий, зелёный, красный, альфа. {uNorm} отображает целые 0–255 в значения 0–1. Выход шейдера остаётся логическим RGBA; формат задаёт представление в памяти. Конвейер использует {swapChainDescFormat} для соответствия вложению.' +tutorial.swapChain.title: 'Цепочка обмена' tutorial.title: Первый треугольник -tutorial.troubleshooting.description: "Используйте сообщения консоли и три контрольных результата, чтобы определить этап ошибки:" -tutorial.troubleshooting.details: "{link} и {detail} служат образцами для проверки данных вершин, описания вершинного ввода и команд рисования. В этом примере создание окна и отправка команд вынесены в общую оболочку; в уроке весь порядок работы приложения остаётся в {programCs}. Пример «{context}» знакомит с индексированным рисованием, преобразованиями и проверкой глубины." +tutorial.troubleshooting.description: 'Используйте сообщения консоли и три контрольных результата, чтобы определить этап ошибки:' +tutorial.troubleshooting.details: '{link} и {detail} служат образцами для проверки данных вершин, описания вершинного ввода и команд рисования. В этом примере создание окна и отправка команд вынесены в общую оболочку; в уроке весь порядок работы приложения остаётся в {programCs}. Пример «{context}» знакомит с индексированным рисованием, преобразованиями и проверкой глубины.' tutorial.troubleshooting.details.context: Вращающийся куб tutorial.troubleshooting.details.detail: шейдер Slang -tutorial.troubleshooting.details.link: "Демонстрационный рендерер" +tutorial.troubleshooting.details.link: 'Демонстрационный рендерер' tutorial.troubleshooting.table.backend.check: Убедитесь, что выбранный бэкенд поддерживается устройством и установленным графическим драйвером. tutorial.troubleshooting.table.backend.symptom: Сбой создания бэкенда -tutorial.troubleshooting.table.drawing.check: "Проверьте размер загрузки, описание вершинного входа, выбор конвейера и расположение команд рисования внутри прохода." +tutorial.troubleshooting.table.drawing.check: 'Проверьте размер загрузки, описание вершинного входа, выбор конвейера и расположение команд рисования внутри прохода.' tutorial.troubleshooting.table.drawing.symptom: Фон отображается, но треугольника нет tutorial.troubleshooting.table.headings.check: Что проверить tutorial.troubleshooting.table.headings.symptom: Симптом -tutorial.troubleshooting.table.input.check: "Проверьте шаг в 28 байт и смещения положения и цвета: 0 и 12." +tutorial.troubleshooting.table.input.check: 'Проверьте шаг в 28 байт и смещения положения и цвета: 0 и 12.' tutorial.troubleshooting.table.input.symptom: Искажены координаты или цвета вершин tutorial.troubleshooting.table.shaders.check: Проверьте скопированный файл {triangleSlang}, правильность написания точек входа и сообщения об ошибках от компилятора. tutorial.troubleshooting.table.shaders.symptom: Очистка цветом работает, но загрузка шейдеров завершается ошибкой tutorial.troubleshooting.table.window.check: Убедитесь, что проект .NET собирается и шаг с простым окном выполняется в сессии рабочего стола. В Linux проверьте доступность X11 или XWayland. tutorial.troubleshooting.table.window.symptom: Окно не открывается -tutorial.troubleshooting.title: "Диагностика ошибок" -tutorial.window.description: "Скачайте {cocoaHelperCs} в проект. Этот вспомогательный класс связывает слой Metal с окном macOS." -tutorial.window.details: "Замените сгенерированный код {programCs} следующим. Операторы верхнего уровня выполняются по порядку без явно объявленного метода {main}. В следующих разделах будет указано, куда добавлять каждый фрагмент:" -tutorial.window.guidance: "{graphicsAPINone} оставляет создание графического контекста за Zenith.NET. {initialize} создаёт нативное окно и открывает доступ к дескрипторам оконной системы. {center} размещает окно по центру экрана. {run} обрабатывает события до закрытия окна, после чего {dispose} освобождает его." -tutorial.window.notes: "Соберите и запустите приложение. Убедитесь, что окно открывается и закрывается, его можно перемещать и менять его размер. Содержимое пока не определено, поскольку команды рендеринга ещё не отправлены. Закройте окно перед продолжением." -tutorial.window.title: "Создание окна" +tutorial.troubleshooting.title: 'Диагностика ошибок' +tutorial.window.description: 'Скачайте {cocoaHelperCs} в проект. Этот вспомогательный класс связывает слой Metal с окном macOS.' +tutorial.window.details: 'Замените сгенерированный код {programCs} следующим. Операторы верхнего уровня выполняются по порядку без явно объявленного метода {main}. В следующих разделах будет указано, куда добавлять каждый фрагмент:' +tutorial.window.guidance: '{graphicsAPINone} оставляет создание графического контекста за Zenith.NET. {initialize} создаёт нативное окно и открывает доступ к дескрипторам оконной системы. {center} размещает окно по центру экрана. {run} обрабатывает события до закрытия окна, после чего {dispose} освобождает его.' +tutorial.window.notes: 'Соберите и запустите приложение. Убедитесь, что окно открывается и закрывается, его можно перемещать и менять его размер. Содержимое пока не определено, поскольку команды рендеринга ещё не отправлены. Закройте окно перед продолжением.' +tutorial.window.title: 'Создание окна' ui.action.copy: Копировать ui.action.navigate: Перейти ui.action.open: Открыть @@ -526,11 +526,11 @@ ui.api.noTypes: Совпадающих типов не найдено. ui.api.types: Типы ui.content.reference: Справочник ui.content.source: Исходный код -ui.content.tutorial: "Урок" +ui.content.tutorial: 'Урок' ui.contents.close: Закрыть оглавление ui.contents.open: Открыть оглавление ui.contents.title: Содержание -ui.footer.caption: "Графический API для .NET" +ui.footer.caption: 'Графический API для .NET' ui.footer.label: Нижний колонтитул ui.language.label: Язык ui.language.unavailable: Не переведено @@ -543,7 +543,7 @@ ui.members.search: Поиск членов ui.members.title: Найти член ui.members.undeclared: У этого типа нет объявленных членов. ui.navigation.api: API -ui.navigation.concepts: "Основные понятия" +ui.navigation.concepts: 'Основные понятия' ui.navigation.home: Главная ui.navigation.label: Основная навигация ui.navigation.skip: Перейти к содержимому @@ -552,7 +552,7 @@ ui.outline.title: На этой странице ui.reference.assembly: Сборка ui.reference.classes: Классы ui.reference.constructors: Конструкторы -ui.reference.declaration: "Объявление типа C#" +ui.reference.declaration: 'Объявление типа C#' ui.reference.delegates: Делегаты ui.reference.derived: Производные типы ui.reference.enums: Перечисления @@ -583,11 +583,11 @@ ui.reference.value: Значение ui.reference.values: Значения ui.search.close: Закрыть поиск ui.search.empty: По запросу «{query}» ничего не найдено. -ui.search.hint: "Поиск по урокам, основным понятиям, примерам и справочнику API." +ui.search.hint: 'Поиск по урокам, основным понятиям, примерам и справочнику API.' ui.search.loading: Загрузка поиска… ui.search.more: Показать больше результатов ui.search.pending: Поиск… ui.search.placeholder: Что вы ищете? -ui.search.resultCount: "Результатов: {count}" +ui.search.resultCount: 'Результатов: {count}' ui.search.title: Поиск по документации ui.search.unavailable: Поиск недоступен. Вы можете открыть страницы из списка ниже. diff --git a/documents/locales/ru-RU/translation.md b/documents/locales/ru-RU/translation.md index dae0b27a..cccf8146 100644 --- a/documents/locales/ru-RU/translation.md +++ b/documents/locales/ru-RU/translation.md @@ -2,7 +2,7 @@ ## Ресурсы и структура -[Английский словарь ресурсов](../en-US/strings.yml) — единственный источник текста. Правила проекта описаны в [руководстве по сопровождению документации](../../authoring.md). Начиная новый перевод, скопируйте английский файл целиком в `strings.yml` в этом каталоге. Сохраните первую строку `### YamlMime:Resources` и кодировку UTF-8. При обновлении учитывайте изменения оригинала, не перезаписывая существующие переводы. Этот файл `translation.md` сохраняется постоянно и не публикуется на сайте. +[Английский словарь ресурсов](../en-US/strings.yml) — единственный источник текста. Правила проекта описаны в [руководстве по сопровождению документации](../../maintenance.md). Начиная новый перевод, скопируйте английский файл целиком в `strings.yml` в этом каталоге. Сохраните первую строку `### YamlMime:Resources` и кодировку UTF-8. При обновлении учитывайте изменения оригинала, не перезаписывая существующие переводы. Этот файл `translation.md` сохраняется постоянно и не публикуется на сайте. Навигация, порядок глав, якоря, ссылки, форматирование, код и изображения общие для всех языков и находятся вне `locales/`. Не добавляйте в этот каталог статьи, TOC, шаблоны, сценарии или настройки. @@ -65,21 +65,21 @@ docfx serve documents/_site --hostname 127.0.0.1 --port 8080 ## Терминология -| Английский термин | Принятый вариант | -| --- | --- | -| API / GPU / RHI | Сохранять сокращения и пояснять их по оригиналу | -| barrier | барьер | -| buffer | буфер; `Buffer` не изменять | -| command buffer | командный буфер | -| command queue | очередь команд | -| drawable | выходная текстура текущего кадра; `Drawable` не изменять и не считать обязательно изображением цепочки обмена | -| graphics context | графический контекст | -| pipeline | конвейер | -| readback | считывание данных с GPU | -| render pass | проход рендеринга | -| resource | ресурс | -| shader | шейдер | -| swap chain | цепочка обмена | -| texture | текстура | -| timeline | временная шкала | -| upload | загрузка данных на GPU | +| Английский термин | Принятый вариант | +| ----------------- | ------------------------------------------------------------------------------------------------------------- | +| API / GPU / RHI | Сохранять сокращения и пояснять их по оригиналу | +| barrier | барьер | +| buffer | буфер; `Buffer` не изменять | +| command buffer | командный буфер | +| command queue | очередь команд | +| drawable | выходная текстура текущего кадра; `Drawable` не изменять и не считать обязательно изображением цепочки обмена | +| graphics context | графический контекст | +| pipeline | конвейер | +| readback | считывание данных с GPU | +| render pass | проход рендеринга | +| resource | ресурс | +| shader | шейдер | +| swap chain | цепочка обмена | +| texture | текстура | +| timeline | временная шкала | +| upload | загрузка данных на GPU | diff --git a/documents/locales/zh-CN/strings.yml b/documents/locales/zh-CN/strings.yml index 5f54a118..c20b4be4 100644 --- a/documents/locales/zh-CN/strings.yml +++ b/documents/locales/zh-CN/strings.yml @@ -1,593 +1,593 @@ ### YamlMime:Resources -concepts.execution.context.description: "{graphicsContext} 通过特定后端连接应用程序与 GPU 设备,并提供图形、计算和传输队列。配合使用的资源必须属于同一上下文;缓冲区、纹理、着色器、管线及其句柄不能跨上下文绑定。" -concepts.execution.context.details: "{capabilities} 提供设备名称与支持的功能。创建光线追踪或网格着色所需的资源前,分别通过 {rayTracingSupported} 和 {meshShadingSupported} 检查支持情况。{link}与{detail}示例展示了初始化时的检查方式。" -concepts.execution.context.details.detail: "网格着色" -concepts.execution.context.details.link: "光线追踪" -concepts.execution.context.title: "图形上下文" -concepts.execution.description: "GPU 工作从 CPU 端开始:应用程序创建资源,录制使用这些资源的命令,再将命令提交到队列。提交之后,CPU 可以继续处理其他任务,同时由 GPU 执行命令。相关资源必须保留到执行结束。" -concepts.execution.ownership.description: "所有权决定由谁释放对象,GPU 完成状态决定何时可以释放。即使仍保留对象的 C# 引用,调用 {dispose} 也会释放其原生资源。提交命令不会将资源所有权转交给队列。" -concepts.execution.ownership.details: "关闭程序时,先停止提交新工作,并等待所有相关队列完成最后一次资源访问。随后释放应用程序资源,最后释放上下文。上下文会释放自身的队列和内部辅助对象,因此这一步应在应用程序工作全部完成后进行。" -concepts.execution.ownership.guidance: "渲染期间,若准备覆盖数据或替换资源,应跟踪仍在使用它们的工作。等待这些访问完成后,再修改数据或释放存储。视图与底层资源如何遵循这一生命周期规则,见{link}。" -concepts.execution.ownership.guidance.link: "资源管理" -concepts.execution.ownership.table.applicationResources.object: "应用程序创建的资源" -concepts.execution.ownership.table.applicationResources.ownership: "最后一次 GPU 使用完成后,由应用程序释放。" -concepts.execution.ownership.table.commandBuffers.object: "借用的命令缓冲区" -concepts.execution.ownership.table.commandBuffers.ownership: "由队列管理和回收。" -concepts.execution.ownership.table.headings.object: "对象" -concepts.execution.ownership.table.headings.ownership: "释放责任" -concepts.execution.ownership.table.queues.object: "图形上下文的队列及其时间线" -concepts.execution.ownership.table.queues.ownership: "由上下文和队列管理。" -concepts.execution.ownership.table.swapChainDrawable.ownership: "由交换链管理。" -concepts.execution.ownership.title: "所有权与生命周期" -concepts.execution.pipelines.description: "图形管线规定绘制所用的着色器、顶点输入布局、图元组装方式、附件格式和渲染状态。绑定顶点、索引或常量数据之前,须先选择管线;管线声明的附件格式与采样数也必须与渲染通道一致。" -concepts.execution.pipelines.details: "计算管线选择分派所执行的着色器入口点。在图形渲染通道之外,先绑定管线及其常量,再执行分派。" -concepts.execution.pipelines.guidance: "{link}给出了完整的图形命令顺序。{detail}则先执行计算分派,再通过图形通道显示结果。" -concepts.execution.pipelines.guidance.detail: "计算示例" -concepts.execution.pipelines.guidance.link: "三角形的渲染回调" -concepts.execution.pipelines.title: "管线状态" -concepts.execution.queues.description: "一帧同时包含绘制、计算和复制时,通常从 {graphicsQueue} 开始。将有依赖的操作放在同一队列,有助于明确执行顺序。" -concepts.execution.queues.details: "不同队列可以分别接收独立的工作负载,但未必对应独立的硬件引擎。若工作能够从重叠执行中受益,再考虑增加队列。当一个队列使用另一个队列生成的数据时,需要在两次提交之间建立显式依赖。" -concepts.execution.queues.guidance: "即使位于同一队列,有依赖的操作也可能需要屏障或纹理转换,才能让后续访问读到此前写入的结果。这种内存依赖与提交顺序不同,具体表达方式见{link}。" -concepts.execution.queues.guidance.link: "同步" -concepts.execution.queues.table.computeQueue.workToRecord: "计算分派以及兼容的传输工作,不含图形渲染通道。" -concepts.execution.queues.table.graphicsQueue.workToRecord: "渲染通道、绘制、计算与传输操作。" -concepts.execution.queues.table.headings.queue: "队列" -concepts.execution.queues.table.headings.workToRecord: "支持的工作" -concepts.execution.queues.table.transferQueue.workToRecord: "上传、回读与复制工作,不含绘制或计算分派。" -concepts.execution.queues.title: "队列选择" -concepts.execution.recording.context: "队列会回收已完成的命令缓冲区以供复用。每次录制时,通过 {queueCommandBuffer} 获取缓冲区,同一时间只由一个线程录制,并且只提交一次。提交后,将缓冲区交由队列管理,不再修改、重复提交或自行释放。" -concepts.execution.recording.description: "{queueCommandBuffer} 返回的 {commandBuffer} 已处于录制状态。录制完操作及其依赖后,调用一次 {submit}。提交会结束录制,并返回标识该队列完成点的 {timelineValue}。" -concepts.execution.recording.details: "三角形教程将一帧录制到 {commandBuffer} 后,按如下方式提交并等待完成:" -concepts.execution.recording.guidance: "录制构造命令序列,{submit} 安排该序列执行。随后调用 {wait},CPU 线程会等待本次提交完成。教程因此采用逐帧执行的流程:当前帧完成后,才开始下一帧。" -concepts.execution.recording.title: "录制与提交" -concepts.execution.title: "执行模型" -concepts.platforms.description: "呈现流程可以由应用程序管理,也可以交给 UI 渲染控件。这决定了谁来获取当前帧的输出纹理、录制和提交命令,以及显示渲染结果。" -concepts.platforms.frame.context: "在通道内绑定管线并录制绘制命令,处理程序返回前须结束通道。控件负责提交命令并呈现结果;处理程序不得自行提交命令缓冲区,也不得释放传入的命令缓冲区或输出纹理。若改变了输出纹理的布局,返回前须恢复为 {colorAttachment},以便控件完成最后的转换。" -concepts.platforms.frame.description: "各控件实现 {iZenithView} 接口。应用程序设置 {graphicsContext},在 {updateRequested} 中更新场景,并在 {renderRequested} 中通过传入的 {renderEventArgs} 录制命令。" -concepts.platforms.frame.details: "每帧,控件获取输出纹理与命令缓冲区,将输出纹理转换为 {colorAttachment},再调用更新和渲染处理程序。之后,控件提交录制的工作,并通过对应框架的呈现机制显示图像。" -concepts.platforms.frame.guidance: "先在文件中添加 {usingZenithNET}。假定名为 {view} 的 {iZenithView} 实例已初始化并设置图形上下文,可注册以下处理程序清除其输出纹理:" -concepts.platforms.frame.notes: "初始转换使用 {undefined},允许丢弃先前图像的内容。因此,每帧都应重新绘制或清除整张图像。需要累积或缓存的渲染结果,可保存在应用程序拥有的纹理中,再将该纹理绘制到控件的输出纹理上。" -concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat} 提供这些集成使用的默认颜色格式。" -concepts.platforms.frame.title: "通过 UI 控件渲染" -concepts.platforms.integration.context: "WinForms、WPF 和 Windows 版 WinUI 集成运行于 Windows。使用 MAUI 时,安装目标平台的工作负载,并通过 {useZenithView} 注册控件处理程序,具体见 {extensionsCs}。" -concepts.platforms.integration.description: "控件共享事件接口,但呈现机制因框架而异:" -concepts.platforms.integration.details: "各实现将 GPU 图像送到 UI 的方式不同。位图回读先将像素复制到 CPU 内存,再显示图像;共享纹理互操作可以省去这次 CPU 复制,但仍可能需要 GPU 复制与同步。选择集成方式时,除了共用的 {renderRequested} 事件接口,也应考虑其呈现路径。" -concepts.platforms.integration.guidance: "通过 NuGet 添加所用 UI 框架的集成包。Avalonia 对应的包为 {avaloniaPackage}。" -concepts.platforms.integration.table.avalonia.integration: "Avalonia" -concepts.platforms.integration.table.avalonia.presentation: "渲染到纹理后,将像素回读到 {writeableBitmap},实现见 {zenithViewCs} 和 {surfaceCs}。" -concepts.platforms.integration.table.headings.integration: "集成" -concepts.platforms.integration.table.headings.presentation: "呈现机制" -concepts.platforms.integration.table.maui.integration: ".NET MAUI" -concepts.platforms.integration.table.maui.presentation: "Android、iOS 和 Mac Catalyst 使用原生呈现目标;Windows 使用共享纹理合成,具体见{link}。" -concepts.platforms.integration.table.maui.presentation.link: "平台实现" -concepts.platforms.integration.table.uno.integration: "Uno 路径" -concepts.platforms.integration.table.uno.presentation: "将像素回读到 {writeableBitmap},实现见 {zenithViewUnoCs}。" -concepts.platforms.integration.table.winForms.integration: "WinForms" -concepts.platforms.integration.table.winForms.presentation: "为控件的 {hWND} 创建 Zenith.NET 交换链,实现见 {zenithViewCs}。" -concepts.platforms.integration.table.winUI.integration: "Windows 上的 WinUI" -concepts.platforms.integration.table.winUI.presentation: "渲染到导入的共享 Direct3D 11 纹理,再复制到与 {swapChainPanel} 连接的合成交换链,具体见 {zenithViewWinUICs}。" -concepts.platforms.integration.table.wpf.integration: "WPF" -concepts.platforms.integration.table.wpf.presentation: "导入共享 Direct3D 11 纹理,再经 Direct3D 互操作复制到由 {d3DImage} 显示的表面,具体见 {surfaceCs}。" -concepts.platforms.integration.title: "框架与呈现路径" -concepts.platforms.lifecycle.context: "创建配套附件时,使用渲染事件传入的输出纹理的 {descWidth}、{descHeight}、{descFormat} 和 {descSampleCount}。该纹理给出了渲染目标的实际尺寸,不应根据控件的布局尺寸或显示缩放比例推算。" -concepts.platforms.lifecycle.description: "交换链使用以像素计量的帧缓冲区宽度和高度。启用显示缩放时,这些值可能不同于窗口的逻辑尺寸。任一尺寸为零时,暂停渲染和交换链尺寸调整。每帧重新获取 {swapChainDrawable}:这张纹理由交换链管理,可能在呈现或调整大小后被替换。" -concepts.platforms.lifecycle.details: "帧缓冲区尺寸变化时,先等待 GPU 完成对旧图像的访问,再调用 {swapChainResize}。替换原生呈现目标时,也应先等待这些访问结束,再将新的呈现目标描述与句柄传给 {swapChainRefresh}。关闭程序时,先释放交换链,再销毁其原生呈现目标。" -concepts.platforms.lifecycle.guidance: "应用程序的深度纹理或离屏纹理若随窗口尺寸变化,就需要在调整大小时重建,并更新包含其句柄的常量。只要附件格式与采样数仍然匹配,管线就可以复用。{link}展示了如何调整纹理尺寸并保留管线。" -concepts.platforms.lifecycle.guidance.link: "旋转立方体渲染器" -concepts.platforms.lifecycle.title: "交换链尺寸与生命周期" -concepts.platforms.ownership.description: "应用程序拥有所设置的上下文及其渲染资源,控件拥有呈现资源。视图的 {graphicsContext} 变化后,调度程序会为新上下文重建控件资源。应用程序也须为该上下文重建自己的管线、缓冲区和纹理。" -concepts.platforms.ownership.details: "替换渲染资源前,先停止视图的帧活动,并等待使用这些资源的 GPU 工作完成,再释放旧资源或上下文。移除视图后,所设置的上下文仍由应用程序负责释放。" -concepts.platforms.ownership.guidance: "共享的 {frameSchedulerCs} 通过视图的 UI 调度器运行帧处理程序。处理程序应集中于场景数据更新和命令录制,其中耗时的 CPU 工作也会延迟界面响应。" -concepts.platforms.ownership.title: "应用程序与控件的责任" -concepts.platforms.surface.description: "{link}使用 Silk.NET 创建窗口并处理事件。Zenith.NET 通过 {surface} 描述获取原生窗口句柄与尺寸,再据此创建 {swapChain}。操作系统窗口仍由应用程序负责管理。" -concepts.platforms.surface.description.link: "三角形教程" -concepts.platforms.surface.details: "原生句柄必须与所选后端匹配:" -concepts.platforms.surface.guidance: "{appCs} 中的示例宿主支持 Windows、macOS 和 X11。Linux 窗口提供 Xlib 句柄,因此在 Wayland 会话中需要 XWayland。原生 Wayland 应用程序则通过 {surfaceWayland} 提供显示与表面句柄。" -concepts.platforms.surface.table.android.backend: "Android 上的 Vulkan。" -concepts.platforms.surface.table.apple.backend: "Apple 平台上的 Metal。" -concepts.platforms.surface.table.headings.backend: "后端与平台" -concepts.platforms.surface.table.headings.factory: "呈现目标工厂方法" -concepts.platforms.surface.table.headings.handles: "宿主提供的句柄" -concepts.platforms.surface.table.wayland.backend: "带有原生 Wayland 宿主的 Vulkan。" -concepts.platforms.surface.table.wayland.handles: "Wayland 显示与表面" -concepts.platforms.surface.table.win32.backend: "Windows 上的 DirectX 12 或 Vulkan。" -concepts.platforms.surface.table.xlib.backend: "Linux 上带有 X11 或 XWayland 的 Vulkan。" -concepts.platforms.surface.table.xlib.handles: "X11 显示与窗口" -concepts.platforms.surface.title: "原生呈现目标" -concepts.platforms.title: "平台集成" -concepts.resources.allocation.context: "放置在堆中的资源在整个生命周期内都依赖堆的存储。最后一次 GPU 使用完成后,应先释放资源,再释放堆。" -concepts.resources.allocation.description: "应用程序需要自行管理内存分配时,可以使用 {heap}。堆为资源提供存储,应用程序选择明确的字节偏移量来放置资源,并记录各区域的占用情况。" -concepts.resources.allocation.details: "对每个资源,使用创建时所需的缓冲区或纹理描述调用 {contextGetSizeAndAlignment}。按返回的大小预留空间,起始偏移量须为返回对齐值的整数倍,且整个区域位于堆内,不与其他仍有效的分配重叠。纹理可能包含后端特有的填充,因此不能仅根据像素数量和每像素字节数计算分配大小。" -concepts.resources.allocation.guidance: "放置在堆中的缓冲区必须使用与堆相同的驻留设置。纹理存储使用 GPU 专用堆。" -concepts.resources.allocation.title: "堆分配" -concepts.resources.bufferUsages.table.constant.role: "通过常量缓冲区绑定读取的着色器参数。" -concepts.resources.bufferUsages.table.headings.role: "作用" -concepts.resources.bufferUsages.table.headings.usage: "用途" -concepts.resources.bufferUsages.table.index.role: "索引绘制所使用的索引。" -concepts.resources.bufferUsages.table.indirect.role: "间接绘制或分派命令读取的参数。" -concepts.resources.bufferUsages.table.none.role: "未声明任何缓冲区用途标志。" -concepts.resources.bufferUsages.table.storageReadOnly.role: "通过只读着色器绑定访问的缓冲区数据。" -concepts.resources.bufferUsages.table.storageReadWrite.role: "通过读写着色器绑定访问的缓冲区数据。" -concepts.resources.bufferUsages.table.transferDst.role: "GPU 复制操作的目标存储。" -concepts.resources.bufferUsages.table.transferSrc.role: "GPU 复制操作的源数据。" -concepts.resources.bufferUsages.table.vertex.role: "供绘制命令读取的顶点属性。" -concepts.resources.bufferUsages.title: "缓冲区用途" -concepts.resources.description: "资源描述规定应用程序如何使用其存储。例如,一张纹理若要作为渲染目标、供着色器采样,并将内容复制回 CPU,就需要声明这三种操作对应的用途。内存放置决定 CPU 的访问方式,同步与生命周期管理则决定何时可以访问数据或释放存储。" -concepts.resources.memory.context: "对于 CPU 可访问的缓冲区,{map} 提供 CPU 读写数据所用的地址。映射和 {unmap} 都不会等待 GPU 工作。CPU 读取 GPU 写入的结果前,应用程序须先等待写入完成;修改同一块内存前,也须等待 GPU 对这些字节的访问结束。" -concepts.resources.memory.description: "{bufferDesc} 的 {residency} 字段指定了 CPU 对分配内存的预期访问方式:" -concepts.resources.memory.details: "驻留设置表达 CPU 的访问需求,即使 CPU 与 GPU 共享物理内存也同样适用。三角形教程使用 {cpuWriteOnly} 直接初始化小型顶点缓冲区。对于较大的静态几何数据,上传到 GPU 专用存储可能更合适。" -concepts.resources.memory.guidance: "通过上下文直接创建的纹理使用 GPU 存储,因此 {textureDesc} 没有驻留字段。应用程序通过上传和回读,在纹理与 CPU 内存之间交换数据。" -concepts.resources.memory.table.cpuReadOnly.cPUAccess: "只读" -concepts.resources.memory.table.cpuReadOnly.typicalRole: "GPU 生成的回读数据" -concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "只写" -concepts.resources.memory.table.cpuWriteOnly.typicalRole: "CPU 提供或更新的数据" -concepts.resources.memory.table.gpuOnly.cPUAccess: "无" -concepts.resources.memory.table.gpuOnly.typicalRole: "静态几何体和 GPU 工作数据" -concepts.resources.memory.table.headings.cPUAccess: "预期 CPU 访问" -concepts.resources.memory.table.headings.residency: "内存驻留" -concepts.resources.memory.table.headings.typicalRole: "典型用途" -concepts.resources.memory.title: "CPU 访问与内存放置" -concepts.resources.textureUsages.description: "传输标志声明资源在 GPU 复制中用作源还是目标。CPU 能否直接访问这块存储,则由内存放置方式决定。" -concepts.resources.textureUsages.details: "用途标志声明纹理可以承担的作用。在这些作用之间切换时,需要相应的{link};所选设备也必须支持以该纹理格式执行所声明的操作。" -concepts.resources.textureUsages.details.link: "布局与同步" -concepts.resources.textureUsages.table.colorAttachment.role: "渲染通道中的颜色附件。" -concepts.resources.textureUsages.table.depthStencilAttachment.role: "渲染通道中的深度/模板附件。" -concepts.resources.textureUsages.table.headings.role: "作用" -concepts.resources.textureUsages.table.headings.usage: "用途" -concepts.resources.textureUsages.table.none.role: "未声明任何纹理用途标志。" -concepts.resources.textureUsages.table.sampled.role: "通过采样纹理绑定读取的纹理数据。" -concepts.resources.textureUsages.table.storage.role: "通过存储纹理绑定供着色器读取或写入的纹理数据。" -concepts.resources.textureUsages.table.transferDst.role: "GPU 复制操作的目标图像存储。" -concepts.resources.textureUsages.table.transferSrc.role: "GPU 复制操作的源图像数据。" -concepts.resources.textureUsages.title: "纹理用途" -concepts.resources.title: "资源管理" -concepts.resources.transfers.context: "回读先将 GPU 数据复制到内部回读存储。库回收已完成的命令缓冲区时,再将数据复制到指定的 CPU 目标。对本次回读提交的完成值调用 {wait},可以完成这两个步骤。在调用返回前,目标内存须保持已分配状态,托管内存须保持固定。" -concepts.resources.transfers.description: "上传将 CPU 数据复制到 GPU 资源,回读则将资源数据复制到 CPU 内存。缓冲区和纹理上的这些方法会在传输完成后返回:" -concepts.resources.transfers.details: "调用这些方法前,先处理与其他队列访问之间的冲突。方法内部的等待只覆盖其自身的传输,不会建立与其他队列的依赖。直接通过映射内存复制时,则完全由调用方负责等待存在冲突的 GPU 访问。" -concepts.resources.transfers.guidance: "要将传输与其他 GPU 工作一同提交,可通过 {commandBufferUpload} 或 {commandBufferDownload} 录制。上传源与回读目标的内存生命周期要求不同:" -concepts.resources.transfers.item: "上传调用期间,库会将源数据复制到内部的临时上传存储,即暂存内存。GPU 随后从这块存储读取,因此应用程序的源指针只需保持有效到调用返回。" -concepts.resources.transfers.notes: "纹理传输中的行步幅是 CPU 数据相邻两行之间的字节距离;切片步幅则是相邻深度切片之间的字节距离。传输操作根据这些值,在 CPU 数据与纹理的 GPU 存储之间复制内容。GPU 完成与数据送达回读目标为何是两个步骤,见{link}。" -concepts.resources.transfers.notes.link: "同步" -concepts.resources.transfers.table.bufferDownload.transfer: "对于 {cpuReadOnly},直接从映射内存复制;否则向传输队列提交回读,并等待完成。" -concepts.resources.transfers.table.bufferUpload.transfer: "对于 {cpuWriteOnly},直接复制到映射内存;否则向传输队列提交上传,并等待完成。" -concepts.resources.transfers.table.headings.method: "方法" -concepts.resources.transfers.table.headings.transfer: "传输行为" -concepts.resources.transfers.table.textureTransfers.method: "{textureUpload} / {textureDownload}" -concepts.resources.transfers.table.textureTransfers.transfer: "将复制及其纹理转换提交到图形队列,并等待完成。操作结束后,所选子资源处于指定的最终布局。" -concepts.resources.transfers.title: "立即传输与命令录制" -concepts.resources.usages.description: "{bufferUsages} 和 {textureUsages} 是用于声明资源用途的标志枚举,分别设置在 {bufferDescUsages} 和 {textureDescUsages} 中。资源需要承担多种用途时,可通过 {value} 组合相应成员。" -concepts.resources.usages.title: "资源用途" -concepts.resources.views.description: "{bufferView} 描述缓冲区的一块区域及其数据解释方式。{textureView} 选择子资源范围,以及兼容的纹理类型和格式。二者都引用已有存储,并遵循创建该存储时声明的用途。视图范围用于描述访问范围,各后端并不因此提供一致的着色器边界检查。" -concepts.resources.views.details: "资源自身的句柄提供默认视图。需要其他区域或兼容的解释方式时,再创建独立视图。视图及其底层资源都必须保留到 GPU 使用结束;仅持有资源句柄不能使任一对象保持存活。替换其中任一对象时,还须更新包含旧{link}的常量。" -concepts.resources.views.details.link: "资源句柄" -concepts.resources.views.title: "视图与底层资源" -concepts.shaders.binding.context: "计算示例将 {inputTextureSampledHandle} 写入 {input},将 {outputTextureStorageHandle} 写入 {output}。在 Slang 中,{descriptorHandle} 的类型参数规定了着色器访问资源的方式:" -concepts.shaders.binding.description: "{setConstantBuffer} 选择已有缓冲区及字节偏移量,当前管线从该位置读取常量。着色器使用这些参数前,先将数据上传到相应存储。如果此前提交的 GPU 工作仍在读取同一批字节,须等待该工作完成后再更新。" -concepts.shaders.binding.details: "准备好命令缓冲区、计算管线、已填入数据的常量缓冲区和线程组数量后,按以下顺序录制分派。常量缓冲区的绑定作用于当前管线,因此必须先选择管线:" -concepts.shaders.binding.guidance: "这里,{commandBuffer} 使用 {computePipeline} 及 {constantBuffer} 中的参数录制分派。缓冲区需要声明 {bufferUsagesConstant} 用途,偏移量 0 选择其起始位置。如果多条常量记录共用缓冲区,每条记录的起始偏移量还须满足后端绑定的对齐要求,这与记录内部的字段布局是两项独立要求。" -concepts.shaders.binding.notes: "{resourceHandle} 包含两个 32 位字段,含义由后端解释,其值仅在创建资源的上下文中有效。" -concepts.shaders.binding.reference: "保留资源及用于获取句柄的视图,直到着色器完成最后一次访问。替换纹理或视图后,应更新仍含旧句柄的常量。相关所有权规则见{link}。" -concepts.shaders.binding.reference.link: "资源管理" -concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: "读取着色器类型 {t} 的结构化元素" -concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: "读写着色器类型 {t} 的结构化元素" -concepts.shaders.binding.table.headings.access: "预期访问" -concepts.shaders.binding.table.headings.cHandle: "C# 句柄" -concepts.shaders.binding.table.headings.slangFieldType: "Slang 字段类型" -concepts.shaders.binding.table.samplerHandle.access: "纹理采样状态" -concepts.shaders.binding.table.textureSampledHandle.access: "纹理读取" -concepts.shaders.binding.table.textureStorageHandle.access: "存储纹理的读写" -concepts.shaders.binding.title: "常量缓冲区与资源句柄" -concepts.shaders.compilation.description: "{zenithCompiler} 将指定的 Slang 入口点编译为 {shaderDesc}。上下文的 {graphicsApi} 决定目标格式:DirectX 12 使用 DXIL,Metal 使用 Metal 库,Vulkan 使用 SPIR-V。" -concepts.shaders.compilation.details: "创建名为 {context} 的图形上下文后,可以编译已复制到可执行文件所在目录的三角形着色器:" -concepts.shaders.compilation.guidance: "入口点名称 {vSMain} 必须与着色器文件中的函数声明一致。在初始化阶段编译着色器并创建管线,渲染期间复用管线。管线创建完成后即可释放着色器对象,具体见{link}。" -concepts.shaders.compilation.guidance.link: "第一个三角形" -concepts.shaders.compilation.title: "着色器编译" -concepts.shaders.description: "C# 与 Slang 声明必须约定一致的数据位置和访问方式。顶点输入布局描述顶点属性,着色器缓冲区声明描述参数与数组,资源句柄则标识着色器使用的资源。" -concepts.shaders.dispatch.description: "{dispatch} 指定执行多少个线程组。计算示例声明 {numthreads},每组因此包含 16 × 16 个线程。将图像的宽和高分别除以 16 并向上取整,即可覆盖整张图像:17 × 19 的图像需要 2 × 2 组。着色器检查每个线程的坐标,并跳过位于图像范围以外的线程。" -concepts.shaders.dispatch.details: "{shaderDescThreadGroupSize} 提供声明的组大小,可用于计算传给 {dispatch} 的线程组数量。完整计算过程见 {computeShaderRendererCs}。分派完成后,访问输出图像时还须满足{link}中说明的要求。" -concepts.shaders.dispatch.details.link: "同步" -concepts.shaders.dispatch.title: "线程组" -concepts.shaders.layout.context: "{link}通过图像尺寸与两个纹理句柄展示了这种排列。各字段的起始位置由显式偏移量指定。以下声明使用 {systemRuntimeInteropServices} 和 {zenithNET} 命名空间:" -concepts.shaders.layout.context.link: "计算示例的 C# 常量" -concepts.shaders.layout.description: "对于顶点输入,{inputLayout} 描述各属性的格式、偏移量和语义,以及相邻顶点之间的步幅。三角形先存放 {float3} 位置,再存放 {float4} 颜色:颜色的字节偏移量为 12,每个顶点占 28 字节。{inputLayoutAdd} 根据元素格式计算这一紧密排列的布局。如果 C# 结构体包含填充,就需要在偏移量和步幅中计入这些空间。" -concepts.shaders.layout.details: "常量缓冲区存放着色器参数,结构化缓冲区存放指定类型的元素数组。它们的布局由 Slang 声明决定,不使用 {inputLayout}。C# 字段偏移量、元素大小和填充必须与编译后的着色器布局一致。即使某个 C# 类型是非托管类型,可以直接按字节复制,其内存排列也未必符合着色器要求;例如,顶点中紧密排列的 {float3},在着色器缓冲区中可能需要不同的对齐方式。" -concepts.shaders.layout.guidance: "着色器参数除了普通数值,也可以包含资源句柄。句柄标识的是已有存储,因此将句柄复制到常量缓冲区并不会复制资源内容。" -concepts.shaders.layout.notes: "{computeShaderSlang} 中对应的声明为:" -concepts.shaders.layout.reference: "两个尺寸值占用前 8 字节,后面是两个各占 8 字节的句柄。C# 示例为整条记录预留 256 字节。其他记录的大小应根据各自字段以及所需的布局和对齐方式确定。" -concepts.shaders.layout.title: "数据布局" -concepts.shaders.matrices.description: "编译器采用行优先的矩阵存储方式,使同一行的元素连续排列。{link}在偏移量 0、64 和 128 处保存三个 {matrix4x4} 值,其{detail}按模型、视图和投影顺序执行 {mulVectorMatrix}。" -concepts.shaders.matrices.description.detail: "着色器" -concepts.shaders.matrices.description.link: "旋转立方体渲染器" -concepts.shaders.matrices.details: "存储顺序决定矩阵元素在内存中的排列,乘法顺序决定变换。C# 与 Slang 应采用相互匹配的约定。" -concepts.shaders.matrices.title: "矩阵约定" -concepts.shaders.title: "着色器数据与绑定" -concepts.synchronization.backends.description: "DirectX 12 和 Vulkan 将纹理转换记录为布局与访问状态的变化。在 Zenith.NET 的 Metal 后端中,{transition} 没有对应的 GPU 操作。Metal 后端将命令组织为渲染与计算编码器,并在编码器结束时插入可见性屏障。同一编码器内存在依赖的操作,例如连续的计算分派,通过显式调用 {barrier} 协调。" -concepts.synchronization.backends.details: "{link}开始图形渲染通道时,会结束计算编码器,使计算输出对后续图形工作可见。连续两次计算分派仍位于同一编码器内,即使中间录制了纹理转换,也需要屏障来处理依赖。因此,可跨后端使用的命令序列既要考虑纹理布局,也要处理访问之间的依赖。" -concepts.synchronization.backends.details.link: "计算示例" -concepts.synchronization.backends.title: "后端行为" -concepts.synchronization.barriers.context: "选择包含相关访问、且受到当前队列支持的阶段。{barrierStagesAll} 涵盖所有受支持的阶段;若依赖只涉及其中一部分,可选择更小的范围。" -concepts.synchronization.barriers.description: "假设同一个命令缓冲区内有两次计算分派,第一次写入模拟数据,第二次读取这些数据。在两次分派之间设置屏障,让第二次分派读到已经完成的写入结果。对于存储缓冲区,这样即可安排访问顺序,无须进行纹理布局转换:" -concepts.synchronization.barriers.details: "第一个参数指定产生数据的阶段,第二个参数指定使用数据的阶段。二者共同描述两次分派之间所需的执行顺序和内存可见性。" -concepts.synchronization.barriers.guidance: "{link}在模拟步骤之间采用这一方式。每道屏障都位于产生数据的分派之后、使用数据的分派之前。" -concepts.synchronization.barriers.guidance.link: "FluidTank 模拟" -concepts.synchronization.barriers.title: "管线屏障" -concepts.synchronization.dependencies.description: "逐个资源确认哪些访问涉及同一份数据。只要其中存在写入,就必须维持所需的先后顺序。两次读取本身没有冲突,但仍需满足纹理布局和呈现要求。CPU 更新数据或释放资源前,也须等待 GPU 完成对相应存储的使用。" -concepts.synchronization.dependencies.details: "应根据操作执行的位置选择机制:" -concepts.synchronization.dependencies.guidance: "一项工作可能同时需要多种同步机制。例如,纹理由另一队列生成时,除了提交依赖,还需为下一次使用设置正确的布局。这两项操作本身都不需要阻塞 CPU;只有 CPU 要访问或释放相关数据时,才需要在 CPU 端等待。" -concepts.synchronization.dependencies.table.cpuAccess.mechanism: "对相关的完成值调用 {wait}。" -concepts.synchronization.dependencies.table.cpuAccess.situation: "CPU 访问或资源释放需要等待 GPU 完成" -concepts.synchronization.dependencies.table.crossQueue.mechanism: "将生产者的 {timelineValue} 传给消费者的 {submit}。" -concepts.synchronization.dependencies.table.crossQueue.situation: "一个队列使用另一个队列生成的数据" -concepts.synchronization.dependencies.table.headings.mechanism: "机制" -concepts.synchronization.dependencies.table.headings.situation: "情况" -concepts.synchronization.dependencies.table.layoutChange.mechanism: "调用 {commandBufferTransition},指定先前布局与目标布局。" -concepts.synchronization.dependencies.table.layoutChange.situation: "纹理子资源更改其使用方式" -concepts.synchronization.dependencies.table.pipelineStages.mechanism: "调用 {commandBufferBarrier},指定产生数据和使用数据的阶段。" -concepts.synchronization.dependencies.table.pipelineStages.situation: "命令流中存在依赖关系的 GPU 阶段" -concepts.synchronization.dependencies.title: "访问依赖" -concepts.synchronization.description: "同步确定多个操作访问共享数据的顺序,并确保后续操作能够读到所需结果。在写后读依赖中,写入方称为生产者,读取方称为消费者。屏障与纹理转换协调 GPU 访问;时间线连接不同提交,并让 CPU 等待 GPU 工作完成。" -concepts.synchronization.layouts.context: "现有内容可以丢弃时,可将先前布局设为 {undefined},例如新建图像或即将完整清除的附件。若要保留内容以供加载、采样或累积,则应使用此前访问时的布局。" -concepts.synchronization.layouts.description: "纹理的用途标志声明允许的作用。{textureLayout} 描述命令序列中某一时刻对子资源的访问方式,子资源由 mip 级别和数组层确定。访问方式发生变化时,需要录制转换。例如,计算示例在 {storage} 布局中写入输出纹理,再为图形通道中的采样做准备:" -concepts.synchronization.layouts.details: "这里的 {outputTexture} 已声明 {sampledStorage} 用途,所选子资源处于 {storage} 布局。{default} 选择 mip 级别 0 和数组层 0,其他级别和层不受这次转换影响。" -concepts.synchronization.layouts.guidance: "调用 {transition} 时,提供子资源上一次使用的布局。应用程序在录制命令,以及在渲染阶段之间传递纹理时,负责跟踪这个状态。" -concepts.synchronization.layouts.title: "纹理布局" -concepts.synchronization.readback.description: "{isCompleted} 报告 GPU 的完成状态。通过命令录制的回读还需要一个步骤:将结果从内部回读存储复制到应用程序的目标内存。" -concepts.synchronization.readback.details: "{commandBufferDownload} 录制向内部回读存储复制数据的 GPU 命令。提交完成后,库在回收命令缓冲区时执行最后的 CPU 复制。对本次回读提交的完成值调用 {wait},会等待 GPU 完成,并处理该队列已完成的缓冲区,从而完成这两个步骤。调用返回前,目标内存须保持已分配状态,托管内存须保持固定。" -concepts.synchronization.readback.guidance: "仅轮询 {isCompleted} 不会执行最后的 CPU 复制;等待其他队列,也不会回收回读队列中已完成的缓冲区。上传和回读在何时使用直接内存访问或暂存存储,见{link}。" -concepts.synchronization.readback.guidance.link: "资源管理" -concepts.synchronization.readback.title: "回读完成" -concepts.synchronization.reuse.description: "三角形教程在每帧完成后才复用数据。若要让帧重叠执行,应为每个尚未完成的帧准备独立的可变存储,并跟踪何时可以再次使用。修改数据前,须等待 GPU 完成对相关字节的访问;释放资源前,则须等待它的所有使用结束。" -concepts.synchronization.reuse.details: "调整大小与关闭程序遵循相同的顺序:先停止新的资源访问,等待已有访问结束,再替换或释放资源。调用 {swapChainResize} 或释放资源、上下文前,须先完成上述等待。三角形教程已经逐帧等待,因此可以在回调之间调整大小。" -concepts.synchronization.reuse.guidance: "{swapChainPresent} 在呈现后向图形队列发出信号并等待。因此,即使去掉显式的提交等待,三角形教程仍会在呈现时等待。独立提交到其他队列的工作,则需要单独跟踪其完成状态。" -concepts.synchronization.reuse.title: "资源复用" -concepts.synchronization.timelines.context: "CPU 若要在消费者完成后读取结果、覆盖共享数据或释放资源,须先等待这次提交完成:" -concepts.synchronization.timelines.description: "时间线用递增值标识队列进度。{submit} 返回的 {timelineValue} 同时包含时间线和本次提交的值。不同时间线上的 {value} 数值不能直接比较。" -concepts.synchronization.timelines.details: "设 {producer} 和 {consumer} 是同一上下文中两个队列上已录制的命令缓冲区,后者使用前者写入的数据。提交时传入这项依赖:" -concepts.synchronization.timelines.guidance: "消费者所在的队列会先等待传入的完成值,再执行命令。CPU 无需调用 {producedWait},可以继续处理其他工作。共享资源须保留到 {consumed} 完成,同时仍需录制消费者访问所要求的纹理转换。" -concepts.synchronization.timelines.notes: "{queueTimelineSignal} 返回的值同样可以通过 {wait} 等待,也可以作为另一个队列的依赖。{signal} 将完成点排在此前已提交的工作之后,GPU 完成这些工作后便会到达该点。" -concepts.synchronization.timelines.title: "时间线与队列依赖" -concepts.synchronization.title: "同步" -home.actions.reference: "浏览 API" -home.actions.tutorial: "从三角形开始" -home.entries.description: "教程、示例与 API 参考" -home.entries.label: "文档分类" -home.entries.reference.action: "探索 API" -home.entries.reference.category: "参考" -home.entries.reference.description: "查阅 API 类型、成员与声明" -home.entries.reference.title: "API 参考" -home.entries.samples.action: "浏览示例" -home.entries.samples.category: "示例" -home.entries.samples.description: "图形与计算技术的可运行示例" -home.entries.samples.title: "示例" -home.entries.title: "文档" -home.entries.tutorial.action: "开始教程" -home.entries.tutorial.category: "教程" -home.entries.tutorial.description: "从空项目开始,绘制第一个三角形" -home.entries.tutorial.title: "第一个三角形" -home.introduction.accent: "跨平台图形开发" -home.introduction.description: "Zenith.NET 提供统一的图形与计算 API,支持 DirectX、Metal 和 Vulkan" -home.introduction.title: "面向 .NET 的{lineBreak}{accent}" -home.meta.description: "使用 Zenith.NET 开发跨平台图形与计算应用,通过统一 API 使用 DirectX、Metal 和 Vulkan" -home.scene.description: "可交互的旋转几何体。拖动或使用方向键调整视角。" -home.scene.label: "几何体显示" -home.scene.surface: "表面" -home.scene.wireframe: "线框" -home.title: "适用于 .NET 的现代 RHI" -learning.concepts.description: "选择资源用途、描述着色器数据与协调 GPU 执行" -learning.concepts.execution.description: "命令录制、提交与资源生命周期" -learning.concepts.platforms.description: "原生呈现与 UI 渲染控件" -learning.concepts.resources.description: "资源用途、内存放置与视图" -learning.concepts.shaders.description: "C# 与 Slang 的数据布局和绑定约定" -learning.concepts.synchronization.description: "依赖关系、可见性与完成状态" -learning.concepts.title: "核心概念" -learning.description: "第一次使用 Zenith.NET,可以从三角形教程开始。完成后,按需要查阅资源管理、着色器数据和同步等概念,或通过示例了解具体图形技术的实现。" -learning.entries.samples.action: "浏览示例" -learning.entries.samples.description: "几何体、计算、光线查询与网格着色的 C# 和 Slang 实现" -learning.entries.tutorial.action: "打开教程" -learning.entries.tutorial.description: "创建窗口并渲染三角形的控制台应用程序" -learning.meta.description: "Zenith.NET 编程模型的入门教程与概念说明" -learning.title: "学习" -reference.description: "资源、命令与平台集成的参考文档" -reference.entries.commands.description: "图形、计算与传输命令" -reference.entries.commands.label: "录制命令" -reference.entries.context.description: "为所选后端创建 GPU 资源" -reference.entries.context.label: "从这里开始" -reference.meta.description: "Zenith.NET 的命名空间、类型与成员" -reference.navigation.core: "核心 API 参考" -reference.title: "API 参考" -samples.computeShader.description: "示例加载 {assetsTexturesShokoPng},通过一次计算分派将图像转换为灰度,再显示输出纹理。转换只执行一次,后续帧显示相同结果。渲染器展示了采样纹理与可写纹理的绑定、向上取整线程组数量以覆盖整张图像的计算方式,以及着色器中的图像边界检查。" -samples.computeShader.details: "{computeShaderRendererCs} · {computeShaderSlang}" -samples.computeShader.title: "计算着色器" -samples.cube.description: "旋转立方体加入索引绘制、常量缓冲区中的模型、视图和投影矩阵,以及深度测试。窗口大小变化时,会重建 {d32FloatS8UInt} 深度/模板纹理。" -samples.cube.details: "{spinningCubeRendererCs} · {spinningCubeSlang}" -samples.cube.title: "旋转立方体" -samples.description: "每个示例均由 C# 渲染器与 Slang 着色器组成,集中说明一项技术。完整的应用程序设置与渲染顺序见{link}。" -samples.description.link: "第一个三角形" -samples.execution.description: "运行 {link} 项目,并从控制台菜单选择示例。" -samples.execution.description.link: "ZenithTutorials" -samples.execution.title: "运行示例" -samples.host.description: "{appCs} 初始化上下文、窗口和交换链。每帧获取命令缓冲区,调用所选渲染器,提交命令并呈现结果。{iRendererCs} 规定渲染器的更新、渲染、调整大小和释放操作。" -samples.host.details: "计算与光线追踪渲染器生成离屏纹理。{texturePresenterCs} 和 {presentTextureSlang} 将这些纹理绘制到当前输出纹理,随后由共享宿主提交命令并呈现这一帧。" -samples.host.title: "宿主与呈现" -samples.indirectDrawing.description: "间接绘制通过索引绘制参数缓冲区和保存各实例数据的结构化缓冲区,绘制多个立方体。CPU 提供绘制参数并更新变换。" -samples.indirectDrawing.details: "{indirectDrawingRendererCs} · {indirectDrawingSlang}" -samples.indirectDrawing.title: "间接绘制" -samples.meshShading.description: "任务着色器剔除球体实例,将保留的索引传给负责生成几何体的网格着色器。创建管线前,渲染器检查 {contextCapabilitiesMeshShadingSupported}。" -samples.meshShading.details: "{meshShadingRendererCs} · {meshShadingSlang}" -samples.meshShading.title: "网格着色" -samples.rayTracing.description: "该示例为地面和程序化球体构建底层与顶层加速结构,再在计算着色器中执行内联光线查询。初始化前检查 {contextCapabilitiesRayTracingSupported}。" -samples.rayTracing.details: "{rayTracingRendererCs} · {rayTracingSlang}" -samples.rayTracing.title: "光线追踪" -samples.title: "示例" -samples.triangle.description: "三角形示例将顶点缓冲区与对应的输入布局关联,通过图形管线绘制三个顶点。" -samples.triangle.details: "{helloTriangleRendererCs} · {helloTriangleSlang} · {link}" -samples.triangle.details.link: "完整教程" -samples.triangle.title: "Hello Triangle" -samples.workloads.description: "主仓库的{link}包含规模较大的应用程序,这些项目直接引用库源码。" -samples.workloads.description.link: "Experiments 目录" -samples.workloads.details: "窗口实验项目采用相同的 Windows、macOS 和 Linux/X11 呈现路径。Avalonia、WinForms、WPF、WinUI/Uno 和 MAUI 控件的帧生命周期及实现代码见{link}。" -samples.workloads.details.link: "平台集成" -samples.workloads.table.cornellBox.example: "{link}" -samples.workloads.table.cornellBox.example.link: "CornellBox" -samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: "路径追踪、降噪、色调映射、分辨率放大和 ImGui 控件。需要光线追踪支持。" -samples.workloads.table.fluidTank.example: "{link}" -samples.workloads.table.fluidTank.example.link: "FluidTank" -samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: "计算流体模拟、模拟阶段之间的依赖,以及多通道表面渲染。" -samples.workloads.table.headings.example: "示例" -samples.workloads.table.headings.whatItDemonstratesAndRequires: "技术与运行要求" -samples.workloads.table.inkCanvas.example: "{link}" -samples.workloads.table.inkCanvas.example.link: "InkCanvas" -samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: "原生窗口中的 Skia 绘制与输入处理。需要对应目标平台的后端和 Skia 原生库。" -samples.workloads.table.platformDetection.example: "{link}" -samples.workloads.table.platformDetection.example.link: "PlatformDetection" -samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: "尝试为每个后端创建上下文,并报告设备能力。创建失败时显示为不支持,原因可能是设备、驱动程序或缺失的运行时依赖。" -samples.workloads.title: "综合应用" -tutorial.context.description: "{graphicsContext} 通过所选后端连接应用程序与 GPU,并提供创建渲染资源的方法。" -tutorial.context.details: "在{emphasis}插入上下文初始化代码:" -tutorial.context.details.emphasis: "using 指令之后、{iWindowWindow} 之前" -tutorial.context.guidance: "各分支为当前平台选择后端并请求启用验证。{validationMessage} 消息会输出到控制台。" -tutorial.context.imports: "在 {programCs} 顶部添加以下 using 指令:" -tutorial.context.title: "图形上下文" -tutorial.description: "本教程从一个空的 .NET 控制台项目开始,逐步完成窗口创建,并在窗口中绘制一个彩色三角形。" -tutorial.details: "本教程有三个检查点:空窗口、单色背景和彩色三角形。每完成一个检查点,先运行程序确认结果,再继续添加下一部分。" -tutorial.draw.context: "{draw} 的参数如下:" -tutorial.draw.description: "在 {windowRender} 回调中,用以下命令替换 {addTheTriangleDrawCommandsHereLater},位置保持在 {beginRenderPass} 与 {endRenderPass} 之间:" -tutorial.draw.details: "{setPipeline} 选择着色器和渲染状态。后端按管线的输入布局解释顶点绑定,因此这一步必须先于顶点绑定。" -tutorial.draw.guidance: "{setVertexBufferVertexBuffer} 从缓冲区的字节偏移 0 开始,将已上传的顶点数据绑定到输入槽 0,对应 {inputLayouts} 中唯一的条目。" -tutorial.draw.notes: "这些调用录制绘制命令。已有的 {submitWait} 提交命令并等待 GPU 完成,随后 {present} 请求显示完成的图像。保留通道开始时的清除操作,让三角形以外的区域也有确定的背景色。" -tutorial.draw.table.firstInstance.meaning: "实例编号从零开始。" -tutorial.draw.table.firstVertex.meaning: "从缓冲区中的第一个顶点开始。" -tutorial.draw.table.headings.argument: "参数" -tutorial.draw.table.headings.description: "值" -tutorial.draw.table.headings.meaning: "含义" -tutorial.draw.table.instanceCount.meaning: "绘制一个三角形实例。" -tutorial.draw.table.vertexCount.meaning: "读取三个顶点。" -tutorial.draw.title: "绘制命令" -tutorial.execution.description: "构建并运行 {firstTriangle} 项目。" -tutorial.execution.details: "窗口中应出现一个三角形:上方为红色,右下为绿色,左下为蓝色,背景为深色。三个顶点的颜色经过插值,在三角形内部形成平滑过渡。" -tutorial.execution.guidance: "调整窗口大小时,图像的像素尺寸会改变,顶点坐标保持不变。视口将这些坐标映射到新的宽度和高度,因此改变窗口的宽高比会拉伸三角形。" -tutorial.execution.title: "运行应用程序" -tutorial.frame.commands.context: "{endRenderPass} 之后的第二次转换使输出纹理进入可呈现的布局。{submit} 结束录制并提交命令缓冲区,{wait} 阻塞至本次提交完成,随后 {present} 请求显示渲染结果。" -tutorial.frame.commands.description: "渲染通道将写入同一组附件的绘制操作组织在一起。本通道用交换链的输出纹理接收颜色输出。{colorAttachmentClear} 指定以 RGBA 颜色初始化该附件,并在通道结束时保留内容。{beginRenderPass} 按这些设置录制通道的开始命令。" -tutorial.frame.commands.details: "集合中有一个颜色附件。{null} 表示本通道不使用深度/模板附件。" -tutorial.frame.commands.guidance: "{beginRenderPass} 默认让视口和裁剪区域覆盖整个附件。视口把渲染坐标映射为像素位置,裁剪区域则限制可以写入的范围。" -tutorial.frame.commands.title: "清除、提交与呈现" -tutorial.frame.description: "先把窗口填成一种背景色,这个操作称为清除。背景正常显示后,就说明呈现目标、命令提交和呈现流程已经接通,可以继续加入三角形的顶点和着色器。" -tutorial.frame.details: "Silk.NET 在需要绘制一帧时调用渲染回调。本示例不使用回调传入的时间间隔,因此将该参数命名为 {value}。在{emphasis}注册回调:" -tutorial.frame.details.emphasis: "{windowRun} 之前" -tutorial.frame.target.description: "{graphicsQueueCommandBuffer} 返回可直接录制的命令缓冲区。录制描述 GPU 工作,提交后才开始执行。" -tutorial.frame.target.details: "纹理布局描述操作对纹理的访问方式。第一次 {transition} 将输出纹理准备为颜色附件。这里的 {default} 选择 mip 级别 0 和数组层 0,也就是输出纹理的基础图像。由于这个通道会清除整张图像,可以指定 {undefined},允许丢弃原有内容。" -tutorial.frame.target.guidance: "呈现后可能换用另一张图像,因此每一帧都要获取当前的输出纹理。" -tutorial.frame.target.title: "准备输出纹理" -tutorial.frame.title: "第一帧" -tutorial.geometry.data.description: "在{emphasis}添加顶点数组。后续资源初始化也放在该回调之前,顺序如下。" -tutorial.geometry.data.description.emphasis: "{windowRender} 之前" -tutorial.geometry.data.details: "每个条目构造一个 {vertex},内部的两个 {new} 表达式分别提供 {vector3} 位置和 {vector4} 颜色。三个位置对应上角、右下角和左下角。顶点着色器将 {w} 作为第四个位置坐标;w 为 1 时,x、y 也就是归一化设备坐标,-1 与 +1 对应图像边界,0 对应中心,与像素尺寸无关。" -tutorial.geometry.data.guidance: "每个颜色包含红、绿、蓝和 alpha 分量,alpha 设为 1。三个顶点的 z 坐标均为 0,位于同一平面。" -tutorial.geometry.data.title: "顶点位置与颜色" -tutorial.geometry.description: "三角形的每个顶点都有位置和颜色。GPU 根据三个位置确定三角形的形状,再对顶点颜色插值,得到内部各处的颜色。" -tutorial.geometry.format.description: "在{emphasis}追加顶点声明:" -tutorial.geometry.format.description.emphasis: "{programCs} 的末尾、清理语句之后" -tutorial.geometry.format.details: "{file} 将类型的使用范围限定在 {programCs} 内,{layoutKindSequential} 则保留字段的声明顺序。{position} 包含三个 32 位浮点数,字节偏移量为 0;{color} 包含四个,字节偏移量为 12。因此,每个顶点占 28 字节。稍后将通过输入布局描述这一排列,让 GPU 正确读取各字段。" -tutorial.geometry.format.imports: "在 {programCs} 顶部添加以下 using 指令,以使用向量类型和结构体布局特性:" -tutorial.geometry.format.title: "顶点表示" -tutorial.geometry.title: "顶点数据" -tutorial.geometry.upload.context: "{fixed} 防止垃圾回收器在地址使用期间移动数组。对于这个 CPU 可写缓冲区,{upload} 会映射内存、复制数据,并在返回前解除映射,因此只需在调用期间固定数组。顶点数据在初始化时上传一次即可;缓冲区则必须保留到渲染结束。" -tutorial.geometry.upload.description: "将顶点存入 {buffer},供 GPU 在绘制时读取。在顶点数组之后紧接着添加分配与上传代码:" -tutorial.geometry.upload.details: "分配大小为 {sizeofVertexVerticesLength},即三个 28 字节顶点,共 84 字节。{bufferUsagesVertex} 声明顶点输入用途,{cpuWriteOnly} 允许 CPU 直接初始化。描述中的步幅记录元素大小,随后定义的输入布局指定 GPU 如何读取各个顶点属性。" -tutorial.geometry.upload.guidance: "分配不会初始化缓冲区内容。{upload} 使用数据描述中的源指针和字节数,将数组复制到目标字节偏移量 0。" -tutorial.geometry.upload.imports: "在 {programCs} 顶部的 using 指令中添加 {bufferAlias},以区分 Zenith.NET 的缓冲区类型与 {systemBuffer}。" -tutorial.geometry.upload.notes: "在 {programCs} 末尾的清理代码中,紧接在 {swapChainDispose} 之前加入 {vertexBufferDispose}。较大静态几何体所需的 GPU 专用存储与上传方式见{link}。" -tutorial.geometry.upload.notes.link: "资源管理" -tutorial.geometry.upload.title: "缓冲区分配与上传" -tutorial.input.description: "GPU 需要知道位置、颜色等顶点属性存在哪里。输入布局指定每个属性的格式和字节偏移量,并用步幅表示从一个顶点到下一个顶点相隔多少字节。在创建着色器之后添加以下代码:" -tutorial.input.details: "{inputLayoutAdd} 将每个属性追加在前一个属性之后,并将其大小计入步幅。偏移量根据这里提供的格式计算,而非通过检查 C# 结构体获得。这两个字段对应的布局如下:" -tutorial.input.guidance: "{semanticIndex} 默认为 0,与着色器中的 {pOSITION0} 和 {cOLOR0} 对应。位置与颜色存放在同一个顶点缓冲区中,因此管线只需在槽 0 使用一个输入布局。如果 C# 结构体的字段顺序或填充发生变化,也要相应调整此布局。" -tutorial.input.table.headings.byteOffset: "字节偏移量" -tutorial.input.table.headings.cField: "C# 字段" -tutorial.input.table.headings.format: "格式" -tutorial.input.table.headings.shaderInput: "着色器输入" -tutorial.input.table.nextVertex.cField: "下一个顶点" -tutorial.input.table.nextVertex.format: "总步幅:28 字节" -tutorial.input.table.nextVertex.shaderInput: "下一个输入记录" -tutorial.input.table.vertexColor.format: "{float4}(16 字节)" -tutorial.input.table.vertexPosition.format: "{float3}(12 字节)" -tutorial.input.title: "顶点输入布局" -tutorial.lifecycle.description: "每帧依次执行以下操作:" -tutorial.lifecycle.details: "关闭窗口后,{run} 返回,程序继续执行清理代码。每一帧都已等待其提交完成,因此现在可以释放这些命令使用的资源。{windowRun} 之后完整的清理代码如下:" -tutorial.lifecycle.guidance: "先释放交换链,再销毁其原生窗口;先释放应用程序资源,再释放上下文。已提交的命令缓冲区由队列回收,输出纹理由交换链管理,二者都不需要单独调用 {dispose}。" -tutorial.lifecycle.title: "帧生命周期与清理" -tutorial.pipeline.behavior: "在输入布局之后创建管线:" -tutorial.pipeline.context: "{cullNone} 关闭面剔除,因此无论顶点在画面中呈顺时针还是逆时针排列,三角形都会被绘制。" -tutorial.pipeline.description: "{graphicsPipeline} 将顶点布局、两个着色器,以及图元组装和附件输出所需的设置组合在一起。" -tutorial.pipeline.details: "着色器负责处理顶点和片元。其余管线设置决定图元如何组装、是否剔除某个朝向的面,以及如何进行深度测试和颜色混合:" -tutorial.pipeline.guidance: "管线颜色格式必须匹配渲染通道附件,因此直接取自 {swapChainDescFormat}。{count1} 表示每像素一个采样点。" -tutorial.pipeline.item: "{triangleList} 将每组连续的三个顶点组装成一个三角形。" -tutorial.pipeline.notes: "{depthNone} 关闭深度测试和深度写入,与通道没有深度附件的配置一致。" -tutorial.pipeline.reference: "{opaque} 关闭混合,因此片元着色器输出直接替换三角形内部的背景色。" -tutorial.pipeline.title: "图形管线" -tutorial.pipeline.usage: "管线创建完成后即可释放着色器对象。渲染期间保留管线,在清理代码中将 {pipelineDispose} 放在 {vertexBufferDispose} 之前。" -tutorial.presentation.title: "图形上下文与呈现" -tutorial.project.context: "在项目构建设置中启用{emphasis}({allowUnsafeBlocks})。窗口辅助代码的原生调用和顶点上传需要不安全代码。" -tutorial.project.context.emphasis: "允许不安全代码" -tutorial.project.description: "创建名为 {firstTriangle} 的 C# 控制台项目,目标框架设为 .NET 10。" -tutorial.project.details: "为项目添加以下 NuGet 包:" -tutorial.project.guidance: "{zenithNET} 提供统一渲染 API,三个后端包提供各平台的实现。{zenithNETCompiler} 为所选后端编译稍后介绍的 Slang 着色器。Silk.NET 负责窗口创建与事件处理。" -tutorial.project.title: "项目设置" -tutorial.requirements.context: "{link}及其{detail}提供了本教程的参考实现。" -tutorial.requirements.context.detail: "共享宿主" -tutorial.requirements.context.link: "Hello Triangle 示例" -tutorial.requirements.description: "需要 {emphasis},并具备基础 C# 知识。应用程序以 {net10} 为目标框架。GPU 和驱动程序须支持所在平台选用的后端:" -tutorial.requirements.description.emphasis: ".NET 10 SDK" -tutorial.requirements.guidance: "Zenith.NET 渲染到应用程序提供的原生呈现目标。Silk.NET.Windowing 创建窗口并处理事件。macOS 使用由 {cAMetalLayerCs} 表示的 Metal 图层,窗口辅助代码负责将其连接到窗口。" -tutorial.requirements.table.headings.graphicsBackend: "图形后端" -tutorial.requirements.table.headings.platform: "平台" -tutorial.requirements.table.linux.graphicsBackend: "Vulkan 1.4" -tutorial.requirements.table.linux.platform: "Linux(X11 或 XWayland)" -tutorial.requirements.table.macOS.graphicsBackend: "Metal 4" -tutorial.requirements.table.macOS.platform: "macOS" -tutorial.requirements.table.windows.graphicsBackend: "DirectX 12" -tutorial.requirements.table.windows.platform: "Windows" -tutorial.requirements.title: "前置条件" -tutorial.resize.context: "再次构建并运行程序。调整窗口大小后,背景应继续填满整个窗口:每次开始新的渲染通道时,视口和裁剪区域都会按调整后的附件尺寸设置。保留渲染回调,后面将在这个通道内绘制三角形。" -tutorial.resize.description: "帧缓冲区尺寸变化时,交换链也要随之调整。在渲染回调之后、{windowRun} 之前注册 {framebufferResize} 回调:" -tutorial.resize.details: "这里监听的是以像素为单位的{link},而非窗口逻辑尺寸的变化。窗口最小化时,帧缓冲区的宽度或高度可能变为零;此时,尺寸变化回调保留现有交换链,不执行调整。渲染回调也会在任一尺寸为零时直接返回,直到帧缓冲区恢复有效尺寸后再继续绘制。" -tutorial.resize.details.link: "帧缓冲区大小变化" -tutorial.resize.guidance: "渲染回调会等待当前帧的提交完成,再调用 {present}。因此,尺寸变化回调替换交换链图像时,此前帧的工作已经结束。关于完成状态与资源生命周期的要求,详见{link}。" -tutorial.resize.guidance.link: "同步" -tutorial.resize.title: "窗口尺寸变化" -tutorial.shaders.compilation.context: "{appContextBaseDirectory} 让程序从输出目录加载已复制的着色器。即使从其他工作目录启动程序,查找文件的位置也不会改变。" -tutorial.shaders.compilation.description: "将 {triangleSlang} 的文件属性{emphasis}设为{detail},构建时便会将着色器复制到可执行文件所在目录。" -tutorial.shaders.compilation.description.detail: "如果较新则复制" -tutorial.shaders.compilation.description.emphasis: "复制到输出目录" -tutorial.shaders.compilation.details: "返回 {programCs},在顶点上传之后、渲染回调之前添加着色器初始化:" -tutorial.shaders.compilation.guidance: "{zenithCompiler} 为 {contextGraphicsApi} 指定的后端编译源码,{createShader} 再根据编译后的描述创建着色器对象。入口点名称 {vSMain} 和 {fSMain} 分别选中 Slang 文件中定义的两个函数。" -tutorial.shaders.compilation.title: "编译着色器" -tutorial.shaders.context: "{fSInput} 连接两个着色器阶段。顶点着色器将裁剪空间位置写入 {sVPOSITION},GPU 据此判断三角形的可见部分。{cOLOR0} 字段传递顶点颜色,颜色经过三角形内部的插值后到达片元着色器。两个阶段必须使用一致的颜色类型与语义。" -tutorial.shaders.description: "着色器是在 GPU 上运行的程序。顶点着色器确定每个顶点的位置,片元着色器则确定图像中被覆盖位置的颜色。我们将两个阶段写在同一个 Slang 文件中,并分别定义入口点,也就是各阶段开始执行的函数。" -tutorial.shaders.details: "创建 {triangleSlang},先定义输入与输出结构:" -tutorial.shaders.fragment.description: "在同一文件中追加片元入口点:" -tutorial.shaders.fragment.details: "光栅化确定三角形在图像中的覆盖范围,并在这些位置生成片元。每个片元的颜色由三个顶点的颜色插值得到。{fSMain} 返回这个颜色,{sVTARGET} 则将结果送到第一个颜色附件。" -tutorial.shaders.fragment.title: "片元着色" -tutorial.shaders.guidance: "{vSInput} 定义顶点着色器输入。{pOSITION0} 和 {cOLOR0} 按语义标识属性,C# 字段名称本身不建立这一映射。" -tutorial.shaders.title: "着色器阶段" -tutorial.shaders.vertex.description: "在 {triangleSlang} 中追加顶点入口点:" -tutorial.shaders.vertex.details: "GPU 为每个输入顶点调用这一入口点,补充齐次坐标 {w} 并传递颜色。顶点处理结束后,位置要除以 w。本例 w 为 1,x、y、z 保持不变,可直接解释为归一化设备坐标。" -tutorial.shaders.vertex.title: "顶点着色" -tutorial.surface.description: "在{emphasis}指定原生呈现目标:" -tutorial.surface.description.emphasis: "{windowCenter} 之后、{windowRun} 之前" -tutorial.surface.details: "帧缓冲区是窗口用于显示的像素图像。{surface} 描述原生呈现目标及其尺寸,{framebufferSize} 给出以像素为单位的大小。启用显示缩放时,这个大小可能与窗口的逻辑尺寸不同。" -tutorial.surface.guidance: "呈现目标提供后端所需的原生句柄:Windows 使用 Win32 窗口,Linux 使用 X11 显示与窗口,macOS 使用已连接的 Metal 图层。" -tutorial.surface.title: "原生呈现目标" -tutorial.swapChain.context: "交换链同时依赖上下文与窗口。将 {programCs} 末尾的 {windowDispose} 替换为以下释放顺序:" -tutorial.swapChain.description: "紧接呈现目标描述,创建交换链:" -tutorial.swapChain.details: "{swapChain} 管理窗口呈现的图像。{drawable} 以图像资源 {texture} 的形式提供当前图像。渲染后,{present} 请求显示该图像,并推进到下一个输出纹理。" -tutorial.swapChain.guidance: "{b8G8R8A8UNorm} 按蓝、绿、红和 alpha 顺序保存四个 8 位通道。{uNorm} 将整数 0–255 对应到 0–1。着色器仍输出逻辑 RGBA 值,格式只规定存储表示;管线通过 {swapChainDescFormat} 匹配附件。" -tutorial.swapChain.title: "交换链" -tutorial.title: "第一个三角形" -tutorial.troubleshooting.description: "结合控制台诊断与三个检查点定位失败阶段:" -tutorial.troubleshooting.details: "{link}与{detail}可用于核对顶点数据、输入布局和绘制操作。该示例将窗口与提交逻辑放入共享宿主,本教程则保留在 {programCs} 中。{context}进一步介绍索引绘制、变换与深度测试。" -tutorial.troubleshooting.details.context: "旋转立方体" -tutorial.troubleshooting.details.detail: "Slang 着色器" -tutorial.troubleshooting.details.link: "示例渲染器" -tutorial.troubleshooting.table.backend.check: "检查所选后端是否受设备和已安装的图形驱动程序支持。" -tutorial.troubleshooting.table.backend.symptom: "后端创建失败" -tutorial.troubleshooting.table.drawing.check: "检查上传大小、输入布局、管线选择以及渲染通道内绘制命令的位置。" -tutorial.troubleshooting.table.drawing.symptom: "背景出现但三角形未出现" -tutorial.troubleshooting.table.headings.check: "检查项" -tutorial.troubleshooting.table.headings.symptom: "现象" -tutorial.troubleshooting.table.input.check: "检查步幅是否为 28 字节,位置和颜色是否分别从偏移 0 和 12 字节开始。" -tutorial.troubleshooting.table.input.symptom: "顶点位置或颜色异常" -tutorial.troubleshooting.table.shaders.check: "检查复制的 {triangleSlang}、入口点拼写以及编译器报告的诊断信息。" -tutorial.troubleshooting.table.shaders.symptom: "背景色正常显示,但着色器加载失败" -tutorial.troubleshooting.table.window.check: "确认 .NET 项目能够构建成功,并且仅包含窗口的步骤可以在桌面会话中运行。在 Linux 上,检查 X11 或 XWayland 是否可用。" -tutorial.troubleshooting.table.window.symptom: "窗口未打开" -tutorial.troubleshooting.title: "问题排查" -tutorial.window.description: "将 {cocoaHelperCs} 下载到项目中。该辅助类负责将 Metal 图层连接到 macOS 窗口。" -tutorial.window.details: "将自动生成的 {programCs} 内容替换为以下代码。它使用顶级语句,按书写顺序执行,不需要显式编写 {main} 方法。后续各节会指出新代码应放在哪里:" -tutorial.window.guidance: "{graphicsAPINone} 将图形上下文的创建交给 Zenith.NET。{initialize} 创建原生窗口,使窗口系统的句柄可供使用;{center} 把窗口放到屏幕中央。{run} 持续处理事件,直到窗口关闭,随后执行 {dispose} 释放窗口。" -tutorial.window.notes: "构建并运行程序,检查窗口能否打开、移动、调整大小和关闭。此时还没有提交渲染命令,窗口内容尚未定义。关闭窗口后再继续。" -tutorial.window.title: "创建窗口" -ui.action.copy: "复制" -ui.action.navigate: "导航" -ui.action.open: "打开" -ui.action.source: "查看源码" -ui.api.browse: "浏览命名空间和类型。" -ui.api.clearTypeSearch: "清除类型搜索" -ui.api.findType: "查找类型" -ui.api.loadError: "无法加载类型。刷新此页面以重试。" -ui.api.loadingNamespaces: "正在加载命名空间…" -ui.api.loadingTypes: "正在加载类型…" -ui.api.matchingTypes: "匹配的类型" -ui.api.namespace: "命名空间" -ui.api.namespaces: "命名空间" -ui.api.noNamespaceTypes: "此命名空间中没有类型。" -ui.api.noTypes: "没有匹配的类型。" -ui.api.types: "类型" -ui.content.reference: "参考" -ui.content.source: "源代码" -ui.content.tutorial: "教程" -ui.contents.close: "关闭目录" -ui.contents.open: "打开目录" -ui.contents.title: "目录" -ui.footer.caption: "面向 .NET 的现代 RHI" -ui.footer.label: "页脚" -ui.language.label: "语言" -ui.language.unavailable: "未翻译" -ui.members.clear: "清除成员搜索" -ui.members.close: "关闭成员查找器" -ui.members.empty: "没有匹配的成员。" -ui.members.open: "转到成员" -ui.members.placeholder: "名称或签名…" -ui.members.search: "搜索成员" -ui.members.title: "查找成员" -ui.members.undeclared: "此类型没有声明的成员。" -ui.navigation.api: "API" -ui.navigation.concepts: "概念" -ui.navigation.home: "首页" -ui.navigation.label: "主导航" +concepts.execution.context.description: '{graphicsContext} 通过特定后端连接应用程序与 GPU 设备,并提供图形、计算和传输队列。配合使用的资源必须属于同一上下文;缓冲区、纹理、着色器、管线及其句柄不能跨上下文绑定。' +concepts.execution.context.details: '{capabilities} 提供设备名称与支持的功能。创建光线追踪或网格着色所需的资源前,分别通过 {rayTracingSupported} 和 {meshShadingSupported} 检查支持情况。{link}与{detail}示例展示了初始化时的检查方式。' +concepts.execution.context.details.detail: '网格着色' +concepts.execution.context.details.link: '光线追踪' +concepts.execution.context.title: '图形上下文' +concepts.execution.description: 'GPU 工作从 CPU 端开始:应用程序创建资源,录制使用这些资源的命令,再将命令提交到队列。提交之后,CPU 可以继续处理其他任务,同时由 GPU 执行命令。相关资源必须保留到执行结束。' +concepts.execution.ownership.description: '所有权决定由谁释放对象,GPU 完成状态决定何时可以释放。即使仍保留对象的 C# 引用,调用 {dispose} 也会释放其原生资源。提交命令不会将资源所有权转交给队列。' +concepts.execution.ownership.details: '关闭程序时,先停止提交新工作,并等待所有相关队列完成最后一次资源访问。随后释放应用程序资源,最后释放上下文。上下文会释放自身的队列和内部辅助对象,因此这一步应在应用程序工作全部完成后进行。' +concepts.execution.ownership.guidance: '渲染期间,若准备覆盖数据或替换资源,应跟踪仍在使用它们的工作。等待这些访问完成后,再修改数据或释放存储。视图与底层资源如何遵循这一生命周期规则,见{link}。' +concepts.execution.ownership.guidance.link: '资源管理' +concepts.execution.ownership.table.applicationResources.object: '应用程序创建的资源' +concepts.execution.ownership.table.applicationResources.ownership: '最后一次 GPU 使用完成后,由应用程序释放。' +concepts.execution.ownership.table.commandBuffers.object: '借用的命令缓冲区' +concepts.execution.ownership.table.commandBuffers.ownership: '由队列管理和回收。' +concepts.execution.ownership.table.headings.object: '对象' +concepts.execution.ownership.table.headings.ownership: '释放责任' +concepts.execution.ownership.table.queues.object: '图形上下文的队列及其时间线' +concepts.execution.ownership.table.queues.ownership: '由上下文和队列管理。' +concepts.execution.ownership.table.swapChainDrawable.ownership: '由交换链管理。' +concepts.execution.ownership.title: '所有权与生命周期' +concepts.execution.pipelines.description: '图形管线规定绘制所用的着色器、顶点输入布局、图元组装方式、附件格式和渲染状态。绑定顶点、索引或常量数据之前,须先选择管线;管线声明的附件格式与采样数也必须与渲染通道一致。' +concepts.execution.pipelines.details: '计算管线选择分派所执行的着色器入口点。在图形渲染通道之外,先绑定管线及其常量,再执行分派。' +concepts.execution.pipelines.guidance: '{link}给出了完整的图形命令顺序。{detail}则先执行计算分派,再通过图形通道显示结果。' +concepts.execution.pipelines.guidance.detail: '计算示例' +concepts.execution.pipelines.guidance.link: '三角形的渲染回调' +concepts.execution.pipelines.title: '管线状态' +concepts.execution.queues.description: '一帧同时包含绘制、计算和复制时,通常从 {graphicsQueue} 开始。将有依赖的操作放在同一队列,有助于明确执行顺序。' +concepts.execution.queues.details: '不同队列可以分别接收独立的工作负载,但未必对应独立的硬件引擎。若工作能够从重叠执行中受益,再考虑增加队列。当一个队列使用另一个队列生成的数据时,需要在两次提交之间建立显式依赖。' +concepts.execution.queues.guidance: '即使位于同一队列,有依赖的操作也可能需要屏障或纹理转换,才能让后续访问读到此前写入的结果。这种内存依赖与提交顺序不同,具体表达方式见{link}。' +concepts.execution.queues.guidance.link: '同步' +concepts.execution.queues.table.computeQueue.workToRecord: '计算分派以及兼容的传输工作,不含图形渲染通道。' +concepts.execution.queues.table.graphicsQueue.workToRecord: '渲染通道、绘制、计算与传输操作。' +concepts.execution.queues.table.headings.queue: '队列' +concepts.execution.queues.table.headings.workToRecord: '支持的工作' +concepts.execution.queues.table.transferQueue.workToRecord: '上传、回读与复制工作,不含绘制或计算分派。' +concepts.execution.queues.title: '队列选择' +concepts.execution.recording.context: '队列会回收已完成的命令缓冲区以供复用。每次录制时,通过 {queueCommandBuffer} 获取缓冲区,同一时间只由一个线程录制,并且只提交一次。提交后,将缓冲区交由队列管理,不再修改、重复提交或自行释放。' +concepts.execution.recording.description: '{queueCommandBuffer} 返回的 {commandBuffer} 已处于录制状态。录制完操作及其依赖后,调用一次 {submit}。提交会结束录制,并返回标识该队列完成点的 {timelineValue}。' +concepts.execution.recording.details: '三角形教程将一帧录制到 {commandBuffer} 后,按如下方式提交并等待完成:' +concepts.execution.recording.guidance: '录制构造命令序列,{submit} 安排该序列执行。随后调用 {wait},CPU 线程会等待本次提交完成。教程因此采用逐帧执行的流程:当前帧完成后,才开始下一帧。' +concepts.execution.recording.title: '录制与提交' +concepts.execution.title: '执行模型' +concepts.platforms.description: '呈现流程可以由应用程序管理,也可以交给 UI 渲染控件。这决定了谁来获取当前帧的输出纹理、录制和提交命令,以及显示渲染结果。' +concepts.platforms.frame.context: '在通道内绑定管线并录制绘制命令,处理程序返回前须结束通道。控件负责提交命令并呈现结果;处理程序不得自行提交命令缓冲区,也不得释放传入的命令缓冲区或输出纹理。若改变了输出纹理的布局,返回前须恢复为 {colorAttachment},以便控件完成最后的转换。' +concepts.platforms.frame.description: '各控件实现 {iZenithView} 接口。应用程序设置 {graphicsContext},在 {updateRequested} 中更新场景,并在 {renderRequested} 中通过传入的 {renderEventArgs} 录制命令。' +concepts.platforms.frame.details: '每帧,控件获取输出纹理与命令缓冲区,将输出纹理转换为 {colorAttachment},再调用更新和渲染处理程序。之后,控件提交录制的工作,并通过对应框架的呈现机制显示图像。' +concepts.platforms.frame.guidance: '先在文件中添加 {usingZenithNET}。假定名为 {view} 的 {iZenithView} 实例已初始化并设置图形上下文,可注册以下处理程序清除其输出纹理:' +concepts.platforms.frame.notes: '初始转换使用 {undefined},允许丢弃先前图像的内容。因此,每帧都应重新绘制或清除整张图像。需要累积或缓存的渲染结果,可保存在应用程序拥有的纹理中,再将该纹理绘制到控件的输出纹理上。' +concepts.platforms.frame.reference: '{zenithViewHelperDrawableFormat} 提供这些集成使用的默认颜色格式。' +concepts.platforms.frame.title: '通过 UI 控件渲染' +concepts.platforms.integration.context: 'WinForms、WPF 和 Windows 版 WinUI 集成运行于 Windows。使用 MAUI 时,安装目标平台的工作负载,并通过 {useZenithView} 注册控件处理程序,具体见 {extensionsCs}。' +concepts.platforms.integration.description: '控件共享事件接口,但呈现机制因框架而异:' +concepts.platforms.integration.details: '各实现将 GPU 图像送到 UI 的方式不同。位图回读先将像素复制到 CPU 内存,再显示图像;共享纹理互操作可以省去这次 CPU 复制,但仍可能需要 GPU 复制与同步。选择集成方式时,除了共用的 {renderRequested} 事件接口,也应考虑其呈现路径。' +concepts.platforms.integration.guidance: '通过 NuGet 添加所用 UI 框架的集成包。Avalonia 对应的包为 {avaloniaPackage}。' +concepts.platforms.integration.table.avalonia.integration: 'Avalonia' +concepts.platforms.integration.table.avalonia.presentation: '渲染到纹理后,将像素回读到 {writeableBitmap},实现见 {zenithViewCs} 和 {surfaceCs}。' +concepts.platforms.integration.table.headings.integration: '集成' +concepts.platforms.integration.table.headings.presentation: '呈现机制' +concepts.platforms.integration.table.maui.integration: '.NET MAUI' +concepts.platforms.integration.table.maui.presentation: 'Android、iOS 和 Mac Catalyst 使用原生呈现目标;Windows 使用共享纹理合成,具体见{link}。' +concepts.platforms.integration.table.maui.presentation.link: '平台实现' +concepts.platforms.integration.table.uno.integration: 'Uno 路径' +concepts.platforms.integration.table.uno.presentation: '将像素回读到 {writeableBitmap},实现见 {zenithViewUnoCs}。' +concepts.platforms.integration.table.winForms.integration: 'WinForms' +concepts.platforms.integration.table.winForms.presentation: '为控件的 {hWND} 创建 Zenith.NET 交换链,实现见 {zenithViewCs}。' +concepts.platforms.integration.table.winUI.integration: 'Windows 上的 WinUI' +concepts.platforms.integration.table.winUI.presentation: '渲染到导入的共享 Direct3D 11 纹理,再复制到与 {swapChainPanel} 连接的合成交换链,具体见 {zenithViewWinUICs}。' +concepts.platforms.integration.table.wpf.integration: 'WPF' +concepts.platforms.integration.table.wpf.presentation: '导入共享 Direct3D 11 纹理,再经 Direct3D 互操作复制到由 {d3DImage} 显示的表面,具体见 {surfaceCs}。' +concepts.platforms.integration.title: '框架与呈现路径' +concepts.platforms.lifecycle.context: '创建配套附件时,使用渲染事件传入的输出纹理的 {descWidth}、{descHeight}、{descFormat} 和 {descSampleCount}。该纹理给出了渲染目标的实际尺寸,不应根据控件的布局尺寸或显示缩放比例推算。' +concepts.platforms.lifecycle.description: '交换链使用以像素计量的帧缓冲区宽度和高度。启用显示缩放时,这些值可能不同于窗口的逻辑尺寸。任一尺寸为零时,暂停渲染和交换链尺寸调整。每帧重新获取 {swapChainDrawable}:这张纹理由交换链管理,可能在呈现或调整大小后被替换。' +concepts.platforms.lifecycle.details: '帧缓冲区尺寸变化时,先等待 GPU 完成对旧图像的访问,再调用 {swapChainResize}。替换原生呈现目标时,也应先等待这些访问结束,再将新的呈现目标描述与句柄传给 {swapChainRefresh}。关闭程序时,先释放交换链,再销毁其原生呈现目标。' +concepts.platforms.lifecycle.guidance: '应用程序的深度纹理或离屏纹理若随窗口尺寸变化,就需要在调整大小时重建,并更新包含其句柄的常量。只要附件格式与采样数仍然匹配,管线就可以复用。{link}展示了如何调整纹理尺寸并保留管线。' +concepts.platforms.lifecycle.guidance.link: '旋转立方体渲染器' +concepts.platforms.lifecycle.title: '交换链尺寸与生命周期' +concepts.platforms.ownership.description: '应用程序拥有所设置的上下文及其渲染资源,控件拥有呈现资源。视图的 {graphicsContext} 变化后,调度程序会为新上下文重建控件资源。应用程序也须为该上下文重建自己的管线、缓冲区和纹理。' +concepts.platforms.ownership.details: '替换渲染资源前,先停止视图的帧活动,并等待使用这些资源的 GPU 工作完成,再释放旧资源或上下文。移除视图后,所设置的上下文仍由应用程序负责释放。' +concepts.platforms.ownership.guidance: '共享的 {frameSchedulerCs} 通过视图的 UI 调度器运行帧处理程序。处理程序应集中于场景数据更新和命令录制,其中耗时的 CPU 工作也会延迟界面响应。' +concepts.platforms.ownership.title: '应用程序与控件的责任' +concepts.platforms.surface.description: '{link}使用 Silk.NET 创建窗口并处理事件。Zenith.NET 通过 {surface} 描述获取原生窗口句柄与尺寸,再据此创建 {swapChain}。操作系统窗口仍由应用程序负责管理。' +concepts.platforms.surface.description.link: '三角形教程' +concepts.platforms.surface.details: '原生句柄必须与所选后端匹配:' +concepts.platforms.surface.guidance: '{appCs} 中的示例宿主支持 Windows、macOS 和 X11。Linux 窗口提供 Xlib 句柄,因此在 Wayland 会话中需要 XWayland。原生 Wayland 应用程序则通过 {surfaceWayland} 提供显示与表面句柄。' +concepts.platforms.surface.table.android.backend: 'Android 上的 Vulkan。' +concepts.platforms.surface.table.apple.backend: 'Apple 平台上的 Metal。' +concepts.platforms.surface.table.headings.backend: '后端与平台' +concepts.platforms.surface.table.headings.factory: '呈现目标工厂方法' +concepts.platforms.surface.table.headings.handles: '宿主提供的句柄' +concepts.platforms.surface.table.wayland.backend: '带有原生 Wayland 宿主的 Vulkan。' +concepts.platforms.surface.table.wayland.handles: 'Wayland 显示与表面' +concepts.platforms.surface.table.win32.backend: 'Windows 上的 DirectX 12 或 Vulkan。' +concepts.platforms.surface.table.xlib.backend: 'Linux 上带有 X11 或 XWayland 的 Vulkan。' +concepts.platforms.surface.table.xlib.handles: 'X11 显示与窗口' +concepts.platforms.surface.title: '原生呈现目标' +concepts.platforms.title: '平台集成' +concepts.resources.allocation.context: '放置在堆中的资源在整个生命周期内都依赖堆的存储。最后一次 GPU 使用完成后,应先释放资源,再释放堆。' +concepts.resources.allocation.description: '应用程序需要自行管理内存分配时,可以使用 {heap}。堆为资源提供存储,应用程序选择明确的字节偏移量来放置资源,并记录各区域的占用情况。' +concepts.resources.allocation.details: '对每个资源,使用创建时所需的缓冲区或纹理描述调用 {contextGetSizeAndAlignment}。按返回的大小预留空间,起始偏移量须为返回对齐值的整数倍,且整个区域位于堆内,不与其他仍有效的分配重叠。纹理可能包含后端特有的填充,因此不能仅根据像素数量和每像素字节数计算分配大小。' +concepts.resources.allocation.guidance: '放置在堆中的缓冲区必须使用与堆相同的驻留设置。纹理存储使用 GPU 专用堆。' +concepts.resources.allocation.title: '堆分配' +concepts.resources.bufferUsages.table.constant.role: '通过常量缓冲区绑定读取的着色器参数。' +concepts.resources.bufferUsages.table.headings.role: '作用' +concepts.resources.bufferUsages.table.headings.usage: '用途' +concepts.resources.bufferUsages.table.index.role: '索引绘制所使用的索引。' +concepts.resources.bufferUsages.table.indirect.role: '间接绘制或分派命令读取的参数。' +concepts.resources.bufferUsages.table.none.role: '未声明任何缓冲区用途标志。' +concepts.resources.bufferUsages.table.storageReadOnly.role: '通过只读着色器绑定访问的缓冲区数据。' +concepts.resources.bufferUsages.table.storageReadWrite.role: '通过读写着色器绑定访问的缓冲区数据。' +concepts.resources.bufferUsages.table.transferDst.role: 'GPU 复制操作的目标存储。' +concepts.resources.bufferUsages.table.transferSrc.role: 'GPU 复制操作的源数据。' +concepts.resources.bufferUsages.table.vertex.role: '供绘制命令读取的顶点属性。' +concepts.resources.bufferUsages.title: '缓冲区用途' +concepts.resources.description: '资源描述规定应用程序如何使用其存储。例如,一张纹理若要作为渲染目标、供着色器采样,并将内容复制回 CPU,就需要声明这三种操作对应的用途。内存放置决定 CPU 的访问方式,同步与生命周期管理则决定何时可以访问数据或释放存储。' +concepts.resources.memory.context: '对于 CPU 可访问的缓冲区,{map} 提供 CPU 读写数据所用的地址。映射和 {unmap} 都不会等待 GPU 工作。CPU 读取 GPU 写入的结果前,应用程序须先等待写入完成;修改同一块内存前,也须等待 GPU 对这些字节的访问结束。' +concepts.resources.memory.description: '{bufferDesc} 的 {residency} 字段指定了 CPU 对分配内存的预期访问方式:' +concepts.resources.memory.details: '驻留设置表达 CPU 的访问需求,即使 CPU 与 GPU 共享物理内存也同样适用。三角形教程使用 {cpuWriteOnly} 直接初始化小型顶点缓冲区。对于较大的静态几何数据,上传到 GPU 专用存储可能更合适。' +concepts.resources.memory.guidance: '通过上下文直接创建的纹理使用 GPU 存储,因此 {textureDesc} 没有驻留字段。应用程序通过上传和回读,在纹理与 CPU 内存之间交换数据。' +concepts.resources.memory.table.cpuReadOnly.cPUAccess: '只读' +concepts.resources.memory.table.cpuReadOnly.typicalRole: 'GPU 生成的回读数据' +concepts.resources.memory.table.cpuWriteOnly.cPUAccess: '只写' +concepts.resources.memory.table.cpuWriteOnly.typicalRole: 'CPU 提供或更新的数据' +concepts.resources.memory.table.gpuOnly.cPUAccess: '无' +concepts.resources.memory.table.gpuOnly.typicalRole: '静态几何体和 GPU 工作数据' +concepts.resources.memory.table.headings.cPUAccess: '预期 CPU 访问' +concepts.resources.memory.table.headings.residency: '内存驻留' +concepts.resources.memory.table.headings.typicalRole: '典型用途' +concepts.resources.memory.title: 'CPU 访问与内存放置' +concepts.resources.textureUsages.description: '传输标志声明资源在 GPU 复制中用作源还是目标。CPU 能否直接访问这块存储,则由内存放置方式决定。' +concepts.resources.textureUsages.details: '用途标志声明纹理可以承担的作用。在这些作用之间切换时,需要相应的{link};所选设备也必须支持以该纹理格式执行所声明的操作。' +concepts.resources.textureUsages.details.link: '布局与同步' +concepts.resources.textureUsages.table.colorAttachment.role: '渲染通道中的颜色附件。' +concepts.resources.textureUsages.table.depthStencilAttachment.role: '渲染通道中的深度/模板附件。' +concepts.resources.textureUsages.table.headings.role: '作用' +concepts.resources.textureUsages.table.headings.usage: '用途' +concepts.resources.textureUsages.table.none.role: '未声明任何纹理用途标志。' +concepts.resources.textureUsages.table.sampled.role: '通过采样纹理绑定读取的纹理数据。' +concepts.resources.textureUsages.table.storage.role: '通过存储纹理绑定供着色器读取或写入的纹理数据。' +concepts.resources.textureUsages.table.transferDst.role: 'GPU 复制操作的目标图像存储。' +concepts.resources.textureUsages.table.transferSrc.role: 'GPU 复制操作的源图像数据。' +concepts.resources.textureUsages.title: '纹理用途' +concepts.resources.title: '资源管理' +concepts.resources.transfers.context: '回读先将 GPU 数据复制到内部回读存储。库回收已完成的命令缓冲区时,再将数据复制到指定的 CPU 目标。对本次回读提交的完成值调用 {wait},可以完成这两个步骤。在调用返回前,目标内存须保持已分配状态,托管内存须保持固定。' +concepts.resources.transfers.description: '上传将 CPU 数据复制到 GPU 资源,回读则将资源数据复制到 CPU 内存。缓冲区和纹理上的这些方法会在传输完成后返回:' +concepts.resources.transfers.details: '调用这些方法前,先处理与其他队列访问之间的冲突。方法内部的等待只覆盖其自身的传输,不会建立与其他队列的依赖。直接通过映射内存复制时,则完全由调用方负责等待存在冲突的 GPU 访问。' +concepts.resources.transfers.guidance: '要将传输与其他 GPU 工作一同提交,可通过 {commandBufferUpload} 或 {commandBufferDownload} 录制。上传源与回读目标的内存生命周期要求不同:' +concepts.resources.transfers.item: '上传调用期间,库会将源数据复制到内部的临时上传存储,即暂存内存。GPU 随后从这块存储读取,因此应用程序的源指针只需保持有效到调用返回。' +concepts.resources.transfers.notes: '纹理传输中的行步幅是 CPU 数据相邻两行之间的字节距离;切片步幅则是相邻深度切片之间的字节距离。传输操作根据这些值,在 CPU 数据与纹理的 GPU 存储之间复制内容。GPU 完成与数据送达回读目标为何是两个步骤,见{link}。' +concepts.resources.transfers.notes.link: '同步' +concepts.resources.transfers.table.bufferDownload.transfer: '对于 {cpuReadOnly},直接从映射内存复制;否则向传输队列提交回读,并等待完成。' +concepts.resources.transfers.table.bufferUpload.transfer: '对于 {cpuWriteOnly},直接复制到映射内存;否则向传输队列提交上传,并等待完成。' +concepts.resources.transfers.table.headings.method: '方法' +concepts.resources.transfers.table.headings.transfer: '传输行为' +concepts.resources.transfers.table.textureTransfers.method: '{textureUpload} / {textureDownload}' +concepts.resources.transfers.table.textureTransfers.transfer: '将复制及其纹理转换提交到图形队列,并等待完成。操作结束后,所选子资源处于指定的最终布局。' +concepts.resources.transfers.title: '立即传输与命令录制' +concepts.resources.usages.description: '{bufferUsages} 和 {textureUsages} 是用于声明资源用途的标志枚举,分别设置在 {bufferDescUsages} 和 {textureDescUsages} 中。资源需要承担多种用途时,可通过 {value} 组合相应成员。' +concepts.resources.usages.title: '资源用途' +concepts.resources.views.description: '{bufferView} 描述缓冲区的一块区域及其数据解释方式。{textureView} 选择子资源范围,以及兼容的纹理类型和格式。二者都引用已有存储,并遵循创建该存储时声明的用途。视图范围用于描述访问范围,各后端并不因此提供一致的着色器边界检查。' +concepts.resources.views.details: '资源自身的句柄提供默认视图。需要其他区域或兼容的解释方式时,再创建独立视图。视图及其底层资源都必须保留到 GPU 使用结束;仅持有资源句柄不能使任一对象保持存活。替换其中任一对象时,还须更新包含旧{link}的常量。' +concepts.resources.views.details.link: '资源句柄' +concepts.resources.views.title: '视图与底层资源' +concepts.shaders.binding.context: '计算示例将 {inputTextureSampledHandle} 写入 {input},将 {outputTextureStorageHandle} 写入 {output}。在 Slang 中,{descriptorHandle} 的类型参数规定了着色器访问资源的方式:' +concepts.shaders.binding.description: '{setConstantBuffer} 选择已有缓冲区及字节偏移量,当前管线从该位置读取常量。着色器使用这些参数前,先将数据上传到相应存储。如果此前提交的 GPU 工作仍在读取同一批字节,须等待该工作完成后再更新。' +concepts.shaders.binding.details: '准备好命令缓冲区、计算管线、已填入数据的常量缓冲区和线程组数量后,按以下顺序录制分派。常量缓冲区的绑定作用于当前管线,因此必须先选择管线:' +concepts.shaders.binding.guidance: '这里,{commandBuffer} 使用 {computePipeline} 及 {constantBuffer} 中的参数录制分派。缓冲区需要声明 {bufferUsagesConstant} 用途,偏移量 0 选择其起始位置。如果多条常量记录共用缓冲区,每条记录的起始偏移量还须满足后端绑定的对齐要求,这与记录内部的字段布局是两项独立要求。' +concepts.shaders.binding.notes: '{resourceHandle} 包含两个 32 位字段,含义由后端解释,其值仅在创建资源的上下文中有效。' +concepts.shaders.binding.reference: '保留资源及用于获取句柄的视图,直到着色器完成最后一次访问。替换纹理或视图后,应更新仍含旧句柄的常量。相关所有权规则见{link}。' +concepts.shaders.binding.reference.link: '资源管理' +concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: '读取着色器类型 {t} 的结构化元素' +concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: '读写着色器类型 {t} 的结构化元素' +concepts.shaders.binding.table.headings.access: '预期访问' +concepts.shaders.binding.table.headings.cHandle: 'C# 句柄' +concepts.shaders.binding.table.headings.slangFieldType: 'Slang 字段类型' +concepts.shaders.binding.table.samplerHandle.access: '纹理采样状态' +concepts.shaders.binding.table.textureSampledHandle.access: '纹理读取' +concepts.shaders.binding.table.textureStorageHandle.access: '存储纹理的读写' +concepts.shaders.binding.title: '常量缓冲区与资源句柄' +concepts.shaders.compilation.description: '{zenithCompiler} 将指定的 Slang 入口点编译为 {shaderDesc}。上下文的 {graphicsApi} 决定目标格式:DirectX 12 使用 DXIL,Metal 使用 Metal 库,Vulkan 使用 SPIR-V。' +concepts.shaders.compilation.details: '创建名为 {context} 的图形上下文后,可以编译已复制到可执行文件所在目录的三角形着色器:' +concepts.shaders.compilation.guidance: '入口点名称 {vSMain} 必须与着色器文件中的函数声明一致。在初始化阶段编译着色器并创建管线,渲染期间复用管线。管线创建完成后即可释放着色器对象,具体见{link}。' +concepts.shaders.compilation.guidance.link: '第一个三角形' +concepts.shaders.compilation.title: '着色器编译' +concepts.shaders.description: 'C# 与 Slang 声明必须约定一致的数据位置和访问方式。顶点输入布局描述顶点属性,着色器缓冲区声明描述参数与数组,资源句柄则标识着色器使用的资源。' +concepts.shaders.dispatch.description: '{dispatch} 指定执行多少个线程组。计算示例声明 {numthreads},每组因此包含 16 × 16 个线程。将图像的宽和高分别除以 16 并向上取整,即可覆盖整张图像:17 × 19 的图像需要 2 × 2 组。着色器检查每个线程的坐标,并跳过位于图像范围以外的线程。' +concepts.shaders.dispatch.details: '{shaderDescThreadGroupSize} 提供声明的组大小,可用于计算传给 {dispatch} 的线程组数量。完整计算过程见 {computeShaderRendererCs}。分派完成后,访问输出图像时还须满足{link}中说明的要求。' +concepts.shaders.dispatch.details.link: '同步' +concepts.shaders.dispatch.title: '线程组' +concepts.shaders.layout.context: '{link}通过图像尺寸与两个纹理句柄展示了这种排列。各字段的起始位置由显式偏移量指定。以下声明使用 {systemRuntimeInteropServices} 和 {zenithNET} 命名空间:' +concepts.shaders.layout.context.link: '计算示例的 C# 常量' +concepts.shaders.layout.description: '对于顶点输入,{inputLayout} 描述各属性的格式、偏移量和语义,以及相邻顶点之间的步幅。三角形先存放 {float3} 位置,再存放 {float4} 颜色:颜色的字节偏移量为 12,每个顶点占 28 字节。{inputLayoutAdd} 根据元素格式计算这一紧密排列的布局。如果 C# 结构体包含填充,就需要在偏移量和步幅中计入这些空间。' +concepts.shaders.layout.details: '常量缓冲区存放着色器参数,结构化缓冲区存放指定类型的元素数组。它们的布局由 Slang 声明决定,不使用 {inputLayout}。C# 字段偏移量、元素大小和填充必须与编译后的着色器布局一致。即使某个 C# 类型是非托管类型,可以直接按字节复制,其内存排列也未必符合着色器要求;例如,顶点中紧密排列的 {float3},在着色器缓冲区中可能需要不同的对齐方式。' +concepts.shaders.layout.guidance: '着色器参数除了普通数值,也可以包含资源句柄。句柄标识的是已有存储,因此将句柄复制到常量缓冲区并不会复制资源内容。' +concepts.shaders.layout.notes: '{computeShaderSlang} 中对应的声明为:' +concepts.shaders.layout.reference: '两个尺寸值占用前 8 字节,后面是两个各占 8 字节的句柄。C# 示例为整条记录预留 256 字节。其他记录的大小应根据各自字段以及所需的布局和对齐方式确定。' +concepts.shaders.layout.title: '数据布局' +concepts.shaders.matrices.description: '编译器采用行优先的矩阵存储方式,使同一行的元素连续排列。{link}在偏移量 0、64 和 128 处保存三个 {matrix4x4} 值,其{detail}按模型、视图和投影顺序执行 {mulVectorMatrix}。' +concepts.shaders.matrices.description.detail: '着色器' +concepts.shaders.matrices.description.link: '旋转立方体渲染器' +concepts.shaders.matrices.details: '存储顺序决定矩阵元素在内存中的排列,乘法顺序决定变换。C# 与 Slang 应采用相互匹配的约定。' +concepts.shaders.matrices.title: '矩阵约定' +concepts.shaders.title: '着色器数据与绑定' +concepts.synchronization.backends.description: 'DirectX 12 和 Vulkan 将纹理转换记录为布局与访问状态的变化。在 Zenith.NET 的 Metal 后端中,{transition} 没有对应的 GPU 操作。Metal 后端将命令组织为渲染与计算编码器,并在编码器结束时插入可见性屏障。同一编码器内存在依赖的操作,例如连续的计算分派,通过显式调用 {barrier} 协调。' +concepts.synchronization.backends.details: '{link}开始图形渲染通道时,会结束计算编码器,使计算输出对后续图形工作可见。连续两次计算分派仍位于同一编码器内,即使中间录制了纹理转换,也需要屏障来处理依赖。因此,可跨后端使用的命令序列既要考虑纹理布局,也要处理访问之间的依赖。' +concepts.synchronization.backends.details.link: '计算示例' +concepts.synchronization.backends.title: '后端行为' +concepts.synchronization.barriers.context: '选择包含相关访问、且受到当前队列支持的阶段。{barrierStagesAll} 涵盖所有受支持的阶段;若依赖只涉及其中一部分,可选择更小的范围。' +concepts.synchronization.barriers.description: '假设同一个命令缓冲区内有两次计算分派,第一次写入模拟数据,第二次读取这些数据。在两次分派之间设置屏障,让第二次分派读到已经完成的写入结果。对于存储缓冲区,这样即可安排访问顺序,无须进行纹理布局转换:' +concepts.synchronization.barriers.details: '第一个参数指定产生数据的阶段,第二个参数指定使用数据的阶段。二者共同描述两次分派之间所需的执行顺序和内存可见性。' +concepts.synchronization.barriers.guidance: '{link}在模拟步骤之间采用这一方式。每道屏障都位于产生数据的分派之后、使用数据的分派之前。' +concepts.synchronization.barriers.guidance.link: 'FluidTank 模拟' +concepts.synchronization.barriers.title: '管线屏障' +concepts.synchronization.dependencies.description: '逐个资源确认哪些访问涉及同一份数据。只要其中存在写入,就必须维持所需的先后顺序。两次读取本身没有冲突,但仍需满足纹理布局和呈现要求。CPU 更新数据或释放资源前,也须等待 GPU 完成对相应存储的使用。' +concepts.synchronization.dependencies.details: '应根据操作执行的位置选择机制:' +concepts.synchronization.dependencies.guidance: '一项工作可能同时需要多种同步机制。例如,纹理由另一队列生成时,除了提交依赖,还需为下一次使用设置正确的布局。这两项操作本身都不需要阻塞 CPU;只有 CPU 要访问或释放相关数据时,才需要在 CPU 端等待。' +concepts.synchronization.dependencies.table.cpuAccess.mechanism: '对相关的完成值调用 {wait}。' +concepts.synchronization.dependencies.table.cpuAccess.situation: 'CPU 访问或资源释放需要等待 GPU 完成' +concepts.synchronization.dependencies.table.crossQueue.mechanism: '将生产者的 {timelineValue} 传给消费者的 {submit}。' +concepts.synchronization.dependencies.table.crossQueue.situation: '一个队列使用另一个队列生成的数据' +concepts.synchronization.dependencies.table.headings.mechanism: '机制' +concepts.synchronization.dependencies.table.headings.situation: '情况' +concepts.synchronization.dependencies.table.layoutChange.mechanism: '调用 {commandBufferTransition},指定先前布局与目标布局。' +concepts.synchronization.dependencies.table.layoutChange.situation: '纹理子资源更改其使用方式' +concepts.synchronization.dependencies.table.pipelineStages.mechanism: '调用 {commandBufferBarrier},指定产生数据和使用数据的阶段。' +concepts.synchronization.dependencies.table.pipelineStages.situation: '命令流中存在依赖关系的 GPU 阶段' +concepts.synchronization.dependencies.title: '访问依赖' +concepts.synchronization.description: '同步确定多个操作访问共享数据的顺序,并确保后续操作能够读到所需结果。在写后读依赖中,写入方称为生产者,读取方称为消费者。屏障与纹理转换协调 GPU 访问;时间线连接不同提交,并让 CPU 等待 GPU 工作完成。' +concepts.synchronization.layouts.context: '现有内容可以丢弃时,可将先前布局设为 {undefined},例如新建图像或即将完整清除的附件。若要保留内容以供加载、采样或累积,则应使用此前访问时的布局。' +concepts.synchronization.layouts.description: '纹理的用途标志声明允许的作用。{textureLayout} 描述命令序列中某一时刻对子资源的访问方式,子资源由 mip 级别和数组层确定。访问方式发生变化时,需要录制转换。例如,计算示例在 {storage} 布局中写入输出纹理,再为图形通道中的采样做准备:' +concepts.synchronization.layouts.details: '这里的 {outputTexture} 已声明 {sampledStorage} 用途,所选子资源处于 {storage} 布局。{default} 选择 mip 级别 0 和数组层 0,其他级别和层不受这次转换影响。' +concepts.synchronization.layouts.guidance: '调用 {transition} 时,提供子资源上一次使用的布局。应用程序在录制命令,以及在渲染阶段之间传递纹理时,负责跟踪这个状态。' +concepts.synchronization.layouts.title: '纹理布局' +concepts.synchronization.readback.description: '{isCompleted} 报告 GPU 的完成状态。通过命令录制的回读还需要一个步骤:将结果从内部回读存储复制到应用程序的目标内存。' +concepts.synchronization.readback.details: '{commandBufferDownload} 录制向内部回读存储复制数据的 GPU 命令。提交完成后,库在回收命令缓冲区时执行最后的 CPU 复制。对本次回读提交的完成值调用 {wait},会等待 GPU 完成,并处理该队列已完成的缓冲区,从而完成这两个步骤。调用返回前,目标内存须保持已分配状态,托管内存须保持固定。' +concepts.synchronization.readback.guidance: '仅轮询 {isCompleted} 不会执行最后的 CPU 复制;等待其他队列,也不会回收回读队列中已完成的缓冲区。上传和回读在何时使用直接内存访问或暂存存储,见{link}。' +concepts.synchronization.readback.guidance.link: '资源管理' +concepts.synchronization.readback.title: '回读完成' +concepts.synchronization.reuse.description: '三角形教程在每帧完成后才复用数据。若要让帧重叠执行,应为每个尚未完成的帧准备独立的可变存储,并跟踪何时可以再次使用。修改数据前,须等待 GPU 完成对相关字节的访问;释放资源前,则须等待它的所有使用结束。' +concepts.synchronization.reuse.details: '调整大小与关闭程序遵循相同的顺序:先停止新的资源访问,等待已有访问结束,再替换或释放资源。调用 {swapChainResize} 或释放资源、上下文前,须先完成上述等待。三角形教程已经逐帧等待,因此可以在回调之间调整大小。' +concepts.synchronization.reuse.guidance: '{swapChainPresent} 在呈现后向图形队列发出信号并等待。因此,即使去掉显式的提交等待,三角形教程仍会在呈现时等待。独立提交到其他队列的工作,则需要单独跟踪其完成状态。' +concepts.synchronization.reuse.title: '资源复用' +concepts.synchronization.timelines.context: 'CPU 若要在消费者完成后读取结果、覆盖共享数据或释放资源,须先等待这次提交完成:' +concepts.synchronization.timelines.description: '时间线用递增值标识队列进度。{submit} 返回的 {timelineValue} 同时包含时间线和本次提交的值。不同时间线上的 {value} 数值不能直接比较。' +concepts.synchronization.timelines.details: '设 {producer} 和 {consumer} 是同一上下文中两个队列上已录制的命令缓冲区,后者使用前者写入的数据。提交时传入这项依赖:' +concepts.synchronization.timelines.guidance: '消费者所在的队列会先等待传入的完成值,再执行命令。CPU 无需调用 {producedWait},可以继续处理其他工作。共享资源须保留到 {consumed} 完成,同时仍需录制消费者访问所要求的纹理转换。' +concepts.synchronization.timelines.notes: '{queueTimelineSignal} 返回的值同样可以通过 {wait} 等待,也可以作为另一个队列的依赖。{signal} 将完成点排在此前已提交的工作之后,GPU 完成这些工作后便会到达该点。' +concepts.synchronization.timelines.title: '时间线与队列依赖' +concepts.synchronization.title: '同步' +home.actions.reference: '浏览 API' +home.actions.tutorial: '从三角形开始' +home.entries.description: '教程、示例与 API 参考' +home.entries.label: '文档分类' +home.entries.reference.action: '探索 API' +home.entries.reference.category: '参考' +home.entries.reference.description: '查阅 API 类型、成员与声明' +home.entries.reference.title: 'API 参考' +home.entries.samples.action: '浏览示例' +home.entries.samples.category: '示例' +home.entries.samples.description: '图形与计算技术的可运行示例' +home.entries.samples.title: '示例' +home.entries.title: '文档' +home.entries.tutorial.action: '开始教程' +home.entries.tutorial.category: '教程' +home.entries.tutorial.description: '从空项目开始,绘制第一个三角形' +home.entries.tutorial.title: '第一个三角形' +home.introduction.accent: '跨平台图形开发' +home.introduction.description: 'Zenith.NET 提供统一的图形与计算 API,支持 DirectX、Metal 和 Vulkan' +home.introduction.title: '面向 .NET 的{lineBreak}{accent}' +home.meta.description: '使用 Zenith.NET 开发跨平台图形与计算应用,通过统一 API 使用 DirectX、Metal 和 Vulkan' +home.scene.description: '可交互的旋转几何体。拖动或使用方向键调整视角。' +home.scene.label: '几何体显示' +home.scene.surface: '表面' +home.scene.wireframe: '线框' +home.title: '适用于 .NET 的现代 RHI' +learning.concepts.description: '选择资源用途、描述着色器数据与协调 GPU 执行' +learning.concepts.execution.description: '命令录制、提交与资源生命周期' +learning.concepts.platforms.description: '原生呈现与 UI 渲染控件' +learning.concepts.resources.description: '资源用途、内存放置与视图' +learning.concepts.shaders.description: 'C# 与 Slang 的数据布局和绑定约定' +learning.concepts.synchronization.description: '依赖关系、可见性与完成状态' +learning.concepts.title: '核心概念' +learning.description: '第一次使用 Zenith.NET,可以从三角形教程开始。完成后,按需要查阅资源管理、着色器数据和同步等概念,或通过示例了解具体图形技术的实现。' +learning.entries.samples.action: '浏览示例' +learning.entries.samples.description: '几何体、计算、光线查询与网格着色的 C# 和 Slang 实现' +learning.entries.tutorial.action: '打开教程' +learning.entries.tutorial.description: '创建窗口并渲染三角形的控制台应用程序' +learning.meta.description: 'Zenith.NET 编程模型的入门教程与概念说明' +learning.title: '学习' +reference.description: '资源、命令与平台集成的参考文档' +reference.entries.commands.description: '图形、计算与传输命令' +reference.entries.commands.label: '录制命令' +reference.entries.context.description: '为所选后端创建 GPU 资源' +reference.entries.context.label: '从这里开始' +reference.meta.description: 'Zenith.NET 的命名空间、类型与成员' +reference.navigation.core: '核心 API 参考' +reference.title: 'API 参考' +samples.computeShader.description: '示例加载 {assetsTexturesShokoPng},通过一次计算分派将图像转换为灰度,再显示输出纹理。转换只执行一次,后续帧显示相同结果。渲染器展示了采样纹理与可写纹理的绑定、向上取整线程组数量以覆盖整张图像的计算方式,以及着色器中的图像边界检查。' +samples.computeShader.details: '{computeShaderRendererCs} · {computeShaderSlang}' +samples.computeShader.title: '计算着色器' +samples.cube.description: '旋转立方体加入索引绘制、常量缓冲区中的模型、视图和投影矩阵,以及深度测试。窗口大小变化时,会重建 {d32FloatS8UInt} 深度/模板纹理。' +samples.cube.details: '{spinningCubeRendererCs} · {spinningCubeSlang}' +samples.cube.title: '旋转立方体' +samples.description: '每个示例均由 C# 渲染器与 Slang 着色器组成,集中说明一项技术。完整的应用程序设置与渲染顺序见{link}。' +samples.description.link: '第一个三角形' +samples.execution.description: '运行 {link} 项目,并从控制台菜单选择示例。' +samples.execution.description.link: 'ZenithTutorials' +samples.execution.title: '运行示例' +samples.host.description: '{appCs} 初始化上下文、窗口和交换链。每帧获取命令缓冲区,调用所选渲染器,提交命令并呈现结果。{iRendererCs} 规定渲染器的更新、渲染、调整大小和释放操作。' +samples.host.details: '计算与光线追踪渲染器生成离屏纹理。{texturePresenterCs} 和 {presentTextureSlang} 将这些纹理绘制到当前输出纹理,随后由共享宿主提交命令并呈现这一帧。' +samples.host.title: '宿主与呈现' +samples.indirectDrawing.description: '间接绘制通过索引绘制参数缓冲区和保存各实例数据的结构化缓冲区,绘制多个立方体。CPU 提供绘制参数并更新变换。' +samples.indirectDrawing.details: '{indirectDrawingRendererCs} · {indirectDrawingSlang}' +samples.indirectDrawing.title: '间接绘制' +samples.meshShading.description: '任务着色器剔除球体实例,将保留的索引传给负责生成几何体的网格着色器。创建管线前,渲染器检查 {contextCapabilitiesMeshShadingSupported}。' +samples.meshShading.details: '{meshShadingRendererCs} · {meshShadingSlang}' +samples.meshShading.title: '网格着色' +samples.rayTracing.description: '该示例为地面和程序化球体构建底层与顶层加速结构,再在计算着色器中执行内联光线查询。初始化前检查 {contextCapabilitiesRayTracingSupported}。' +samples.rayTracing.details: '{rayTracingRendererCs} · {rayTracingSlang}' +samples.rayTracing.title: '光线追踪' +samples.title: '示例' +samples.triangle.description: '三角形示例将顶点缓冲区与对应的输入布局关联,通过图形管线绘制三个顶点。' +samples.triangle.details: '{helloTriangleRendererCs} · {helloTriangleSlang} · {link}' +samples.triangle.details.link: '完整教程' +samples.triangle.title: 'Hello Triangle' +samples.workloads.description: '主仓库的{link}包含规模较大的应用程序,这些项目直接引用库源码。' +samples.workloads.description.link: 'Experiments 目录' +samples.workloads.details: '窗口实验项目采用相同的 Windows、macOS 和 Linux/X11 呈现路径。Avalonia、WinForms、WPF、WinUI/Uno 和 MAUI 控件的帧生命周期及实现代码见{link}。' +samples.workloads.details.link: '平台集成' +samples.workloads.table.cornellBox.example: '{link}' +samples.workloads.table.cornellBox.example.link: 'CornellBox' +samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: '路径追踪、降噪、色调映射、分辨率放大和 ImGui 控件。需要光线追踪支持。' +samples.workloads.table.fluidTank.example: '{link}' +samples.workloads.table.fluidTank.example.link: 'FluidTank' +samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: '计算流体模拟、模拟阶段之间的依赖,以及多通道表面渲染。' +samples.workloads.table.headings.example: '示例' +samples.workloads.table.headings.whatItDemonstratesAndRequires: '技术与运行要求' +samples.workloads.table.inkCanvas.example: '{link}' +samples.workloads.table.inkCanvas.example.link: 'InkCanvas' +samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: '原生窗口中的 Skia 绘制与输入处理。需要对应目标平台的后端和 Skia 原生库。' +samples.workloads.table.platformDetection.example: '{link}' +samples.workloads.table.platformDetection.example.link: 'PlatformDetection' +samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: '尝试为每个后端创建上下文,并报告设备能力。创建失败时显示为不支持,原因可能是设备、驱动程序或缺失的运行时依赖。' +samples.workloads.title: '综合应用' +tutorial.context.description: '{graphicsContext} 通过所选后端连接应用程序与 GPU,并提供创建渲染资源的方法。' +tutorial.context.details: '在{emphasis}插入上下文初始化代码:' +tutorial.context.details.emphasis: 'using 指令之后、{iWindowWindow} 之前' +tutorial.context.guidance: '各分支为当前平台选择后端并请求启用验证。{validationMessage} 消息会输出到控制台。' +tutorial.context.imports: '在 {programCs} 顶部添加以下 using 指令:' +tutorial.context.title: '图形上下文' +tutorial.description: '本教程从一个空的 .NET 控制台项目开始,逐步完成窗口创建,并在窗口中绘制一个彩色三角形。' +tutorial.details: '本教程有三个检查点:空窗口、单色背景和彩色三角形。每完成一个检查点,先运行程序确认结果,再继续添加下一部分。' +tutorial.draw.context: '{draw} 的参数如下:' +tutorial.draw.description: '在 {windowRender} 回调中,用以下命令替换 {addTheTriangleDrawCommandsHereLater},位置保持在 {beginRenderPass} 与 {endRenderPass} 之间:' +tutorial.draw.details: '{setPipeline} 选择着色器和渲染状态。后端按管线的输入布局解释顶点绑定,因此这一步必须先于顶点绑定。' +tutorial.draw.guidance: '{setVertexBufferVertexBuffer} 从缓冲区的字节偏移 0 开始,将已上传的顶点数据绑定到输入槽 0,对应 {inputLayouts} 中唯一的条目。' +tutorial.draw.notes: '这些调用录制绘制命令。已有的 {submitWait} 提交命令并等待 GPU 完成,随后 {present} 请求显示完成的图像。保留通道开始时的清除操作,让三角形以外的区域也有确定的背景色。' +tutorial.draw.table.firstInstance.meaning: '实例编号从零开始。' +tutorial.draw.table.firstVertex.meaning: '从缓冲区中的第一个顶点开始。' +tutorial.draw.table.headings.argument: '参数' +tutorial.draw.table.headings.description: '值' +tutorial.draw.table.headings.meaning: '含义' +tutorial.draw.table.instanceCount.meaning: '绘制一个三角形实例。' +tutorial.draw.table.vertexCount.meaning: '读取三个顶点。' +tutorial.draw.title: '绘制命令' +tutorial.execution.description: '构建并运行 {firstTriangle} 项目。' +tutorial.execution.details: '窗口中应出现一个三角形:上方为红色,右下为绿色,左下为蓝色,背景为深色。三个顶点的颜色经过插值,在三角形内部形成平滑过渡。' +tutorial.execution.guidance: '调整窗口大小时,图像的像素尺寸会改变,顶点坐标保持不变。视口将这些坐标映射到新的宽度和高度,因此改变窗口的宽高比会拉伸三角形。' +tutorial.execution.title: '运行应用程序' +tutorial.frame.commands.context: '{endRenderPass} 之后的第二次转换使输出纹理进入可呈现的布局。{submit} 结束录制并提交命令缓冲区,{wait} 阻塞至本次提交完成,随后 {present} 请求显示渲染结果。' +tutorial.frame.commands.description: '渲染通道将写入同一组附件的绘制操作组织在一起。本通道用交换链的输出纹理接收颜色输出。{colorAttachmentClear} 指定以 RGBA 颜色初始化该附件,并在通道结束时保留内容。{beginRenderPass} 按这些设置录制通道的开始命令。' +tutorial.frame.commands.details: '集合中有一个颜色附件。{null} 表示本通道不使用深度/模板附件。' +tutorial.frame.commands.guidance: '{beginRenderPass} 默认让视口和裁剪区域覆盖整个附件。视口把渲染坐标映射为像素位置,裁剪区域则限制可以写入的范围。' +tutorial.frame.commands.title: '清除、提交与呈现' +tutorial.frame.description: '先把窗口填成一种背景色,这个操作称为清除。背景正常显示后,就说明呈现目标、命令提交和呈现流程已经接通,可以继续加入三角形的顶点和着色器。' +tutorial.frame.details: 'Silk.NET 在需要绘制一帧时调用渲染回调。本示例不使用回调传入的时间间隔,因此将该参数命名为 {value}。在{emphasis}注册回调:' +tutorial.frame.details.emphasis: '{windowRun} 之前' +tutorial.frame.target.description: '{graphicsQueueCommandBuffer} 返回可直接录制的命令缓冲区。录制描述 GPU 工作,提交后才开始执行。' +tutorial.frame.target.details: '纹理布局描述操作对纹理的访问方式。第一次 {transition} 将输出纹理准备为颜色附件。这里的 {default} 选择 mip 级别 0 和数组层 0,也就是输出纹理的基础图像。由于这个通道会清除整张图像,可以指定 {undefined},允许丢弃原有内容。' +tutorial.frame.target.guidance: '呈现后可能换用另一张图像,因此每一帧都要获取当前的输出纹理。' +tutorial.frame.target.title: '准备输出纹理' +tutorial.frame.title: '第一帧' +tutorial.geometry.data.description: '在{emphasis}添加顶点数组。后续资源初始化也放在该回调之前,顺序如下。' +tutorial.geometry.data.description.emphasis: '{windowRender} 之前' +tutorial.geometry.data.details: '每个条目构造一个 {vertex},内部的两个 {new} 表达式分别提供 {vector3} 位置和 {vector4} 颜色。三个位置对应上角、右下角和左下角。顶点着色器将 {w} 作为第四个位置坐标;w 为 1 时,x、y 也就是归一化设备坐标,-1 与 +1 对应图像边界,0 对应中心,与像素尺寸无关。' +tutorial.geometry.data.guidance: '每个颜色包含红、绿、蓝和 alpha 分量,alpha 设为 1。三个顶点的 z 坐标均为 0,位于同一平面。' +tutorial.geometry.data.title: '顶点位置与颜色' +tutorial.geometry.description: '三角形的每个顶点都有位置和颜色。GPU 根据三个位置确定三角形的形状,再对顶点颜色插值,得到内部各处的颜色。' +tutorial.geometry.format.description: '在{emphasis}追加顶点声明:' +tutorial.geometry.format.description.emphasis: '{programCs} 的末尾、清理语句之后' +tutorial.geometry.format.details: '{file} 将类型的使用范围限定在 {programCs} 内,{layoutKindSequential} 则保留字段的声明顺序。{position} 包含三个 32 位浮点数,字节偏移量为 0;{color} 包含四个,字节偏移量为 12。因此,每个顶点占 28 字节。稍后将通过输入布局描述这一排列,让 GPU 正确读取各字段。' +tutorial.geometry.format.imports: '在 {programCs} 顶部添加以下 using 指令,以使用向量类型和结构体布局特性:' +tutorial.geometry.format.title: '顶点表示' +tutorial.geometry.title: '顶点数据' +tutorial.geometry.upload.context: '{fixed} 防止垃圾回收器在地址使用期间移动数组。对于这个 CPU 可写缓冲区,{upload} 会映射内存、复制数据,并在返回前解除映射,因此只需在调用期间固定数组。顶点数据在初始化时上传一次即可;缓冲区则必须保留到渲染结束。' +tutorial.geometry.upload.description: '将顶点存入 {buffer},供 GPU 在绘制时读取。在顶点数组之后紧接着添加分配与上传代码:' +tutorial.geometry.upload.details: '分配大小为 {sizeofVertexVerticesLength},即三个 28 字节顶点,共 84 字节。{bufferUsagesVertex} 声明顶点输入用途,{cpuWriteOnly} 允许 CPU 直接初始化。描述中的步幅记录元素大小,随后定义的输入布局指定 GPU 如何读取各个顶点属性。' +tutorial.geometry.upload.guidance: '分配不会初始化缓冲区内容。{upload} 使用数据描述中的源指针和字节数,将数组复制到目标字节偏移量 0。' +tutorial.geometry.upload.imports: '在 {programCs} 顶部的 using 指令中添加 {bufferAlias},以区分 Zenith.NET 的缓冲区类型与 {systemBuffer}。' +tutorial.geometry.upload.notes: '在 {programCs} 末尾的清理代码中,紧接在 {swapChainDispose} 之前加入 {vertexBufferDispose}。较大静态几何体所需的 GPU 专用存储与上传方式见{link}。' +tutorial.geometry.upload.notes.link: '资源管理' +tutorial.geometry.upload.title: '缓冲区分配与上传' +tutorial.input.description: 'GPU 需要知道位置、颜色等顶点属性存在哪里。输入布局指定每个属性的格式和字节偏移量,并用步幅表示从一个顶点到下一个顶点相隔多少字节。在创建着色器之后添加以下代码:' +tutorial.input.details: '{inputLayoutAdd} 将每个属性追加在前一个属性之后,并将其大小计入步幅。偏移量根据这里提供的格式计算,而非通过检查 C# 结构体获得。这两个字段对应的布局如下:' +tutorial.input.guidance: '{semanticIndex} 默认为 0,与着色器中的 {pOSITION0} 和 {cOLOR0} 对应。位置与颜色存放在同一个顶点缓冲区中,因此管线只需在槽 0 使用一个输入布局。如果 C# 结构体的字段顺序或填充发生变化,也要相应调整此布局。' +tutorial.input.table.headings.byteOffset: '字节偏移量' +tutorial.input.table.headings.cField: 'C# 字段' +tutorial.input.table.headings.format: '格式' +tutorial.input.table.headings.shaderInput: '着色器输入' +tutorial.input.table.nextVertex.cField: '下一个顶点' +tutorial.input.table.nextVertex.format: '总步幅:28 字节' +tutorial.input.table.nextVertex.shaderInput: '下一个输入记录' +tutorial.input.table.vertexColor.format: '{float4}(16 字节)' +tutorial.input.table.vertexPosition.format: '{float3}(12 字节)' +tutorial.input.title: '顶点输入布局' +tutorial.lifecycle.description: '每帧依次执行以下操作:' +tutorial.lifecycle.details: '关闭窗口后,{run} 返回,程序继续执行清理代码。每一帧都已等待其提交完成,因此现在可以释放这些命令使用的资源。{windowRun} 之后完整的清理代码如下:' +tutorial.lifecycle.guidance: '先释放交换链,再销毁其原生窗口;先释放应用程序资源,再释放上下文。已提交的命令缓冲区由队列回收,输出纹理由交换链管理,二者都不需要单独调用 {dispose}。' +tutorial.lifecycle.title: '帧生命周期与清理' +tutorial.pipeline.behavior: '在输入布局之后创建管线:' +tutorial.pipeline.context: '{cullNone} 关闭面剔除,因此无论顶点在画面中呈顺时针还是逆时针排列,三角形都会被绘制。' +tutorial.pipeline.description: '{graphicsPipeline} 将顶点布局、两个着色器,以及图元组装和附件输出所需的设置组合在一起。' +tutorial.pipeline.details: '着色器负责处理顶点和片元。其余管线设置决定图元如何组装、是否剔除某个朝向的面,以及如何进行深度测试和颜色混合:' +tutorial.pipeline.guidance: '管线颜色格式必须匹配渲染通道附件,因此直接取自 {swapChainDescFormat}。{count1} 表示每像素一个采样点。' +tutorial.pipeline.item: '{triangleList} 将每组连续的三个顶点组装成一个三角形。' +tutorial.pipeline.notes: '{depthNone} 关闭深度测试和深度写入,与通道没有深度附件的配置一致。' +tutorial.pipeline.reference: '{opaque} 关闭混合,因此片元着色器输出直接替换三角形内部的背景色。' +tutorial.pipeline.title: '图形管线' +tutorial.pipeline.usage: '管线创建完成后即可释放着色器对象。渲染期间保留管线,在清理代码中将 {pipelineDispose} 放在 {vertexBufferDispose} 之前。' +tutorial.presentation.title: '图形上下文与呈现' +tutorial.project.context: '在项目构建设置中启用{emphasis}({allowUnsafeBlocks})。窗口辅助代码的原生调用和顶点上传需要不安全代码。' +tutorial.project.context.emphasis: '允许不安全代码' +tutorial.project.description: '创建名为 {firstTriangle} 的 C# 控制台项目,目标框架设为 .NET 10。' +tutorial.project.details: '为项目添加以下 NuGet 包:' +tutorial.project.guidance: '{zenithNET} 提供统一渲染 API,三个后端包提供各平台的实现。{zenithNETCompiler} 为所选后端编译稍后介绍的 Slang 着色器。Silk.NET 负责窗口创建与事件处理。' +tutorial.project.title: '项目设置' +tutorial.requirements.context: '{link}及其{detail}提供了本教程的参考实现。' +tutorial.requirements.context.detail: '共享宿主' +tutorial.requirements.context.link: 'Hello Triangle 示例' +tutorial.requirements.description: '需要 {emphasis},并具备基础 C# 知识。应用程序以 {net10} 为目标框架。GPU 和驱动程序须支持所在平台选用的后端:' +tutorial.requirements.description.emphasis: '.NET 10 SDK' +tutorial.requirements.guidance: 'Zenith.NET 渲染到应用程序提供的原生呈现目标。Silk.NET.Windowing 创建窗口并处理事件。macOS 使用由 {cAMetalLayerCs} 表示的 Metal 图层,窗口辅助代码负责将其连接到窗口。' +tutorial.requirements.table.headings.graphicsBackend: '图形后端' +tutorial.requirements.table.headings.platform: '平台' +tutorial.requirements.table.linux.graphicsBackend: 'Vulkan 1.4' +tutorial.requirements.table.linux.platform: 'Linux(X11 或 XWayland)' +tutorial.requirements.table.macOS.graphicsBackend: 'Metal 4' +tutorial.requirements.table.macOS.platform: 'macOS' +tutorial.requirements.table.windows.graphicsBackend: 'DirectX 12' +tutorial.requirements.table.windows.platform: 'Windows' +tutorial.requirements.title: '前置条件' +tutorial.resize.context: '再次构建并运行程序。调整窗口大小后,背景应继续填满整个窗口:每次开始新的渲染通道时,视口和裁剪区域都会按调整后的附件尺寸设置。保留渲染回调,后面将在这个通道内绘制三角形。' +tutorial.resize.description: '帧缓冲区尺寸变化时,交换链也要随之调整。在渲染回调之后、{windowRun} 之前注册 {framebufferResize} 回调:' +tutorial.resize.details: '这里监听的是以像素为单位的{link},而非窗口逻辑尺寸的变化。窗口最小化时,帧缓冲区的宽度或高度可能变为零;此时,尺寸变化回调保留现有交换链,不执行调整。渲染回调也会在任一尺寸为零时直接返回,直到帧缓冲区恢复有效尺寸后再继续绘制。' +tutorial.resize.details.link: '帧缓冲区大小变化' +tutorial.resize.guidance: '渲染回调会等待当前帧的提交完成,再调用 {present}。因此,尺寸变化回调替换交换链图像时,此前帧的工作已经结束。关于完成状态与资源生命周期的要求,详见{link}。' +tutorial.resize.guidance.link: '同步' +tutorial.resize.title: '窗口尺寸变化' +tutorial.shaders.compilation.context: '{appContextBaseDirectory} 让程序从输出目录加载已复制的着色器。即使从其他工作目录启动程序,查找文件的位置也不会改变。' +tutorial.shaders.compilation.description: '将 {triangleSlang} 的文件属性{emphasis}设为{detail},构建时便会将着色器复制到可执行文件所在目录。' +tutorial.shaders.compilation.description.detail: '如果较新则复制' +tutorial.shaders.compilation.description.emphasis: '复制到输出目录' +tutorial.shaders.compilation.details: '返回 {programCs},在顶点上传之后、渲染回调之前添加着色器初始化:' +tutorial.shaders.compilation.guidance: '{zenithCompiler} 为 {contextGraphicsApi} 指定的后端编译源码,{createShader} 再根据编译后的描述创建着色器对象。入口点名称 {vSMain} 和 {fSMain} 分别选中 Slang 文件中定义的两个函数。' +tutorial.shaders.compilation.title: '编译着色器' +tutorial.shaders.context: '{fSInput} 连接两个着色器阶段。顶点着色器将裁剪空间位置写入 {sVPOSITION},GPU 据此判断三角形的可见部分。{cOLOR0} 字段传递顶点颜色,颜色经过三角形内部的插值后到达片元着色器。两个阶段必须使用一致的颜色类型与语义。' +tutorial.shaders.description: '着色器是在 GPU 上运行的程序。顶点着色器确定每个顶点的位置,片元着色器则确定图像中被覆盖位置的颜色。我们将两个阶段写在同一个 Slang 文件中,并分别定义入口点,也就是各阶段开始执行的函数。' +tutorial.shaders.details: '创建 {triangleSlang},先定义输入与输出结构:' +tutorial.shaders.fragment.description: '在同一文件中追加片元入口点:' +tutorial.shaders.fragment.details: '光栅化确定三角形在图像中的覆盖范围,并在这些位置生成片元。每个片元的颜色由三个顶点的颜色插值得到。{fSMain} 返回这个颜色,{sVTARGET} 则将结果送到第一个颜色附件。' +tutorial.shaders.fragment.title: '片元着色' +tutorial.shaders.guidance: '{vSInput} 定义顶点着色器输入。{pOSITION0} 和 {cOLOR0} 按语义标识属性,C# 字段名称本身不建立这一映射。' +tutorial.shaders.title: '着色器阶段' +tutorial.shaders.vertex.description: '在 {triangleSlang} 中追加顶点入口点:' +tutorial.shaders.vertex.details: 'GPU 为每个输入顶点调用这一入口点,补充齐次坐标 {w} 并传递颜色。顶点处理结束后,位置要除以 w。本例 w 为 1,x、y、z 保持不变,可直接解释为归一化设备坐标。' +tutorial.shaders.vertex.title: '顶点着色' +tutorial.surface.description: '在{emphasis}指定原生呈现目标:' +tutorial.surface.description.emphasis: '{windowCenter} 之后、{windowRun} 之前' +tutorial.surface.details: '帧缓冲区是窗口用于显示的像素图像。{surface} 描述原生呈现目标及其尺寸,{framebufferSize} 给出以像素为单位的大小。启用显示缩放时,这个大小可能与窗口的逻辑尺寸不同。' +tutorial.surface.guidance: '呈现目标提供后端所需的原生句柄:Windows 使用 Win32 窗口,Linux 使用 X11 显示与窗口,macOS 使用已连接的 Metal 图层。' +tutorial.surface.title: '原生呈现目标' +tutorial.swapChain.context: '交换链同时依赖上下文与窗口。将 {programCs} 末尾的 {windowDispose} 替换为以下释放顺序:' +tutorial.swapChain.description: '紧接呈现目标描述,创建交换链:' +tutorial.swapChain.details: '{swapChain} 管理窗口呈现的图像。{drawable} 以图像资源 {texture} 的形式提供当前图像。渲染后,{present} 请求显示该图像,并推进到下一个输出纹理。' +tutorial.swapChain.guidance: '{b8G8R8A8UNorm} 按蓝、绿、红和 alpha 顺序保存四个 8 位通道。{uNorm} 将整数 0–255 对应到 0–1。着色器仍输出逻辑 RGBA 值,格式只规定存储表示;管线通过 {swapChainDescFormat} 匹配附件。' +tutorial.swapChain.title: '交换链' +tutorial.title: '第一个三角形' +tutorial.troubleshooting.description: '结合控制台诊断与三个检查点定位失败阶段:' +tutorial.troubleshooting.details: '{link}与{detail}可用于核对顶点数据、输入布局和绘制操作。该示例将窗口与提交逻辑放入共享宿主,本教程则保留在 {programCs} 中。{context}进一步介绍索引绘制、变换与深度测试。' +tutorial.troubleshooting.details.context: '旋转立方体' +tutorial.troubleshooting.details.detail: 'Slang 着色器' +tutorial.troubleshooting.details.link: '示例渲染器' +tutorial.troubleshooting.table.backend.check: '检查所选后端是否受设备和已安装的图形驱动程序支持。' +tutorial.troubleshooting.table.backend.symptom: '后端创建失败' +tutorial.troubleshooting.table.drawing.check: '检查上传大小、输入布局、管线选择以及渲染通道内绘制命令的位置。' +tutorial.troubleshooting.table.drawing.symptom: '背景出现但三角形未出现' +tutorial.troubleshooting.table.headings.check: '检查项' +tutorial.troubleshooting.table.headings.symptom: '现象' +tutorial.troubleshooting.table.input.check: '检查步幅是否为 28 字节,位置和颜色是否分别从偏移 0 和 12 字节开始。' +tutorial.troubleshooting.table.input.symptom: '顶点位置或颜色异常' +tutorial.troubleshooting.table.shaders.check: '检查复制的 {triangleSlang}、入口点拼写以及编译器报告的诊断信息。' +tutorial.troubleshooting.table.shaders.symptom: '背景色正常显示,但着色器加载失败' +tutorial.troubleshooting.table.window.check: '确认 .NET 项目能够构建成功,并且仅包含窗口的步骤可以在桌面会话中运行。在 Linux 上,检查 X11 或 XWayland 是否可用。' +tutorial.troubleshooting.table.window.symptom: '窗口未打开' +tutorial.troubleshooting.title: '问题排查' +tutorial.window.description: '将 {cocoaHelperCs} 下载到项目中。该辅助类负责将 Metal 图层连接到 macOS 窗口。' +tutorial.window.details: '将自动生成的 {programCs} 内容替换为以下代码。它使用顶级语句,按书写顺序执行,不需要显式编写 {main} 方法。后续各节会指出新代码应放在哪里:' +tutorial.window.guidance: '{graphicsAPINone} 将图形上下文的创建交给 Zenith.NET。{initialize} 创建原生窗口,使窗口系统的句柄可供使用;{center} 把窗口放到屏幕中央。{run} 持续处理事件,直到窗口关闭,随后执行 {dispose} 释放窗口。' +tutorial.window.notes: '构建并运行程序,检查窗口能否打开、移动、调整大小和关闭。此时还没有提交渲染命令,窗口内容尚未定义。关闭窗口后再继续。' +tutorial.window.title: '创建窗口' +ui.action.copy: '复制' +ui.action.navigate: '导航' +ui.action.open: '打开' +ui.action.source: '查看源码' +ui.api.browse: '浏览命名空间和类型。' +ui.api.clearTypeSearch: '清除类型搜索' +ui.api.findType: '查找类型' +ui.api.loadError: '无法加载类型。刷新此页面以重试。' +ui.api.loadingNamespaces: '正在加载命名空间…' +ui.api.loadingTypes: '正在加载类型…' +ui.api.matchingTypes: '匹配的类型' +ui.api.namespace: '命名空间' +ui.api.namespaces: '命名空间' +ui.api.noNamespaceTypes: '此命名空间中没有类型。' +ui.api.noTypes: '没有匹配的类型。' +ui.api.types: '类型' +ui.content.reference: '参考' +ui.content.source: '源代码' +ui.content.tutorial: '教程' +ui.contents.close: '关闭目录' +ui.contents.open: '打开目录' +ui.contents.title: '目录' +ui.footer.caption: '面向 .NET 的现代 RHI' +ui.footer.label: '页脚' +ui.language.label: '语言' +ui.language.unavailable: '未翻译' +ui.members.clear: '清除成员搜索' +ui.members.close: '关闭成员查找器' +ui.members.empty: '没有匹配的成员。' +ui.members.open: '转到成员' +ui.members.placeholder: '名称或签名…' +ui.members.search: '搜索成员' +ui.members.title: '查找成员' +ui.members.undeclared: '此类型没有声明的成员。' +ui.navigation.api: 'API' +ui.navigation.concepts: '概念' +ui.navigation.home: '首页' +ui.navigation.label: '主导航' ui.navigation.skip: 跳转到正文 -ui.navigation.toggle: "切换导航" -ui.outline.title: "本页导读" -ui.reference.assembly: "程序集" -ui.reference.classes: "类" -ui.reference.constructors: "构造函数" -ui.reference.declaration: "C# 类型声明" -ui.reference.delegates: "委托" -ui.reference.derived: "派生类型" -ui.reference.enums: "枚举" -ui.reference.events: "事件" -ui.reference.examples: "示例" -ui.reference.exceptions: "异常" -ui.reference.extensionMethods: "扩展方法" -ui.reference.fields: "字段" -ui.reference.implementations: "显式接口实现" -ui.reference.implements: "实现" -ui.reference.inheritance: "继承" -ui.reference.inheritedMembers: "继承的成员" -ui.reference.interfaces: "接口" -ui.reference.metadata: "类型元数据" -ui.reference.methods: "方法" -ui.reference.namespace: "命名空间" -ui.reference.open: "打开 {name} 的参考文档" -ui.reference.operators: "运算符" -ui.reference.parameters: "参数" -ui.reference.properties: "属性" -ui.reference.related: "另请参阅" -ui.reference.relationships: "继承与元数据" -ui.reference.remarks: "备注" -ui.reference.returns: "返回值" -ui.reference.structs: "结构体" -ui.reference.typeParameters: "类型参数" -ui.reference.value: "值" -ui.reference.values: "值" -ui.search.close: "关闭搜索" -ui.search.empty: "没有找到与“{query}”相关的结果。" -ui.search.hint: "搜索教程、概念、示例和 API 参考。" -ui.search.loading: "正在加载搜索…" -ui.search.more: "显示更多结果" -ui.search.pending: "正在搜索…" -ui.search.placeholder: "输入搜索内容" -ui.search.resultCount: "结果:{count}" -ui.search.title: "搜索文档" -ui.search.unavailable: "搜索暂不可用,可直接打开下方页面。" +ui.navigation.toggle: '切换导航' +ui.outline.title: '本页导读' +ui.reference.assembly: '程序集' +ui.reference.classes: '类' +ui.reference.constructors: '构造函数' +ui.reference.declaration: 'C# 类型声明' +ui.reference.delegates: '委托' +ui.reference.derived: '派生类型' +ui.reference.enums: '枚举' +ui.reference.events: '事件' +ui.reference.examples: '示例' +ui.reference.exceptions: '异常' +ui.reference.extensionMethods: '扩展方法' +ui.reference.fields: '字段' +ui.reference.implementations: '显式接口实现' +ui.reference.implements: '实现' +ui.reference.inheritance: '继承' +ui.reference.inheritedMembers: '继承的成员' +ui.reference.interfaces: '接口' +ui.reference.metadata: '类型元数据' +ui.reference.methods: '方法' +ui.reference.namespace: '命名空间' +ui.reference.open: '打开 {name} 的参考文档' +ui.reference.operators: '运算符' +ui.reference.parameters: '参数' +ui.reference.properties: '属性' +ui.reference.related: '另请参阅' +ui.reference.relationships: '继承与元数据' +ui.reference.remarks: '备注' +ui.reference.returns: '返回值' +ui.reference.structs: '结构体' +ui.reference.typeParameters: '类型参数' +ui.reference.value: '值' +ui.reference.values: '值' +ui.search.close: '关闭搜索' +ui.search.empty: '没有找到与“{query}”相关的结果。' +ui.search.hint: '搜索教程、概念、示例和 API 参考。' +ui.search.loading: '正在加载搜索…' +ui.search.more: '显示更多结果' +ui.search.pending: '正在搜索…' +ui.search.placeholder: '输入搜索内容' +ui.search.resultCount: '结果:{count}' +ui.search.title: '搜索文档' +ui.search.unavailable: '搜索暂不可用,可直接打开下方页面。' diff --git a/documents/locales/zh-CN/translation.md b/documents/locales/zh-CN/translation.md index a79a4251..29908c60 100644 --- a/documents/locales/zh-CN/translation.md +++ b/documents/locales/zh-CN/translation.md @@ -2,7 +2,7 @@ ## 资源与结构 -[英文资源字典](../en-US/strings.yml)是唯一原文;项目约定见[文档维护指南](../../authoring.md)。开始新译本时,将英文文件完整复制为本目录的 `strings.yml`,保留首行 `### YamlMime:Resources`,使用 UTF-8 编码。后续更新应对照英文变更修订现有译文,不要重新覆盖整个文件。本文件 `translation.md` 永久保留,不发布到网站。 +[英文资源字典](../en-US/strings.yml)是唯一原文;项目约定见[文档维护指南](../../maintenance.md)。开始新译本时,将英文文件完整复制为本目录的 `strings.yml`,保留首行 `### YamlMime:Resources`,使用 UTF-8 编码。后续更新应对照英文变更修订现有译文,不要重新覆盖整个文件。本文件 `translation.md` 永久保留,不发布到网站。 导航、章节顺序、锚点、链接、格式、代码和图片都在 `locales/` 外统一维护。不要在语言目录内新增文章、TOC、模板、脚本或配置。 @@ -65,36 +65,36 @@ docfx serve documents/_site --hostname 127.0.0.1 --port 8080 ## 术语 -| 英文 | 约定译法或处理 | -| --- | --- | -| rendering hardware interface / RHI | 渲染硬件接口(RHI);之后可直接使用 RHI | -| graphics context | 图形上下文 | -| command queue | 命令队列 | -| command buffer | 命令缓冲区 | -| command recording | 命令录制 | -| submit / submission | 提交/提交操作;与 GPU 执行区分 | -| resource | 资源 | -| resource usage | 资源用途 | -| resource ownership / lifetime | 资源所有权/生命周期 | -| buffer | 缓冲区;标识符 `Buffer` 保持原样 | -| texture | 纹理 | -| heap | 堆 | -| view | 视图;区分资源视图与 UI 控件 | -| render pass | 渲染通道 | -| render target | 渲染目标 | -| color attachment | 颜色附件 | -| depth/stencil | 深度/模板 | -| pipeline | 管线;按上下文使用图形管线或计算管线 | -| shader / entry point | 着色器/入口点 | -| vertex / fragment | 顶点/片元 | -| rasterization | 光栅化 | -| viewport / scissor | 视口/裁剪区域 | -| swap chain / presentation | 交换链/呈现 | -| surface(呈现语境) | 原生呈现目标;`Surface` 标识符不译 | -| drawable | 当前帧的输出纹理;`Drawable` 标识符不译,不一律称为交换链图像 | -| framebuffer | 帧缓冲区;尺寸以原文规定的像素单位表述 | -| barrier / timeline | 屏障/时间线 | -| bindless | 无绑定;保留 API 标识符 | -| upload | 上传 | -| download / readback | GPU 数据语境使用“回读”;下载文件时使用“下载” | -| undefined | 未定义;不能改写为某个具体默认结果 | +| 英文 | 约定译法或处理 | +| ---------------------------------- | ------------------------------------------------------------- | +| rendering hardware interface / RHI | 渲染硬件接口(RHI);之后可直接使用 RHI | +| graphics context | 图形上下文 | +| command queue | 命令队列 | +| command buffer | 命令缓冲区 | +| command recording | 命令录制 | +| submit / submission | 提交/提交操作;与 GPU 执行区分 | +| resource | 资源 | +| resource usage | 资源用途 | +| resource ownership / lifetime | 资源所有权/生命周期 | +| buffer | 缓冲区;标识符 `Buffer` 保持原样 | +| texture | 纹理 | +| heap | 堆 | +| view | 视图;区分资源视图与 UI 控件 | +| render pass | 渲染通道 | +| render target | 渲染目标 | +| color attachment | 颜色附件 | +| depth/stencil | 深度/模板 | +| pipeline | 管线;按上下文使用图形管线或计算管线 | +| shader / entry point | 着色器/入口点 | +| vertex / fragment | 顶点/片元 | +| rasterization | 光栅化 | +| viewport / scissor | 视口/裁剪区域 | +| swap chain / presentation | 交换链/呈现 | +| surface(呈现语境) | 原生呈现目标;`Surface` 标识符不译 | +| drawable | 当前帧的输出纹理;`Drawable` 标识符不译,不一律称为交换链图像 | +| framebuffer | 帧缓冲区;尺寸以原文规定的像素单位表述 | +| barrier / timeline | 屏障/时间线 | +| bindless | 无绑定;保留 API 标识符 | +| upload | 上传 | +| download / readback | GPU 数据语境使用“回读”;下载文件时使用“下载” | +| undefined | 未定义;不能改写为某个具体默认结果 | diff --git a/documents/locales/zh-TW/strings.yml b/documents/locales/zh-TW/strings.yml index 988cde82..68619138 100644 --- a/documents/locales/zh-TW/strings.yml +++ b/documents/locales/zh-TW/strings.yml @@ -1,593 +1,593 @@ ### YamlMime:Resources -concepts.execution.context.description: "{graphicsContext} 透過特定後端連接應用程式與 GPU 裝置,並提供圖形、計算與傳輸佇列。一起使用的資源必須屬於同一上下文;緩衝區、紋理、著色器、管線及其控制代碼不能跨上下文繫結。" -concepts.execution.context.details: "{capabilities} 提供裝置名稱與支援的功能。建立光線追蹤或網格著色所需的資源前,分別透過 {rayTracingSupported} 與 {meshShadingSupported} 確認支援情況。{link}與{detail}範例展示了初始化時的檢查方式。" -concepts.execution.context.details.detail: "網格著色" -concepts.execution.context.details.link: "光線追蹤" -concepts.execution.context.title: "圖形上下文" -concepts.execution.description: "GPU 工作從 CPU 端開始準備:應用程式建立資源,記錄使用這些資源的命令,再提交到佇列。提交後,CPU 可以繼續處理其他工作,同時由 GPU 執行命令。相關資源必須保留到 GPU 執行結束。" -concepts.execution.ownership.description: "所有權決定由誰釋放物件,GPU 完成狀態決定何時可以釋放。即使仍保留物件的 C# 參考,呼叫 {dispose} 也會釋放其原生資源。提交命令不會將資源所有權轉交給佇列。" -concepts.execution.ownership.details: "結束程式時,先停止提交新工作,並等待所有相關佇列完成最後一次資源存取。接著釋放應用程式資源,最後釋放上下文。上下文會釋放自身的佇列與內部輔助物件,因此這一步必須在應用程式工作全部完成後進行。" -concepts.execution.ownership.guidance: "渲染期間,若準備覆寫資料或替換資源,就應追蹤仍在使用它們的工作。等待這些存取完成後,再修改資料或釋放儲存空間。檢視與底層資源如何遵循這個生命週期規則,見{link}。" -concepts.execution.ownership.guidance.link: "資源管理" -concepts.execution.ownership.table.applicationResources.object: "應用程式建立的資源" -concepts.execution.ownership.table.applicationResources.ownership: "最後一次 GPU 使用完成後,由應用程式釋放。" -concepts.execution.ownership.table.commandBuffers.object: "借用的命令緩衝區" -concepts.execution.ownership.table.commandBuffers.ownership: "由佇列管理和回收。" -concepts.execution.ownership.table.headings.object: "物件" -concepts.execution.ownership.table.headings.ownership: "釋放責任" -concepts.execution.ownership.table.queues.object: "圖形上下文佇列與其時間線" -concepts.execution.ownership.table.queues.ownership: "由上下文和佇列管理。" -concepts.execution.ownership.table.swapChainDrawable.ownership: "由交換鏈管理。" -concepts.execution.ownership.title: "所有權與生命週期" -concepts.execution.pipelines.description: "圖形管線規定繪製所用的著色器、頂點輸入佈局、圖元組裝方式、附件格式和渲染狀態。繫結頂點、索引或常數資料之前,須先選擇管線;管線宣告的附件格式與取樣數也必須與渲染通道一致。" -concepts.execution.pipelines.details: "計算管線選擇分派所執行的著色器進入點。在圖形渲染通道之外,先繫結管線及其常數,再執行分派。" -concepts.execution.pipelines.guidance: "{link}給出了完整的圖形命令順序。{detail}則先執行計算分派,再透過圖形通道顯示結果。" -concepts.execution.pipelines.guidance.detail: "計算範例" -concepts.execution.pipelines.guidance.link: "三角形的渲染回呼" -concepts.execution.pipelines.title: "管線狀態" -concepts.execution.queues.description: "一個影格同時包含繪製、計算與複製時,通常從 {graphicsQueue} 開始。將彼此相依的操作放在同一佇列,能簡化順序管理。" -concepts.execution.queues.details: "不同佇列可分別接收獨立的工作負載,但未必對應獨立的硬體引擎。若工作能從重疊執行中受益,再考慮增加佇列。當一個佇列使用另一個佇列產生的資料時,需要在兩次提交之間建立明確的相依關係。" -concepts.execution.queues.guidance: "即使位於同一佇列,彼此相依的操作也可能需要屏障或紋理轉換,讓後續存取讀到先前寫入的結果。這種記憶體相依關係與提交順序不同,具體指定方式見{link}。" -concepts.execution.queues.guidance.link: "同步" -concepts.execution.queues.table.computeQueue.workToRecord: "計算分派與相容的傳輸工作,不包含圖形渲染通道。" -concepts.execution.queues.table.graphicsQueue.workToRecord: "渲染通道、繪製、計算與傳輸操作。" -concepts.execution.queues.table.headings.queue: "佇列" -concepts.execution.queues.table.headings.workToRecord: "支援的工作" -concepts.execution.queues.table.transferQueue.workToRecord: "上傳、回讀與複製工作,不包含繪圖或計算分派。" -concepts.execution.queues.title: "佇列選擇" -concepts.execution.recording.context: "佇列會回收已完成的命令緩衝區以供重複使用。每次記錄時,透過 {queueCommandBuffer} 取得緩衝區,同一時間只由一個執行緒記錄,而且只提交一次。提交後交由佇列管理,不再修改、重複提交或自行釋放。" -concepts.execution.recording.description: "{queueCommandBuffer} 傳回的 {commandBuffer} 已開始記錄。完成操作及其相依關係的記錄後,呼叫一次 {submit},結束記錄並提交命令。傳回的 {timelineValue} 識別這次提交在佇列上的完成點。" -concepts.execution.recording.details: "三角形教學將一個影格記錄到 {commandBuffer} 後,按如下方式提交並等待完成:" -concepts.execution.recording.guidance: "記錄會建立命令序列,{submit} 則安排該序列執行。接著呼叫 {wait},CPU 執行緒便會等待這次提交完成。教學因此採用逐影格執行的流程:目前影格完成後,才開始下一個影格。" -concepts.execution.recording.title: "記錄與提交" -concepts.execution.title: "執行模型" -concepts.platforms.description: "呈現流程可以由應用程式管理,也可以交給 UI 渲染控制項。這決定了誰來取得目前影格的輸出紋理、記錄與提交命令,以及顯示渲染結果。" -concepts.platforms.frame.context: "在通道內繫結管線並記錄繪製命令,處理程式返回前須結束通道。控制項負責提交命令與呈現結果;處理程式不可自行提交命令緩衝區,也不可釋放傳入的命令緩衝區或輸出紋理。若改變了輸出紋理的佈局,返回前須恢復為 {colorAttachment},讓控制項能完成最後的轉換。" -concepts.platforms.frame.description: "各控制項實作 {iZenithView} 介面。應用程式設定 {graphicsContext},在 {updateRequested} 中更新場景,並在 {renderRequested} 中透過傳入的 {renderEventArgs} 記錄命令。" -concepts.platforms.frame.details: "每個影格中,控制項會取得輸出紋理與命令緩衝區,將輸出紋理轉換為 {colorAttachment},再呼叫更新和渲染處理程式。之後,控制項提交已記錄的工作,並透過對應框架的呈現機制顯示影像。" -concepts.platforms.frame.guidance: "先在檔案中加入 {usingZenithNET}。假定名為 {view} 的 {iZenithView} 執行個體已初始化,且已設定圖形上下文,可註冊以下處理程式來清除其輸出紋理:" -concepts.platforms.frame.notes: "初始轉換使用 {undefined},允許丟棄先前影像的內容。因此,每個影格都應重新繪製或清除整張影像。需要累積或快取的渲染結果,可儲存在應用程式擁有的紋理中,再將該紋理繪製到控制項的輸出紋理上。" -concepts.platforms.frame.reference: "{zenithViewHelperDrawableFormat} 提供這些整合使用的預設色彩格式。" -concepts.platforms.frame.title: "透過 UI 控制項渲染" -concepts.platforms.integration.context: "WinForms、WPF 與 Windows 版 WinUI 整合在 Windows 上執行。使用 MAUI 時,安裝目標平台的工作負載,並透過 {useZenithView} 註冊控制項處理程式,具體見 {extensionsCs}。" -concepts.platforms.integration.description: "控制項共用事件介面,但呈現機制因框架而異:" -concepts.platforms.integration.details: "各實作將 GPU 影像送到 UI 的方式不同。點陣圖回讀先將像素複製到 CPU 記憶體,再顯示影像;共用紋理互通能省去這次 CPU 複製,但仍可能需要 GPU 複製與同步。選擇整合方式時,除了共用的 {renderRequested} 事件介面,也應考慮其呈現方式。" -concepts.platforms.integration.guidance: "透過 NuGet 加入所用 UI 框架的整合套件。Avalonia 對應的套件為 {avaloniaPackage}。" -concepts.platforms.integration.table.avalonia.integration: "Avalonia" -concepts.platforms.integration.table.avalonia.presentation: "渲染到紋理後,將像素回讀到 {writeableBitmap},實作見 {zenithViewCs} 和 {surfaceCs}。" -concepts.platforms.integration.table.headings.integration: "整合" -concepts.platforms.integration.table.headings.presentation: "呈現機制" -concepts.platforms.integration.table.maui.integration: ".NET MAUI" -concepts.platforms.integration.table.maui.presentation: "Android、iOS 和 Mac Catalyst 使用原生呈現目標;Windows 使用共用紋理合成,具體見{link}。" -concepts.platforms.integration.table.maui.presentation.link: "平台實作" -concepts.platforms.integration.table.uno.integration: "Uno 路徑" -concepts.platforms.integration.table.uno.presentation: "將像素回讀到 {writeableBitmap},實作見 {zenithViewUnoCs}。" -concepts.platforms.integration.table.winForms.integration: "WinForms" -concepts.platforms.integration.table.winForms.presentation: "為控制項的 {hWND} 建立 Zenith.NET 交換鏈,實作見 {zenithViewCs}。" -concepts.platforms.integration.table.winUI.integration: "Windows 上的 WinUI" -concepts.platforms.integration.table.winUI.presentation: "渲染到匯入的共用 Direct3D 11 紋理,再複製到與 {swapChainPanel} 連線的合成交換鏈,具體見 {zenithViewWinUICs}。" -concepts.platforms.integration.table.wpf.integration: "WPF" -concepts.platforms.integration.table.wpf.presentation: "匯入共用 Direct3D 11 紋理,再經 Direct3D 互通複製到由 {d3DImage} 顯示的表面,具體見 {surfaceCs}。" -concepts.platforms.integration.title: "框架與呈現路徑" -concepts.platforms.lifecycle.context: "建立配套附件時,使用渲染事件傳入的輸出紋理的 {descWidth}、{descHeight}、{descFormat} 與 {descSampleCount}。該紋理提供渲染目標的實際尺寸,不應依控制項的版面配置尺寸或顯示縮放比例推算。" -concepts.platforms.lifecycle.description: "交換鏈使用以像素計量的畫面緩衝區寬度與高度。啟用顯示縮放時,這些值可能不同於視窗的邏輯尺寸。任一尺寸為零時,暫停渲染與交換鏈尺寸調整。每個影格重新取得 {swapChainDrawable}:這張紋理由交換鏈管理,可能在呈現或調整大小後被替換。" -concepts.platforms.lifecycle.details: "畫面緩衝區尺寸改變時,先等待 GPU 完成對舊影像的存取,再呼叫 {swapChainResize}。替換原生呈現目標時,也應先等待這些存取結束,再將新的目標描述與控制代碼傳給 {swapChainRefresh}。結束程式時,先釋放交換鏈,再銷毀其原生呈現目標。" -concepts.platforms.lifecycle.guidance: "應用程式的深度紋理或離屏紋理若隨視窗尺寸改變,就需要在調整大小時重建,並更新包含其控制代碼的常數。只要附件格式與取樣數仍然相符,管線就可以繼續使用。{link}展示了如何調整紋理尺寸並保留管線。" -concepts.platforms.lifecycle.guidance.link: "旋轉立方體渲染器" -concepts.platforms.lifecycle.title: "交換鏈尺寸與生命週期" -concepts.platforms.ownership.description: "應用程式擁有所設定的上下文及其渲染資源,控制項擁有呈現資源。檢視的 {graphicsContext} 改變後,排程程式會為新上下文重建控制項資源。應用程式也須為該上下文重建自己的管線、緩衝區與紋理。" -concepts.platforms.ownership.details: "替換渲染資源前,先停止檢視的影格活動,並等待使用這些資源的 GPU 工作完成,再釋放舊資源或上下文。移除檢視後,所設定的上下文仍由應用程式負責釋放。" -concepts.platforms.ownership.guidance: "共用的 {frameSchedulerCs} 透過檢視的 UI 排程器執行影格處理程式。處理程式應專注於場景資料更新與命令記錄,其中耗時的 CPU 工作也會延遲介面回應。" -concepts.platforms.ownership.title: "應用程式與控制項的責任" -concepts.platforms.surface.description: "{link}使用 Silk.NET 建立視窗並處理事件。Zenith.NET 透過 {surface} 描述取得原生視窗控制代碼與尺寸,再據此建立 {swapChain}。作業系統視窗仍由應用程式負責管理。" -concepts.platforms.surface.description.link: "三角形教學" -concepts.platforms.surface.details: "原生控制代碼必須與所選後端匹配:" -concepts.platforms.surface.guidance: "{appCs} 中的範例宿主支援 Windows、macOS 與 X11。Linux 視窗提供 Xlib 控制代碼,因此在 Wayland 工作階段中需要 XWayland。原生 Wayland 應用程式則透過 {surfaceWayland} 提供顯示與表面的控制代碼。" -concepts.platforms.surface.table.android.backend: "Android 上的 Vulkan。" -concepts.platforms.surface.table.apple.backend: "Apple 平台上的 Metal。" -concepts.platforms.surface.table.headings.backend: "後端與平台" -concepts.platforms.surface.table.headings.factory: "呈現目標工廠方法" -concepts.platforms.surface.table.headings.handles: "宿主程式提供的控制代碼" -concepts.platforms.surface.table.wayland.backend: "具有原生 Wayland 宿主程式的 Vulkan。" -concepts.platforms.surface.table.wayland.handles: "Wayland 顯示與表面" -concepts.platforms.surface.table.win32.backend: "Windows 上的 DirectX 12 或 Vulkan。" -concepts.platforms.surface.table.xlib.backend: "Linux 上帶有 X11 或 XWayland 的 Vulkan。" -concepts.platforms.surface.table.xlib.handles: "X11 顯示與視窗" -concepts.platforms.surface.title: "原生呈現目標" -concepts.platforms.title: "平台整合" -concepts.resources.allocation.context: "放置在堆積中的資源,在整個生命週期內都依賴堆積的儲存空間。最後一次 GPU 使用完成後,應先釋放資源,再釋放堆積。" -concepts.resources.allocation.description: "應用程式需要自行管理記憶體配置時,可以使用 {heap}。堆積為資源提供儲存空間,應用程式選擇明確的位元組位移來放置資源,並記錄各區域的使用情況。" -concepts.resources.allocation.details: "對每個資源,使用建立時所需的緩衝區或紋理描述呼叫 {contextGetSizeAndAlignment}。依傳回的大小預留空間,起始位移須為傳回對齊值的整數倍,而且整個區域須位於堆積內,不與其他仍有效的配置重疊。紋理可能包含後端特有的填充,因此不能只依像素數量與每像素位元組數計算配置大小。" -concepts.resources.allocation.guidance: "放置在堆積中的緩衝區,必須使用與堆積相同的駐留設定。紋理儲存使用 GPU 專用堆積。" -concepts.resources.allocation.title: "堆積配置" -concepts.resources.bufferUsages.table.constant.role: "透過常數緩衝區繫結讀取的著色器參數。" -concepts.resources.bufferUsages.table.headings.role: "作用" -concepts.resources.bufferUsages.table.headings.usage: "用途" -concepts.resources.bufferUsages.table.index.role: "索引繪圖所使用的索引。" -concepts.resources.bufferUsages.table.indirect.role: "間接繪製或分派命令讀取的引數。" -concepts.resources.bufferUsages.table.none.role: "未宣告任何緩衝區用途旗標。" -concepts.resources.bufferUsages.table.storageReadOnly.role: "透過唯讀著色器繫結存取的緩衝區資料。" -concepts.resources.bufferUsages.table.storageReadWrite.role: "透過讀寫著色器繫結存取的緩衝區資料。" -concepts.resources.bufferUsages.table.transferDst.role: "GPU 複製作業的目的地儲存空間。" -concepts.resources.bufferUsages.table.transferSrc.role: "GPU 複製作業的來源資料。" -concepts.resources.bufferUsages.table.vertex.role: "供繪製命令讀取的頂點屬性。" -concepts.resources.bufferUsages.title: "緩衝區用途" -concepts.resources.description: "資源描述規定應用程式如何使用其儲存空間。例如,一張紋理若要作為渲染目標、供著色器取樣,並將內容複製回 CPU,就需要宣告這三種操作的用途。記憶體放置決定 CPU 的存取方式,同步與生命週期管理則決定何時可以存取資料或釋放儲存空間。" -concepts.resources.memory.context: "對於 CPU 可存取的緩衝區,{map} 提供 CPU 讀寫資料所用的位址。映射與 {unmap} 都不會等待 GPU 工作。CPU 讀取 GPU 寫入的結果前,應用程式須先等待寫入完成;修改同一塊記憶體前,也須等待 GPU 對這些位元組的存取結束。" -concepts.resources.memory.description: "{bufferDesc} 的 {residency} 欄位指定 CPU 對所配置記憶體的預期存取方式:" -concepts.resources.memory.details: "駐留設定表達 CPU 的存取需求,即使 CPU 與 GPU 共用實體記憶體也同樣適用。三角形教學使用 {cpuWriteOnly} 直接初始化小型頂點緩衝區。較大的靜態幾何資料,則可考慮上傳到 GPU 專用儲存空間。" -concepts.resources.memory.guidance: "透過上下文直接建立的紋理使用 GPU 儲存空間,因此 {textureDesc} 沒有駐留欄位。應用程式透過上傳與回讀,在紋理與 CPU 記憶體之間交換資料。" -concepts.resources.memory.table.cpuReadOnly.cPUAccess: "唯讀" -concepts.resources.memory.table.cpuReadOnly.typicalRole: "GPU 產生的回讀資料" -concepts.resources.memory.table.cpuWriteOnly.cPUAccess: "唯寫" -concepts.resources.memory.table.cpuWriteOnly.typicalRole: "CPU 提供或更新的資料" -concepts.resources.memory.table.gpuOnly.cPUAccess: "無" -concepts.resources.memory.table.gpuOnly.typicalRole: "靜態幾何體與 GPU 工作資料" -concepts.resources.memory.table.headings.cPUAccess: "預期 CPU 存取" -concepts.resources.memory.table.headings.residency: "記憶體駐留" -concepts.resources.memory.table.headings.typicalRole: "典型用途" -concepts.resources.memory.title: "CPU 存取與記憶體放置" -concepts.resources.textureUsages.description: "傳輸旗標宣告資源在 GPU 複製中作為來源或目標。CPU 能否直接存取這塊儲存空間,則由記憶體放置方式決定。" -concepts.resources.textureUsages.details: "用途旗標宣告紋理可以發揮的作用。在這些作用之間切換時,需要對應的{link};所選裝置也必須支援以該紋理格式執行所宣告的操作。" -concepts.resources.textureUsages.details.link: "佈局與同步" -concepts.resources.textureUsages.table.colorAttachment.role: "渲染通道中的色彩附件。" -concepts.resources.textureUsages.table.depthStencilAttachment.role: "渲染通道中的深度/樣板附件。" -concepts.resources.textureUsages.table.headings.role: "作用" -concepts.resources.textureUsages.table.headings.usage: "用途" -concepts.resources.textureUsages.table.none.role: "未宣告任何紋理用途旗標。" -concepts.resources.textureUsages.table.sampled.role: "透過取樣紋理繫結讀取的紋理資料。" -concepts.resources.textureUsages.table.storage.role: "透過儲存紋理繫結供著色器讀取或寫入的紋理資料。" -concepts.resources.textureUsages.table.transferDst.role: "GPU 複製作業的目的地影像儲存空間。" -concepts.resources.textureUsages.table.transferSrc.role: "GPU 複製作業的來源影像資料。" -concepts.resources.textureUsages.title: "紋理用途" -concepts.resources.title: "資源管理" -concepts.resources.transfers.context: "回讀先將 GPU 資料複製到內部回讀空間。程式庫回收已完成的命令緩衝區時,再將資料複製到指定的 CPU 目標。對這次回讀提交的完成值呼叫 {wait},可以完成這兩個步驟。在呼叫返回前,目標記憶體須保持已配置狀態,受控記憶體須保持固定。" -concepts.resources.transfers.description: "上傳將 CPU 資料複製到 GPU 資源,回讀則將資源資料複製到 CPU 記憶體。緩衝區與紋理上的這些方法會在傳輸完成後返回:" -concepts.resources.transfers.details: "呼叫這些方法前,先處理與其他佇列存取之間的衝突。方法內部的等待只涵蓋自身傳輸,不會建立與其他佇列的相依關係。直接透過映射記憶體複製時,則完全由呼叫端負責等待會產生衝突的 GPU 存取。" -concepts.resources.transfers.guidance: "若要將傳輸與其他 GPU 工作一起提交,可透過 {commandBufferUpload} 或 {commandBufferDownload} 記錄。上傳來源與回讀目標的記憶體生命週期要求不同:" -concepts.resources.transfers.item: "上傳呼叫期間,程式庫會將來源資料複製到內部的臨時上傳空間,也就是暫存記憶體。GPU 隨後從這塊空間讀取,因此應用程式的來源指標只需保持有效到呼叫返回。" -concepts.resources.transfers.notes: "紋理傳輸中的列跨距是 CPU 資料相鄰兩列之間的位元組距離;切片跨距則是相鄰深度切片之間的位元組距離。傳輸操作依這些值,在 CPU 資料與紋理的 GPU 儲存空間之間複製內容。GPU 完成與資料送達回讀目標為何是兩個步驟,見{link}。" -concepts.resources.transfers.notes.link: "同步" -concepts.resources.transfers.table.bufferDownload.transfer: "對於 {cpuReadOnly},直接從映射記憶體複製;否則向傳輸佇列提交回讀,並等待完成。" -concepts.resources.transfers.table.bufferUpload.transfer: "對於 {cpuWriteOnly},直接複製到映射記憶體;否則向傳輸佇列提交上傳,並等待完成。" -concepts.resources.transfers.table.headings.method: "方法" -concepts.resources.transfers.table.headings.transfer: "傳輸行為" -concepts.resources.transfers.table.textureTransfers.method: "{textureUpload} / {textureDownload}" -concepts.resources.transfers.table.textureTransfers.transfer: "將複製及其紋理轉換提交到圖形佇列,並等待完成。操作結束後,所選子資源處於指定的最終佈局。" -concepts.resources.transfers.title: "立即傳輸與命令記錄" -concepts.resources.usages.description: "{bufferUsages} 與 {textureUsages} 是宣告資源用途的旗標列舉,分別設定於 {bufferDescUsages} 與 {textureDescUsages}。資源需要多種用途時,可透過 {value} 組合對應的成員。" -concepts.resources.usages.title: "資源用途" -concepts.resources.views.description: "{bufferView} 描述緩衝區的一塊區域及其資料解讀方式。{textureView} 選擇子資源範圍,以及相容的紋理型別與格式。兩者都參考既有儲存空間,並遵循建立時宣告的用途。檢視範圍用來描述存取範圍,各後端並不因此提供一致的著色器邊界檢查。" -concepts.resources.views.details: "資源本身的控制代碼提供預設檢視。需要其他區域或相容的解讀方式時,再建立獨立檢視。檢視及其底層資源都必須保留到 GPU 使用結束;僅持有資源控制代碼,無法維持任一物件的存活。替換其中任一物件時,還須更新包含舊{link}的常數。" -concepts.resources.views.details.link: "資源控制代碼" -concepts.resources.views.title: "檢視與底層資源" -concepts.shaders.binding.context: "計算範例將 {inputTextureSampledHandle} 寫入 {input},將 {outputTextureStorageHandle} 寫入 {output}。在 Slang 中,{descriptorHandle} 的型別引數規定了著色器存取資源的方式:" -concepts.shaders.binding.description: "{setConstantBuffer} 選擇既有緩衝區與位元組位移,目前管線從該位置讀取常數。著色器使用這些參數前,先將資料上傳到對應的儲存空間。如果先前提交的 GPU 工作仍在讀取相同位元組,須等待該工作完成後再更新。" -concepts.shaders.binding.details: "準備好命令緩衝區、計算管線、已填入資料的常數緩衝區及執行緒群組數量後,依以下順序記錄分派。常數緩衝區會繫結到目前管線,因此必須先選擇管線:" -concepts.shaders.binding.guidance: "這裡,{commandBuffer} 使用 {computePipeline} 及 {constantBuffer} 中的參數記錄分派。緩衝區需要宣告 {bufferUsagesConstant} 用途,位移 0 選擇其起始位置。若多筆常數記錄共用緩衝區,每筆記錄的起始位移還須符合後端繫結的對齊要求,這與記錄內部的欄位佈局是兩項不同要求。" -concepts.shaders.binding.notes: "{resourceHandle} 包含兩個 32 位元欄位,含義由後端解釋,其值只在建立資源的上下文中有效。" -concepts.shaders.binding.reference: "保留資源及用於取得控制代碼的檢視,直到著色器完成最後一次存取。替換紋理或檢視後,應更新仍含舊控制代碼的常數。相關所有權規則見{link}。" -concepts.shaders.binding.reference.link: "資源管理" -concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: "讀取著色器型別 {t} 的結構化元素" -concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: "讀寫著色器型別 {t} 的結構化元素" -concepts.shaders.binding.table.headings.access: "預期存取" -concepts.shaders.binding.table.headings.cHandle: "C# 控制代碼" -concepts.shaders.binding.table.headings.slangFieldType: "Slang 欄位型別" -concepts.shaders.binding.table.samplerHandle.access: "紋理取樣狀態" -concepts.shaders.binding.table.textureSampledHandle.access: "紋理讀取" -concepts.shaders.binding.table.textureStorageHandle.access: "儲存紋理的讀寫" -concepts.shaders.binding.title: "常數緩衝區與資源控制代碼" -concepts.shaders.compilation.description: "{zenithCompiler} 將指定的 Slang 進入點編譯為 {shaderDesc}。上下文的 {graphicsApi} 決定目標格式:DirectX 12 使用 DXIL,Metal 使用 Metal 程式庫,Vulkan 使用 SPIR-V。" -concepts.shaders.compilation.details: "建立名為 {context} 的圖形上下文後,可以編譯已複製到執行檔所在目錄的三角形著色器:" -concepts.shaders.compilation.guidance: "進入點名稱 {vSMain} 必須與著色器檔案中的函式宣告一致。在初始化階段編譯著色器並建立管線,渲染期間重複使用管線。管線建立完成後,即可釋放著色器物件,具體見{link}。" -concepts.shaders.compilation.guidance.link: "第一個三角形" -concepts.shaders.compilation.title: "著色器編譯" -concepts.shaders.description: "C# 與 Slang 宣告必須約定一致的資料位置與存取方式。頂點輸入佈局描述頂點屬性,著色器緩衝區宣告描述參數與陣列,資源控制代碼則識別著色器使用的資源。" -concepts.shaders.dispatch.description: "{dispatch} 指定要執行多少個執行緒群組。計算範例宣告 {numthreads},因此每組包含 16 × 16 個執行緒。將影像寬度與高度分別除以 16,並向上取整,即可覆蓋整張影像:17 × 19 的影像需要 2 × 2 組。著色器檢查每個執行緒的座標,並跳過位於影像範圍以外的執行緒。" -concepts.shaders.dispatch.details: "{shaderDescThreadGroupSize} 提供宣告的群組大小,可用來計算傳給 {dispatch} 的群組數量。完整計算過程見 {computeShaderRendererCs}。分派完成後,存取輸出影像時仍須符合{link}中說明的要求。" -concepts.shaders.dispatch.details.link: "同步" -concepts.shaders.dispatch.title: "執行緒群組" -concepts.shaders.layout.context: "{link}透過影像尺寸與兩個紋理控制代碼展示這種排列。各欄位的起始位置由明確位移指定。以下宣告使用 {systemRuntimeInteropServices} 與 {zenithNET} 命名空間:" -concepts.shaders.layout.context.link: "計算範例的 C# 常數" -concepts.shaders.layout.description: "對於頂點輸入,{inputLayout} 描述各屬性的格式、位移與語義,以及相鄰頂點之間的跨距。三角形先儲存 {float3} 位置,再儲存 {float4} 色彩:色彩的位元組位移為 12,每個頂點占 28 位元組。{inputLayoutAdd} 根據元素格式計算這個緊密排列的佈局。若 C# 結構包含填充,就需要在位移與跨距中計入這些空間。" -concepts.shaders.layout.details: "常數緩衝區儲存著色器參數,結構化緩衝區儲存指定型別的元素陣列。它們的佈局由 Slang 宣告決定,不使用 {inputLayout}。C# 欄位位移、元素大小與填充,必須符合編譯後的著色器佈局。即使某個 C# 型別是非受控型別,可以直接依位元組複製,其記憶體排列也未必符合著色器要求;例如,頂點中緊密排列的 {float3},在著色器緩衝區中可能需要不同的對齊方式。" -concepts.shaders.layout.guidance: "著色器參數除了普通數值,也可以包含資源控制代碼。控制代碼識別的是既有儲存空間,因此將它複製到常數緩衝區,不會複製資源內容。" -concepts.shaders.layout.notes: "{computeShaderSlang} 中對應的宣告為:" -concepts.shaders.layout.reference: "兩個尺寸值占用前 8 位元組,後面是兩個各占 8 位元組的控制代碼。C# 範例為整筆記錄預留 256 位元組。其他記錄的大小,應依各自欄位以及所需的佈局與對齊方式決定。" -concepts.shaders.layout.title: "資料佈局" -concepts.shaders.matrices.description: "編譯器採用列優先的矩陣儲存方式,使同一列的元素連續排列。{link}在位移 0、64 和 128 處儲存三個 {matrix4x4} 值,其{detail}按模型、檢視和投影順序執行 {mulVectorMatrix}。" -concepts.shaders.matrices.description.detail: "著色器" -concepts.shaders.matrices.description.link: "旋轉立方體渲染器" -concepts.shaders.matrices.details: "儲存順序決定矩陣元素在記憶體中的排列,乘法順序決定變換。C# 與 Slang 應採用相互配合的約定。" -concepts.shaders.matrices.title: "矩陣約定" -concepts.shaders.title: "著色器資料與繫結" -concepts.synchronization.backends.description: "DirectX 12 與 Vulkan 將紋理轉換記錄為佈局與存取狀態的變更。在 Zenith.NET 的 Metal 後端中,{transition} 沒有對應的 GPU 操作。Metal 後端將命令組織成渲染與計算編碼器,並在編碼器結束時插入可見性屏障。同一編碼器內彼此相依的操作,例如連續的計算分派,透過明確呼叫 {barrier} 協調。" -concepts.synchronization.backends.details: "{link}開始圖形渲染通道時,會結束計算編碼器,讓後續圖形工作能讀取計算輸出。連續兩次計算分派仍位於同一編碼器內,即使中間記錄了紋理轉換,也需要屏障來處理相依關係。因此,跨後端使用的命令序列既要考慮紋理佈局,也要處理存取之間的相依關係。" -concepts.synchronization.backends.details.link: "計算範例" -concepts.synchronization.backends.title: "後端行為" -concepts.synchronization.barriers.context: "選擇涵蓋相關存取,且目前佇列支援的階段。{barrierStagesAll} 包含所有支援的階段;若相依關係只涉及其中一部分,可選擇較小的範圍。" -concepts.synchronization.barriers.description: "假設同一個命令緩衝區內有兩次計算分派,第一次寫入模擬資料,第二次讀取這些資料。在兩次分派之間設定屏障,讓第二次分派讀到已完成的寫入結果。對於儲存緩衝區,這樣即可安排存取順序,不需要進行紋理佈局轉換:" -concepts.synchronization.barriers.details: "第一個引數指定產生資料的階段,第二個引數指定使用資料的階段。兩者共同描述兩次分派之間所需的執行順序與記憶體可見性。" -concepts.synchronization.barriers.guidance: "{link}在模擬步驟之間採用這個方式。每道屏障都位於產生資料的分派之後、使用資料的分派之前。" -concepts.synchronization.barriers.guidance.link: "FluidTank 模擬" -concepts.synchronization.barriers.title: "管線屏障" -concepts.synchronization.dependencies.description: "逐一確認每個資源有哪些存取涉及同一份資料。只要其中包含寫入,就必須維持所需的先後順序。兩次讀取本身沒有衝突,但仍需符合紋理佈局與呈現要求。CPU 更新資料或釋放資源前,也須等待 GPU 完成對該儲存空間的使用。" -concepts.synchronization.dependencies.details: "應根據操作執行的位置選擇機制:" -concepts.synchronization.dependencies.guidance: "一項工作可能同時需要多種同步機制。例如,紋理由另一個佇列產生時,除了提交相依關係,還需為下一次使用設定正確的佈局。這兩項操作本身都不需要阻塞 CPU;只有 CPU 要存取或釋放相關資料時,才需要在 CPU 端等待。" -concepts.synchronization.dependencies.table.cpuAccess.mechanism: "針對相關完成值呼叫 {wait}。" -concepts.synchronization.dependencies.table.cpuAccess.situation: "CPU 存取或資源釋放需要等待 GPU 完成" -concepts.synchronization.dependencies.table.crossQueue.mechanism: "將生產者的 {timelineValue} 傳給消費者的 {submit}。" -concepts.synchronization.dependencies.table.crossQueue.situation: "一個佇列使用另一個佇列產生的資料" -concepts.synchronization.dependencies.table.headings.mechanism: "機制" -concepts.synchronization.dependencies.table.headings.situation: "情況" -concepts.synchronization.dependencies.table.layoutChange.mechanism: "呼叫 {commandBufferTransition},指定先前佈局與目標佈局。" -concepts.synchronization.dependencies.table.layoutChange.situation: "紋理子資源變更其使用方式" -concepts.synchronization.dependencies.table.pipelineStages.mechanism: "呼叫 {commandBufferBarrier},指定產生資料和使用資料的階段。" -concepts.synchronization.dependencies.table.pipelineStages.situation: "命令串流中相依的 GPU 階段" -concepts.synchronization.dependencies.title: "存取相依關係" -concepts.synchronization.description: "同步確定多個操作存取共用資料的順序,並讓後續操作能讀到所需結果。在寫後讀相依關係中,寫入端稱為生產者,讀取端稱為消費者。屏障與紋理轉換協調 GPU 存取;時間線連接不同提交,並讓 CPU 等待 GPU 工作完成。" -concepts.synchronization.layouts.context: "現有內容可以丟棄時,可將先前佈局設為 {undefined},例如新建影像或即將完整清除的附件。若要保留內容以供載入、取樣或累積,則應使用前次存取時的佈局。" -concepts.synchronization.layouts.description: "紋理的用途旗標宣告允許的作用。{textureLayout} 描述命令序列中某個時點對子資源的存取方式,子資源由 mip 級別與陣列層識別。存取方式改變時,需要記錄轉換。例如,計算範例在 {storage} 佈局中寫入輸出紋理,再為圖形通道中的取樣做準備:" -concepts.synchronization.layouts.details: "這裡的 {outputTexture} 已宣告 {sampledStorage} 用途,所選子資源處於 {storage} 佈局。{default} 選擇 mip 級別 0 和陣列層 0,其他級別和層不受這次轉換影響。" -concepts.synchronization.layouts.guidance: "呼叫 {transition} 時,提供子資源上一次使用時的佈局。應用程式在記錄命令,以及在渲染階段之間傳遞紋理時,負責追蹤這個狀態。" -concepts.synchronization.layouts.title: "紋理佈局" -concepts.synchronization.readback.description: "{isCompleted} 回報 GPU 的完成狀態。透過命令記錄的回讀還需要一個步驟:將結果從內部回讀空間複製到應用程式的目標記憶體。" -concepts.synchronization.readback.details: "{commandBufferDownload} 記錄向內部回讀空間複製資料的 GPU 命令。提交完成後,程式庫在回收命令緩衝區時執行最後的 CPU 複製。對這次回讀提交的完成值呼叫 {wait},會等待 GPU 完成,並處理該佇列已完成的緩衝區,從而完成這兩個步驟。呼叫返回前,目標記憶體須保持已配置狀態,受控記憶體須保持固定。" -concepts.synchronization.readback.guidance: "只輪詢 {isCompleted} 不會執行最後的 CPU 複製;等待其他佇列,也不會回收回讀佇列中已完成的緩衝區。上傳與回讀何時使用直接記憶體存取或暫存空間,見{link}。" -concepts.synchronization.readback.guidance.link: "資源管理" -concepts.synchronization.readback.title: "回讀完成" -concepts.synchronization.reuse.description: "三角形教學在每個影格完成後才重複使用資料。若要讓影格重疊執行,應為每個尚未完成的影格準備獨立的可變儲存空間,並追蹤何時可以再次使用。修改資料前,須等待 GPU 完成對相關位元組的存取;釋放資源前,則須等待它的所有使用結束。" -concepts.synchronization.reuse.details: "調整大小與結束程式遵循相同順序:先停止新的資源存取,等待既有存取結束,再替換或釋放資源。呼叫 {swapChainResize} 或釋放資源、上下文前,須先完成上述等待。三角形教學已經逐影格等待,因此可以在回呼之間調整大小。" -concepts.synchronization.reuse.guidance: "{swapChainPresent} 在呈現後向圖形佇列發出訊號並等待。因此,即使移除明確的提交等待,三角形教學仍會在呈現時等待。獨立提交到其他佇列的工作,需要另外追蹤其完成狀態。" -concepts.synchronization.reuse.title: "資源重複使用" -concepts.synchronization.timelines.context: "CPU 若要在消費者完成後讀取結果、覆寫共用資料或釋放資源,須先等待這次提交完成:" -concepts.synchronization.timelines.description: "時間線用遞增值識別佇列進度。{submit} 傳回的 {timelineValue} 同時包含時間線和本次提交的值。不同時間線上的 {value} 數值不能直接比較。" -concepts.synchronization.timelines.details: "設 {producer} 與 {consumer} 是同一上下文中兩個佇列上已記錄的命令緩衝區,後者使用前者寫入的資料。提交時傳入以下相依關係:" -concepts.synchronization.timelines.guidance: "消費者所在的佇列會先等待傳入的完成值,再執行命令。CPU 不必呼叫 {producedWait},可以繼續處理其他工作。共用資源須保留到 {consumed} 完成,同時仍需記錄消費者存取所要求的紋理轉換。" -concepts.synchronization.timelines.notes: "{queueTimelineSignal} 傳回的值,同樣可以透過 {wait} 等待,也可以作為另一個佇列的相依條件。{signal} 將完成點排在先前已提交的工作之後,GPU 完成這些工作後就會到達該點。" -concepts.synchronization.timelines.title: "時間線與佇列相依關係" -concepts.synchronization.title: "同步" -home.actions.reference: "瀏覽 API" -home.actions.tutorial: "從三角形開始" -home.entries.description: "教學、範例與 API 參考" -home.entries.label: "文件分類" -home.entries.reference.action: "探索 API" -home.entries.reference.category: "參考" -home.entries.reference.description: "查閱 API 型別、成員與宣告" -home.entries.reference.title: "API 參考" -home.entries.samples.action: "瀏覽範例" -home.entries.samples.category: "範例" -home.entries.samples.description: "可直接執行的圖形與計算範例" -home.entries.samples.title: "範例" -home.entries.title: "文件" -home.entries.tutorial.action: "開始教學" -home.entries.tutorial.category: "教學" -home.entries.tutorial.description: "從空白專案開始,繪製第一個三角形" -home.entries.tutorial.title: "第一個三角形" -home.introduction.accent: "跨平台圖形應用" -home.introduction.description: "Zenith.NET 提供統一的圖形與計算 API,支援 DirectX、Metal 與 Vulkan" -home.introduction.title: "以 .NET 開發{lineBreak}{accent}" -home.meta.description: "透過 Zenith.NET 開發跨平台圖形與計算應用程式,以共用 API 使用 DirectX、Metal 與 Vulkan" -home.scene.description: "可互動的旋轉幾何體。拖動或使用方向鍵調整視角。" -home.scene.label: "幾何體顯示" -home.scene.surface: "表面" -home.scene.wireframe: "線框" -home.title: "適用於 .NET 的現代 RHI" -learning.concepts.description: "選擇資源用途、描述著色器資料與協調 GPU 執行" -learning.concepts.execution.description: "命令記錄、提交與資源生命週期" -learning.concepts.platforms.description: "原生呈現與 UI 渲染控制項" -learning.concepts.resources.description: "資源用途、記憶體放置與檢視" -learning.concepts.shaders.description: "C# 與 Slang 的資料佈局和繫結約定" -learning.concepts.synchronization.description: "相依關係、可見性與完成狀態" -learning.concepts.title: "核心概念" -learning.description: "初次使用 Zenith.NET,可以從三角形教學開始。完成後,再依需要查閱資源管理、著色器資料與同步等概念,或透過範例了解各種圖形技術的實作。" -learning.entries.samples.action: "瀏覽範例" -learning.entries.samples.description: "幾何體、計算、光線查詢與網格著色的 C# 和 Slang 實作" -learning.entries.tutorial.action: "開啟教學" -learning.entries.tutorial.description: "建立視窗並渲染三角形的主控台應用程式" -learning.meta.description: "Zenith.NET 程式設計模型的入門教學與概念說明" -learning.title: "學習" -reference.description: "資源、命令與平台整合的參考文件" -reference.entries.commands.description: "圖形、計算與傳輸命令" -reference.entries.commands.label: "記錄命令" -reference.entries.context.description: "為所選後端建立 GPU 資源" -reference.entries.context.label: "從這裡開始" -reference.meta.description: "Zenith.NET 的命名空間、型別與成員" -reference.navigation.core: "核心 API 參考" -reference.title: "API 參考" -samples.computeShader.description: "範例載入 {assetsTexturesShokoPng},透過一次計算分派將影像轉成灰階,再顯示輸出紋理。轉換只執行一次,後續影格顯示同一結果。渲染器展示了取樣紋理與可寫紋理的繫結、向上取整群組數量以覆蓋整張影像的計算方式,以及著色器中的影像邊界檢查。" -samples.computeShader.details: "{computeShaderRendererCs} · {computeShaderSlang}" -samples.computeShader.title: "計算著色器" -samples.cube.description: "旋轉立方體加入索引繪製、常數緩衝區中的模型、檢視和投影矩陣,以及深度測試。視窗調整大小時,會重建 {d32FloatS8UInt} 深度/樣板紋理。" -samples.cube.details: "{spinningCubeRendererCs} · {spinningCubeSlang}" -samples.cube.title: "旋轉立方體" -samples.description: "每個範例均由 C# 渲染器與 Slang 著色器組成,集中說明一項技術。完整的應用程式設定與渲染順序見{link}。" -samples.description.link: "第一個三角形" -samples.execution.description: "執行 {link} 專案,並從主控台選單選擇範例。" -samples.execution.description.link: "ZenithTutorials" -samples.execution.title: "執行範例" -samples.host.description: "{appCs} 初始化上下文、視窗和交換鏈。每個影格取得命令緩衝區,呼叫所選渲染器,提交命令並呈現結果。{iRendererCs} 規定渲染器的更新、渲染、調整大小和釋放操作。" -samples.host.details: "計算與光線追蹤渲染器產生離屏紋理。{texturePresenterCs} 與 {presentTextureSlang} 將這些紋理繪製到目前的輸出紋理,接著由共用宿主提交命令並呈現這個影格。" -samples.host.title: "宿主與呈現" -samples.indirectDrawing.description: "間接繪製透過索引繪製引數緩衝區,以及儲存各執行個體資料的結構化緩衝區,繪製多個立方體。CPU 提供繪製引數並更新變換。" -samples.indirectDrawing.details: "{indirectDrawingRendererCs} · {indirectDrawingSlang}" -samples.indirectDrawing.title: "間接繪製" -samples.meshShading.description: "任務著色器剔除球體執行個體,將保留的索引傳給負責產生幾何體的網格著色器。建立管線前,渲染器檢查 {contextCapabilitiesMeshShadingSupported}。" -samples.meshShading.details: "{meshShadingRendererCs} · {meshShadingSlang}" -samples.meshShading.title: "網格著色" -samples.rayTracing.description: "此範例為地面與程序化球體建立底層及頂層加速結構,再於計算著色器內執行內嵌光線查詢。初始化前檢查 {contextCapabilitiesRayTracingSupported}。" -samples.rayTracing.details: "{rayTracingRendererCs} · {rayTracingSlang}" -samples.rayTracing.title: "光線追蹤" -samples.title: "範例" -samples.triangle.description: "三角形範例將頂點緩衝區與對應的輸入佈局關聯,再透過圖形管線繪製三個頂點。" -samples.triangle.details: "{helloTriangleRendererCs} · {helloTriangleSlang} · {link}" -samples.triangle.details.link: "完整教學" -samples.triangle.title: "Hello Triangle" -samples.workloads.description: "主存放庫的{link}包含規模較大的應用程式,這些專案直接參考程式庫原始碼。" -samples.workloads.description.link: "Experiments 目錄" -samples.workloads.details: "視窗實驗專案採用相同的 Windows、macOS 和 Linux/X11 呈現路徑。Avalonia、WinForms、WPF、WinUI/Uno 和 MAUI 控制項的影格生命週期及實作程式碼見{link}。" -samples.workloads.details.link: "平台整合" -samples.workloads.table.cornellBox.example: "{link}" -samples.workloads.table.cornellBox.example.link: "CornellBox" -samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: "路徑追蹤、降噪、色調對應、影像升頻與 ImGui 控制項。需要光線追蹤支援。" -samples.workloads.table.fluidTank.example: "{link}" -samples.workloads.table.fluidTank.example.link: "FluidTank" -samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: "計算流體模擬、模擬階段之間的相依關係,以及多通道表面渲染。" -samples.workloads.table.headings.example: "範例" -samples.workloads.table.headings.whatItDemonstratesAndRequires: "技術與執行要求" -samples.workloads.table.inkCanvas.example: "{link}" -samples.workloads.table.inkCanvas.example.link: "InkCanvas" -samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: "在原生視窗中進行 Skia 繪圖與輸入處理。需要目標平台的後端與 Skia 原生程式庫。" -samples.workloads.table.platformDetection.example: "{link}" -samples.workloads.table.platformDetection.example.link: "PlatformDetection" -samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: "嘗試為每個後端建立上下文,並回報裝置功能。建立失敗時顯示為不支援,原因可能是裝置、驅動程式或缺少執行時所需的元件。" -samples.workloads.title: "綜合應用" -tutorial.context.description: "{graphicsContext} 透過後端連接應用程式與 GPU,並提供建立渲染資源的方法。" -tutorial.context.details: "在{emphasis}插入上下文初始化程式碼:" -tutorial.context.details.emphasis: "using 指示詞之後、{iWindowWindow} 之前" -tutorial.context.guidance: "各分支為目前平台選擇後端並要求啟用驗證。{validationMessage} 訊息會輸出到主控台。" -tutorial.context.imports: "在 {programCs} 頂端加入以下 using 指示詞:" -tutorial.context.title: "圖形上下文" -tutorial.description: "本教學從空白的 .NET 主控台專案開始,逐步建立視窗,並在其中繪製一個彩色三角形。" -tutorial.details: "本教學分三個階段確認結果:空白視窗、單色背景,以及彩色三角形。每完成一個階段,先執行程式檢查畫面,再繼續下一步。" -tutorial.draw.context: "{draw} 的引數如下:" -tutorial.draw.description: "在 {windowRender} 回呼中,用以下命令替換 {addTheTriangleDrawCommandsHereLater},位置保持在 {beginRenderPass} 與 {endRenderPass} 之間:" -tutorial.draw.details: "{setPipeline} 選擇著色器和渲染狀態。後端按管線的輸入佈局解釋頂點繫結,因此這一步必須先於頂點繫結。" -tutorial.draw.guidance: "{setVertexBufferVertexBuffer} 從緩衝區的位元組位移 0 開始,將已上傳的頂點資料繫結到輸入槽 0,對應 {inputLayouts} 中唯一的項目。" -tutorial.draw.notes: "這些呼叫記錄繪製命令。既有的 {submitWait} 提交命令並等待 GPU 完成,接著由 {present} 要求顯示完成的影像。保留通道開始時的清除操作,讓三角形以外的區域也有確定的背景色。" -tutorial.draw.table.firstInstance.meaning: "執行個體編號從零開始。" -tutorial.draw.table.firstVertex.meaning: "從緩衝區中的第一個頂點開始。" -tutorial.draw.table.headings.argument: "引數" -tutorial.draw.table.headings.description: "值" -tutorial.draw.table.headings.meaning: "意義" -tutorial.draw.table.instanceCount.meaning: "繪製一個三角形執行個體。" -tutorial.draw.table.vertexCount.meaning: "讀取三個頂點。" -tutorial.draw.title: "繪製命令" -tutorial.execution.description: "建置並執行 {firstTriangle} 專案。" -tutorial.execution.details: "視窗中應出現一個三角形:上方為紅色,右下方為綠色,左下方為藍色,背景為深色。頂點色彩經過內插,在三角形內形成平滑的漸層。" -tutorial.execution.guidance: "調整視窗大小時,影像的像素尺寸會改變,頂點座標則維持不變。視口將這些座標對應到新的寬度與高度,因此改變視窗的寬高比會拉伸三角形。" -tutorial.execution.title: "執行應用程式" -tutorial.frame.commands.context: "{endRenderPass} 之後的第二次轉換讓輸出紋理進入可呈現的佈局。{submit} 結束記錄並提交命令緩衝區,{wait} 阻塞至本次提交完成,隨後 {present} 請求顯示渲染結果。" -tutorial.frame.commands.description: "渲染通道將寫入同一組附件的繪製操作放在一起。本通道使用交換鏈的輸出紋理接收色彩結果。{colorAttachmentClear} 指定以 RGBA 色彩初始化附件,並在通道結束時保留內容。{beginRenderPass} 依這些設定記錄通道的開始命令。" -tutorial.frame.commands.details: "集合中有一個色彩附件。{null} 表示此通道不使用深度/樣板附件。" -tutorial.frame.commands.guidance: "{beginRenderPass} 預設讓視口與裁剪區域覆蓋整個附件。視口將渲染座標映射為像素位置,裁剪區域則限制可以寫入的範圍。" -tutorial.frame.commands.title: "清除、提交與呈現" -tutorial.frame.description: "先將視窗填滿單一背景色,這個操作稱為清除。背景正常顯示後,就能確認呈現目標、命令提交與呈現流程已連接完成,接著再加入三角形的頂點與著色器。" -tutorial.frame.details: "Silk.NET 在需要繪製一個影格時呼叫渲染回呼。本範例不使用回呼傳入的時間間隔,因此將該引數命名為 {value}。在{emphasis}註冊回呼:" -tutorial.frame.details.emphasis: "{windowRun} 之前" -tutorial.frame.target.description: "{graphicsQueueCommandBuffer} 傳回可直接記錄的命令緩衝區。記錄描述 GPU 工作,提交後才開始執行。" -tutorial.frame.target.details: "紋理佈局描述操作如何存取紋理。第一次 {transition} 讓輸出紋理準備好作為色彩附件。這裡的 {default} 選擇 mip 級別 0 與陣列層 0,也就是輸出紋理的基本影像。由於這個通道會清除整張影像,可以指定 {undefined},允許丟棄先前內容。" -tutorial.frame.target.guidance: "呈現後可能換用另一張影像,因此每個影格都要重新取得目前的輸出紋理。" -tutorial.frame.target.title: "準備輸出紋理" -tutorial.frame.title: "第一個影格" -tutorial.geometry.data.description: "在{emphasis}新增頂點陣列。後續資源初始化也放在該回呼之前,順序如下。" -tutorial.geometry.data.description.emphasis: "{windowRender} 之前" -tutorial.geometry.data.details: "每個條目構造一個 {vertex},內部的兩個 {new} 表示式分別提供 {vector3} 位置和 {vector4} 顏色。三個位置對應上角、右下角和左下角。頂點著色器將 {w} 作為第四個位置座標;w 為 1 時,x、y 也就是正規化裝置座標,-1 與 +1 對應影像邊界,0 對應中心,與像素尺寸無關。" -tutorial.geometry.data.guidance: "每個色彩包含紅、綠、藍與 alpha 分量,alpha 設為 1。三個頂點的 z 座標均為 0,位於同一平面。" -tutorial.geometry.data.title: "頂點位置與顏色" -tutorial.geometry.description: "三角形的每個頂點都有位置與色彩。GPU 依三個位置決定三角形的形狀,再對頂點色彩內插,算出內部各處的色彩。" -tutorial.geometry.format.description: "在{emphasis}追加頂點宣告:" -tutorial.geometry.format.description.emphasis: "{programCs} 的結尾處、清理陳述式之後" -tutorial.geometry.format.details: "{file} 將型別的使用範圍限定在 {programCs},{layoutKindSequential} 則保留欄位的宣告順序。{position} 包含三個 32 位元浮點數,位元組位移為 0;{color} 包含四個,位元組位移為 12。因此,每個頂點占 28 位元組。稍後會透過輸入佈局描述這個排列,讓 GPU 正確讀取各欄位。" -tutorial.geometry.format.imports: "在 {programCs} 頂端加入以下 using 指示詞,以使用向量型別與結構佈局屬性:" -tutorial.geometry.format.title: "頂點表示" -tutorial.geometry.title: "頂點資料" -tutorial.geometry.upload.context: "{fixed} 可避免記憶體回收行程在位址使用期間移動陣列。對於這個 CPU 可寫緩衝區,{upload} 會映射記憶體、複製資料,再解除映射後返回,因此只需在呼叫期間固定陣列。頂點資料在初始化時上傳一次即可;緩衝區則必須保留到渲染結束。" -tutorial.geometry.upload.description: "將頂點存入 {buffer},供 GPU 在繪製時讀取。緊接在頂點陣列之後,加入配置與上傳程式碼:" -tutorial.geometry.upload.details: "配置大小為 {sizeofVertexVerticesLength},即三個 28 位元組頂點,共 84 位元組。{bufferUsagesVertex} 宣告頂點輸入用途,{cpuWriteOnly} 允許 CPU 直接初始化。描述中的跨距記錄元素大小,隨後定義的輸入佈局指定 GPU 如何讀取各個頂點屬性。" -tutorial.geometry.upload.guidance: "配置空間不會初始化緩衝區內容。{upload} 使用資料描述中的來源指標與位元組數,將陣列複製到目標位元組位移 0。" -tutorial.geometry.upload.imports: "在 {programCs} 頂端的 using 指示詞中加入 {bufferAlias},以區分 Zenith.NET 的緩衝區型別與 {systemBuffer}。" -tutorial.geometry.upload.notes: "在 {programCs} 結尾的清理程式碼中,緊接在 {swapChainDispose} 之前加入 {vertexBufferDispose}。較大型靜態幾何體所需的 GPU 專用儲存與上傳方式,見{link}。" -tutorial.geometry.upload.notes.link: "資源管理" -tutorial.geometry.upload.title: "緩衝區配置與上傳" -tutorial.input.description: "GPU 需要知道位置、色彩等頂點屬性儲存在哪裡。輸入佈局指定各屬性的格式與位元組位移,並以跨距表示兩個相鄰頂點相隔多少位元組。在建立著色器之後加入以下程式碼:" -tutorial.input.details: "{inputLayoutAdd} 將屬性依序排列,並將每個屬性的大小加到跨距中。位移是根據這裡提供的格式計算,不是透過檢查 C# 結構取得。這兩個欄位的佈局如下:" -tutorial.input.guidance: "{semanticIndex} 預設為 0,對應著色器中的 {pOSITION0} 與 {cOLOR0}。位置與色彩存放在同一個頂點緩衝區,因此管線只需在槽 0 使用一個輸入佈局。若 C# 結構的欄位順序或填充改變,也要一併調整此佈局。" -tutorial.input.table.headings.byteOffset: "位元組位移" -tutorial.input.table.headings.cField: "C# 欄位" -tutorial.input.table.headings.format: "格式" -tutorial.input.table.headings.shaderInput: "著色器輸入" -tutorial.input.table.nextVertex.cField: "下一個頂點" -tutorial.input.table.nextVertex.format: "總跨距:28 位元組" -tutorial.input.table.nextVertex.shaderInput: "下一筆輸入記錄" -tutorial.input.table.vertexColor.format: "{float4}(16 位元組)" -tutorial.input.table.vertexPosition.format: "{float3}(12 位元組)" -tutorial.input.title: "頂點輸入佈局" -tutorial.lifecycle.description: "每個影格依次執行以下操作:" -tutorial.lifecycle.details: "關閉視窗後,{run} 返回,程式繼續執行清理程式碼。每個影格都已等待其提交完成,因此現在可以釋放這些命令使用的資源。{windowRun} 之後完整的清理程式碼如下:" -tutorial.lifecycle.guidance: "先釋放交換鏈,再銷毀其原生視窗;先釋放應用程式資源,再釋放上下文。已提交的命令緩衝區由佇列回收,輸出紋理由交換鏈管理,兩者都不需要單獨呼叫 {dispose}。" -tutorial.lifecycle.title: "影格生命週期與清理" -tutorial.pipeline.behavior: "在輸入佈局之後建立管線:" -tutorial.pipeline.context: "{cullNone} 關閉面剔除,因此無論頂點在畫面中呈順時針或逆時針排列,三角形都會被繪製。" -tutorial.pipeline.description: "{graphicsPipeline} 將頂點佈局、兩個著色器,以及圖元組裝和附件輸出所需的設定組合在一起。" -tutorial.pipeline.details: "著色器負責處理頂點與片元。其餘管線設定決定圖元如何組裝、是否剔除特定朝向的面,以及如何執行深度測試和色彩混合:" -tutorial.pipeline.guidance: "管線顏色格式必須匹配渲染通道附件,因此直接取自 {swapChainDescFormat}。{count1} 表示每像素一個取樣點。" -tutorial.pipeline.item: "{triangleList} 將每組連續的三個頂點組裝成一個三角形。" -tutorial.pipeline.notes: "{depthNone} 關閉深度測試和深度寫入,與通道沒有深度附件的設定一致。" -tutorial.pipeline.reference: "{opaque} 關閉混合,因此片元著色器輸出直接替換三角形內部的背景色。" -tutorial.pipeline.title: "圖形管線" -tutorial.pipeline.usage: "管線建立完成後即可釋放著色器物件。渲染期間保留管線,在清理程式碼中將 {pipelineDispose} 放在 {vertexBufferDispose} 之前。" -tutorial.presentation.title: "圖形上下文與呈現" -tutorial.project.context: "在專案建置設定中啟用{emphasis}({allowUnsafeBlocks})。視窗輔助程式碼的原生呼叫和頂點上傳需要不安全程式碼。" -tutorial.project.context.emphasis: "允許不安全的程式碼" -tutorial.project.description: "建立名為 {firstTriangle} 的 C# 主控台專案,目標框架設為 .NET 10。" -tutorial.project.details: "為專案加入以下 NuGet 套件:" -tutorial.project.guidance: "{zenithNET} 提供統一渲染 API,三個後端套件提供各平台的實作。{zenithNETCompiler} 為所選後端編譯稍後介紹的 Slang 著色器。Silk.NET 負責視窗建立與事件處理。" -tutorial.project.title: "專案設定" -tutorial.requirements.context: "{link}及其{detail}提供了本教學的參考實作。" -tutorial.requirements.context.detail: "共用宿主程式" -tutorial.requirements.context.link: "Hello Triangle 範例" -tutorial.requirements.description: "需要 {emphasis},並具備基礎 C# 知識。應用程式以 {net10} 為目標框架。GPU 與驅動程式須支援所在平台選用的後端:" -tutorial.requirements.description.emphasis: ".NET 10 SDK" -tutorial.requirements.guidance: "Zenith.NET 渲染到應用程式提供的原生呈現目標。Silk.NET.Windowing 建立視窗並處理事件。macOS 使用由 {cAMetalLayerCs} 表示的 Metal 圖層,視窗輔助程式碼負責將它連接到視窗。" -tutorial.requirements.table.headings.graphicsBackend: "圖形後端" -tutorial.requirements.table.headings.platform: "平台" -tutorial.requirements.table.linux.graphicsBackend: "Vulkan 1.4" -tutorial.requirements.table.linux.platform: "Linux(X11 或 XWayland)" -tutorial.requirements.table.macOS.graphicsBackend: "Metal 4" -tutorial.requirements.table.macOS.platform: "macOS" -tutorial.requirements.table.windows.graphicsBackend: "DirectX 12" -tutorial.requirements.table.windows.platform: "Windows" -tutorial.requirements.title: "準備事項" -tutorial.resize.context: "再次建置並執行程式。調整視窗大小後,背景應繼續填滿整個視窗:每次開始新的渲染通道時,視口與裁剪區域都會依附件的新尺寸設定。保留渲染回呼,稍後將在這個通道內繪製三角形。" -tutorial.resize.description: "畫面緩衝區尺寸改變時,交換鏈也要跟著調整。在渲染回呼之後、{windowRun} 之前註冊 {framebufferResize} 回呼:" -tutorial.resize.details: "這裡接收的是以像素為單位的{link},而不是視窗邏輯尺寸的變化。視窗最小化時,畫面緩衝區的寬度或高度可能變成零。此時,尺寸變更回呼保留現有交換鏈,不進行調整。渲染回呼也會在任一尺寸為零時直接返回,直到畫面緩衝區恢復有效尺寸後才繼續繪製。" -tutorial.resize.details.link: "畫面緩衝區大小變更" -tutorial.resize.guidance: "渲染回呼會等待目前影格的提交完成,再呼叫 {present}。因此,尺寸變更回呼替換交換鏈影像時,先前影格的工作已經結束。完成狀態與資源生命週期的要求,詳見{link}。" -tutorial.resize.guidance.link: "同步" -tutorial.resize.title: "視窗尺寸變化" -tutorial.shaders.compilation.context: "{appContextBaseDirectory} 讓程式從輸出目錄載入已複製的著色器。即使從其他工作目錄啟動程式,尋找檔案的位置也不會改變。" -tutorial.shaders.compilation.description: "將 {triangleSlang} 的檔案屬性{emphasis}設為{detail},建置時便會將著色器複製到執行檔所在目錄。" -tutorial.shaders.compilation.description.detail: "有更新時才複製" -tutorial.shaders.compilation.description.emphasis: "複製到輸出目錄" -tutorial.shaders.compilation.details: "回到 {programCs},在頂點上傳之後、渲染回呼之前加入著色器初始化:" -tutorial.shaders.compilation.guidance: "{zenithCompiler} 為 {contextGraphicsApi} 指定的後端編譯原始碼,{createShader} 再依編譯後的描述建立著色器物件。進入點名稱 {vSMain} 與 {fSMain} 分別選取 Slang 檔案中定義的兩個函式。" -tutorial.shaders.compilation.title: "編譯著色器" -tutorial.shaders.context: "{fSInput} 連接兩個著色器階段。頂點著色器將裁剪空間位置寫入 {sVPOSITION},GPU 據此判斷三角形的可見部分。{cOLOR0} 欄位傳遞頂點色彩,經過三角形內部的內插後再交給片元著色器。兩個階段必須採用相同的色彩型別與語義。" -tutorial.shaders.description: "著色器是在 GPU 上執行的程式。頂點著色器決定每個頂點的位置,片元著色器則決定影像中被覆蓋位置的色彩。接下來會將兩個階段寫在同一個 Slang 檔案,並分別定義進入點,也就是各階段開始執行的函式。" -tutorial.shaders.details: "建立 {triangleSlang},先定義輸入與輸出結構:" -tutorial.shaders.fragment.description: "在同一檔案中追加片元進入點:" -tutorial.shaders.fragment.details: "光柵化判定三角形在影像中的覆蓋範圍,並在這些位置產生片元。每個片元的色彩由三個頂點的色彩內插而得。{fSMain} 傳回這個色彩,{sVTARGET} 則將結果送到第一個色彩附件。" -tutorial.shaders.fragment.title: "片元著色" -tutorial.shaders.guidance: "{vSInput} 定義頂點著色器輸入。{pOSITION0} 和 {cOLOR0} 按語義識別屬性,C# 欄位名稱本身不建立這一映射。" -tutorial.shaders.title: "著色器階段" -tutorial.shaders.vertex.description: "在 {triangleSlang} 中追加頂點進入點:" -tutorial.shaders.vertex.details: "GPU 為每個輸入頂點呼叫這一進入點,補充齊次座標 {w} 並傳遞顏色。頂點處理結束後,位置要除以 w。本例 w 為 1,x、y、z 保持不變,可直接解釋為正規化裝置座標。" -tutorial.shaders.vertex.title: "頂點著色" -tutorial.surface.description: "在{emphasis}指定原生呈現目標:" -tutorial.surface.description.emphasis: "{windowCenter} 之後、{windowRun} 之前" -tutorial.surface.details: "畫面緩衝區是視窗用來顯示的像素影像。{surface} 描述原生呈現目標及其尺寸,{framebufferSize} 則提供像素大小。啟用顯示縮放時,這個大小可能與視窗的邏輯尺寸不同。" -tutorial.surface.guidance: "呈現目標提供後端所需的原生控制代碼:Windows 使用 Win32 視窗,Linux 使用 X11 顯示與視窗,macOS 使用已連接的 Metal 圖層。" -tutorial.surface.title: "原生呈現目標" -tutorial.swapChain.context: "交換鏈需要上下文與視窗才能運作。將 {programCs} 結尾的 {windowDispose} 換成以下釋放順序:" -tutorial.swapChain.description: "緊接呈現目標描述,建立交換鏈:" -tutorial.swapChain.details: "{swapChain} 管理視窗呈現的影像。{drawable} 以影像資源 {texture} 的形式提供目前影像。渲染後,{present} 請求顯示該影像,並推進到下一個輸出紋理。" -tutorial.swapChain.guidance: "{b8G8R8A8UNorm} 按藍、綠、紅和 alpha 順序儲存四個 8 位元通道。{uNorm} 將整數 0–255 對應到 0–1。著色器仍輸出邏輯 RGBA 值,格式只規定儲存表示;管線透過 {swapChainDescFormat} 匹配附件。" -tutorial.swapChain.title: "交換鏈" -tutorial.title: "第一個三角形" -tutorial.troubleshooting.description: "結合主控台診斷與三個檢查點定位失敗階段:" -tutorial.troubleshooting.details: "{link}與{detail}可用於核對頂點資料、輸入佈局和繪製操作。該範例將視窗與提交邏輯放入共用宿主程式,本教學則保留在 {programCs} 中。{context}進一步介紹索引繪製、變換與深度測試。" -tutorial.troubleshooting.details.context: "旋轉立方體" -tutorial.troubleshooting.details.detail: "Slang 著色器" -tutorial.troubleshooting.details.link: "範例渲染器" -tutorial.troubleshooting.table.backend.check: "檢查選取的後端是否受到裝置與已安裝的圖形驅動程式支援。" -tutorial.troubleshooting.table.backend.symptom: "後端建立失敗" -tutorial.troubleshooting.table.drawing.check: "檢查上傳大小、輸入佈局、管線選擇,以及繪製命令是否位於渲染通道內。" -tutorial.troubleshooting.table.drawing.symptom: "背景出現但三角形未出現" -tutorial.troubleshooting.table.headings.check: "檢查項目" -tutorial.troubleshooting.table.headings.symptom: "徵狀" -tutorial.troubleshooting.table.input.check: "檢查跨距是否為 28 位元組,位置與色彩是否分別從位移 0 和 12 位元組開始。" -tutorial.troubleshooting.table.input.symptom: "頂點位置或色彩異常" -tutorial.troubleshooting.table.shaders.check: "檢查複製的 {triangleSlang}、進入點拼寫,以及編譯器回報的診斷資訊。" -tutorial.troubleshooting.table.shaders.symptom: "背景色正常顯示,但著色器載入失敗" -tutorial.troubleshooting.table.window.check: "確認 .NET 專案可成功建置,且僅含視窗的步驟可在桌面工作階段中執行。在 Linux 上,檢查 X11 或 XWayland 是否可用。" -tutorial.troubleshooting.table.window.symptom: "視窗未開啟" -tutorial.troubleshooting.title: "問題排查" -tutorial.window.description: "將 {cocoaHelperCs} 下載至專案中。此輔助類別負責將 Metal 圖層連接到 macOS 視窗。" -tutorial.window.details: "將自動產生的 {programCs} 內容換成以下程式碼。它使用最上層陳述式,依書寫順序執行,不需要明確撰寫 {main} 方法。後續各節會指出新程式碼應加入的位置:" -tutorial.window.guidance: "{graphicsAPINone} 將圖形上下文的建立交給 Zenith.NET。{initialize} 建立原生視窗,讓程式取得視窗系統的控制代碼;{center} 把視窗放在螢幕中央。{run} 持續處理事件直到視窗關閉,之後再執行 {dispose} 釋放視窗。" -tutorial.window.notes: "建置並執行程式,確認視窗可以開啟、移動、調整大小及關閉。此時尚未提交渲染命令,視窗內容還沒有定義。關閉視窗後再繼續。" -tutorial.window.title: "建立視窗" -ui.action.copy: "複製" -ui.action.navigate: "巡覽" -ui.action.open: "開啟" -ui.action.source: "檢視原始碼" -ui.api.browse: "瀏覽命名空間與型別。" -ui.api.clearTypeSearch: "清除型別搜尋" -ui.api.findType: "尋找型別" -ui.api.loadError: "無法載入型別。重新載入此頁面以重試。" -ui.api.loadingNamespaces: "正在載入命名空間…" -ui.api.loadingTypes: "正在載入型別…" -ui.api.matchingTypes: "相符的型別" -ui.api.namespace: "命名空間" -ui.api.namespaces: "命名空間" -ui.api.noNamespaceTypes: "此命名空間中沒有型別。" -ui.api.noTypes: "沒有相符的型別。" -ui.api.types: "型別" -ui.content.reference: "參考" -ui.content.source: "原始碼" -ui.content.tutorial: "教學" -ui.contents.close: "關閉目錄" -ui.contents.open: "開啟目錄" -ui.contents.title: "目錄" -ui.footer.caption: "面向 .NET 的現代 RHI" -ui.footer.label: "頁尾" -ui.language.label: "語言" -ui.language.unavailable: "未翻譯" -ui.members.clear: "清除成員搜尋" -ui.members.close: "關閉成員尋找工具" -ui.members.empty: "沒有相符的成員。" -ui.members.open: "前往成員" -ui.members.placeholder: "名稱或簽章…" -ui.members.search: "搜尋成員" -ui.members.title: "尋找成員" -ui.members.undeclared: "此型別沒有宣告的成員。" -ui.navigation.api: "API" -ui.navigation.concepts: "概念" -ui.navigation.home: "首頁" -ui.navigation.label: "主要導覽" +concepts.execution.context.description: '{graphicsContext} 透過特定後端連接應用程式與 GPU 裝置,並提供圖形、計算與傳輸佇列。一起使用的資源必須屬於同一上下文;緩衝區、紋理、著色器、管線及其控制代碼不能跨上下文繫結。' +concepts.execution.context.details: '{capabilities} 提供裝置名稱與支援的功能。建立光線追蹤或網格著色所需的資源前,分別透過 {rayTracingSupported} 與 {meshShadingSupported} 確認支援情況。{link}與{detail}範例展示了初始化時的檢查方式。' +concepts.execution.context.details.detail: '網格著色' +concepts.execution.context.details.link: '光線追蹤' +concepts.execution.context.title: '圖形上下文' +concepts.execution.description: 'GPU 工作從 CPU 端開始準備:應用程式建立資源,記錄使用這些資源的命令,再提交到佇列。提交後,CPU 可以繼續處理其他工作,同時由 GPU 執行命令。相關資源必須保留到 GPU 執行結束。' +concepts.execution.ownership.description: '所有權決定由誰釋放物件,GPU 完成狀態決定何時可以釋放。即使仍保留物件的 C# 參考,呼叫 {dispose} 也會釋放其原生資源。提交命令不會將資源所有權轉交給佇列。' +concepts.execution.ownership.details: '結束程式時,先停止提交新工作,並等待所有相關佇列完成最後一次資源存取。接著釋放應用程式資源,最後釋放上下文。上下文會釋放自身的佇列與內部輔助物件,因此這一步必須在應用程式工作全部完成後進行。' +concepts.execution.ownership.guidance: '渲染期間,若準備覆寫資料或替換資源,就應追蹤仍在使用它們的工作。等待這些存取完成後,再修改資料或釋放儲存空間。檢視與底層資源如何遵循這個生命週期規則,見{link}。' +concepts.execution.ownership.guidance.link: '資源管理' +concepts.execution.ownership.table.applicationResources.object: '應用程式建立的資源' +concepts.execution.ownership.table.applicationResources.ownership: '最後一次 GPU 使用完成後,由應用程式釋放。' +concepts.execution.ownership.table.commandBuffers.object: '借用的命令緩衝區' +concepts.execution.ownership.table.commandBuffers.ownership: '由佇列管理和回收。' +concepts.execution.ownership.table.headings.object: '物件' +concepts.execution.ownership.table.headings.ownership: '釋放責任' +concepts.execution.ownership.table.queues.object: '圖形上下文佇列與其時間線' +concepts.execution.ownership.table.queues.ownership: '由上下文和佇列管理。' +concepts.execution.ownership.table.swapChainDrawable.ownership: '由交換鏈管理。' +concepts.execution.ownership.title: '所有權與生命週期' +concepts.execution.pipelines.description: '圖形管線規定繪製所用的著色器、頂點輸入佈局、圖元組裝方式、附件格式和渲染狀態。繫結頂點、索引或常數資料之前,須先選擇管線;管線宣告的附件格式與取樣數也必須與渲染通道一致。' +concepts.execution.pipelines.details: '計算管線選擇分派所執行的著色器進入點。在圖形渲染通道之外,先繫結管線及其常數,再執行分派。' +concepts.execution.pipelines.guidance: '{link}給出了完整的圖形命令順序。{detail}則先執行計算分派,再透過圖形通道顯示結果。' +concepts.execution.pipelines.guidance.detail: '計算範例' +concepts.execution.pipelines.guidance.link: '三角形的渲染回呼' +concepts.execution.pipelines.title: '管線狀態' +concepts.execution.queues.description: '一個影格同時包含繪製、計算與複製時,通常從 {graphicsQueue} 開始。將彼此相依的操作放在同一佇列,能簡化順序管理。' +concepts.execution.queues.details: '不同佇列可分別接收獨立的工作負載,但未必對應獨立的硬體引擎。若工作能從重疊執行中受益,再考慮增加佇列。當一個佇列使用另一個佇列產生的資料時,需要在兩次提交之間建立明確的相依關係。' +concepts.execution.queues.guidance: '即使位於同一佇列,彼此相依的操作也可能需要屏障或紋理轉換,讓後續存取讀到先前寫入的結果。這種記憶體相依關係與提交順序不同,具體指定方式見{link}。' +concepts.execution.queues.guidance.link: '同步' +concepts.execution.queues.table.computeQueue.workToRecord: '計算分派與相容的傳輸工作,不包含圖形渲染通道。' +concepts.execution.queues.table.graphicsQueue.workToRecord: '渲染通道、繪製、計算與傳輸操作。' +concepts.execution.queues.table.headings.queue: '佇列' +concepts.execution.queues.table.headings.workToRecord: '支援的工作' +concepts.execution.queues.table.transferQueue.workToRecord: '上傳、回讀與複製工作,不包含繪圖或計算分派。' +concepts.execution.queues.title: '佇列選擇' +concepts.execution.recording.context: '佇列會回收已完成的命令緩衝區以供重複使用。每次記錄時,透過 {queueCommandBuffer} 取得緩衝區,同一時間只由一個執行緒記錄,而且只提交一次。提交後交由佇列管理,不再修改、重複提交或自行釋放。' +concepts.execution.recording.description: '{queueCommandBuffer} 傳回的 {commandBuffer} 已開始記錄。完成操作及其相依關係的記錄後,呼叫一次 {submit},結束記錄並提交命令。傳回的 {timelineValue} 識別這次提交在佇列上的完成點。' +concepts.execution.recording.details: '三角形教學將一個影格記錄到 {commandBuffer} 後,按如下方式提交並等待完成:' +concepts.execution.recording.guidance: '記錄會建立命令序列,{submit} 則安排該序列執行。接著呼叫 {wait},CPU 執行緒便會等待這次提交完成。教學因此採用逐影格執行的流程:目前影格完成後,才開始下一個影格。' +concepts.execution.recording.title: '記錄與提交' +concepts.execution.title: '執行模型' +concepts.platforms.description: '呈現流程可以由應用程式管理,也可以交給 UI 渲染控制項。這決定了誰來取得目前影格的輸出紋理、記錄與提交命令,以及顯示渲染結果。' +concepts.platforms.frame.context: '在通道內繫結管線並記錄繪製命令,處理程式返回前須結束通道。控制項負責提交命令與呈現結果;處理程式不可自行提交命令緩衝區,也不可釋放傳入的命令緩衝區或輸出紋理。若改變了輸出紋理的佈局,返回前須恢復為 {colorAttachment},讓控制項能完成最後的轉換。' +concepts.platforms.frame.description: '各控制項實作 {iZenithView} 介面。應用程式設定 {graphicsContext},在 {updateRequested} 中更新場景,並在 {renderRequested} 中透過傳入的 {renderEventArgs} 記錄命令。' +concepts.platforms.frame.details: '每個影格中,控制項會取得輸出紋理與命令緩衝區,將輸出紋理轉換為 {colorAttachment},再呼叫更新和渲染處理程式。之後,控制項提交已記錄的工作,並透過對應框架的呈現機制顯示影像。' +concepts.platforms.frame.guidance: '先在檔案中加入 {usingZenithNET}。假定名為 {view} 的 {iZenithView} 執行個體已初始化,且已設定圖形上下文,可註冊以下處理程式來清除其輸出紋理:' +concepts.platforms.frame.notes: '初始轉換使用 {undefined},允許丟棄先前影像的內容。因此,每個影格都應重新繪製或清除整張影像。需要累積或快取的渲染結果,可儲存在應用程式擁有的紋理中,再將該紋理繪製到控制項的輸出紋理上。' +concepts.platforms.frame.reference: '{zenithViewHelperDrawableFormat} 提供這些整合使用的預設色彩格式。' +concepts.platforms.frame.title: '透過 UI 控制項渲染' +concepts.platforms.integration.context: 'WinForms、WPF 與 Windows 版 WinUI 整合在 Windows 上執行。使用 MAUI 時,安裝目標平台的工作負載,並透過 {useZenithView} 註冊控制項處理程式,具體見 {extensionsCs}。' +concepts.platforms.integration.description: '控制項共用事件介面,但呈現機制因框架而異:' +concepts.platforms.integration.details: '各實作將 GPU 影像送到 UI 的方式不同。點陣圖回讀先將像素複製到 CPU 記憶體,再顯示影像;共用紋理互通能省去這次 CPU 複製,但仍可能需要 GPU 複製與同步。選擇整合方式時,除了共用的 {renderRequested} 事件介面,也應考慮其呈現方式。' +concepts.platforms.integration.guidance: '透過 NuGet 加入所用 UI 框架的整合套件。Avalonia 對應的套件為 {avaloniaPackage}。' +concepts.platforms.integration.table.avalonia.integration: 'Avalonia' +concepts.platforms.integration.table.avalonia.presentation: '渲染到紋理後,將像素回讀到 {writeableBitmap},實作見 {zenithViewCs} 和 {surfaceCs}。' +concepts.platforms.integration.table.headings.integration: '整合' +concepts.platforms.integration.table.headings.presentation: '呈現機制' +concepts.platforms.integration.table.maui.integration: '.NET MAUI' +concepts.platforms.integration.table.maui.presentation: 'Android、iOS 和 Mac Catalyst 使用原生呈現目標;Windows 使用共用紋理合成,具體見{link}。' +concepts.platforms.integration.table.maui.presentation.link: '平台實作' +concepts.platforms.integration.table.uno.integration: 'Uno 路徑' +concepts.platforms.integration.table.uno.presentation: '將像素回讀到 {writeableBitmap},實作見 {zenithViewUnoCs}。' +concepts.platforms.integration.table.winForms.integration: 'WinForms' +concepts.platforms.integration.table.winForms.presentation: '為控制項的 {hWND} 建立 Zenith.NET 交換鏈,實作見 {zenithViewCs}。' +concepts.platforms.integration.table.winUI.integration: 'Windows 上的 WinUI' +concepts.platforms.integration.table.winUI.presentation: '渲染到匯入的共用 Direct3D 11 紋理,再複製到與 {swapChainPanel} 連線的合成交換鏈,具體見 {zenithViewWinUICs}。' +concepts.platforms.integration.table.wpf.integration: 'WPF' +concepts.platforms.integration.table.wpf.presentation: '匯入共用 Direct3D 11 紋理,再經 Direct3D 互通複製到由 {d3DImage} 顯示的表面,具體見 {surfaceCs}。' +concepts.platforms.integration.title: '框架與呈現路徑' +concepts.platforms.lifecycle.context: '建立配套附件時,使用渲染事件傳入的輸出紋理的 {descWidth}、{descHeight}、{descFormat} 與 {descSampleCount}。該紋理提供渲染目標的實際尺寸,不應依控制項的版面配置尺寸或顯示縮放比例推算。' +concepts.platforms.lifecycle.description: '交換鏈使用以像素計量的畫面緩衝區寬度與高度。啟用顯示縮放時,這些值可能不同於視窗的邏輯尺寸。任一尺寸為零時,暫停渲染與交換鏈尺寸調整。每個影格重新取得 {swapChainDrawable}:這張紋理由交換鏈管理,可能在呈現或調整大小後被替換。' +concepts.platforms.lifecycle.details: '畫面緩衝區尺寸改變時,先等待 GPU 完成對舊影像的存取,再呼叫 {swapChainResize}。替換原生呈現目標時,也應先等待這些存取結束,再將新的目標描述與控制代碼傳給 {swapChainRefresh}。結束程式時,先釋放交換鏈,再銷毀其原生呈現目標。' +concepts.platforms.lifecycle.guidance: '應用程式的深度紋理或離屏紋理若隨視窗尺寸改變,就需要在調整大小時重建,並更新包含其控制代碼的常數。只要附件格式與取樣數仍然相符,管線就可以繼續使用。{link}展示了如何調整紋理尺寸並保留管線。' +concepts.platforms.lifecycle.guidance.link: '旋轉立方體渲染器' +concepts.platforms.lifecycle.title: '交換鏈尺寸與生命週期' +concepts.platforms.ownership.description: '應用程式擁有所設定的上下文及其渲染資源,控制項擁有呈現資源。檢視的 {graphicsContext} 改變後,排程程式會為新上下文重建控制項資源。應用程式也須為該上下文重建自己的管線、緩衝區與紋理。' +concepts.platforms.ownership.details: '替換渲染資源前,先停止檢視的影格活動,並等待使用這些資源的 GPU 工作完成,再釋放舊資源或上下文。移除檢視後,所設定的上下文仍由應用程式負責釋放。' +concepts.platforms.ownership.guidance: '共用的 {frameSchedulerCs} 透過檢視的 UI 排程器執行影格處理程式。處理程式應專注於場景資料更新與命令記錄,其中耗時的 CPU 工作也會延遲介面回應。' +concepts.platforms.ownership.title: '應用程式與控制項的責任' +concepts.platforms.surface.description: '{link}使用 Silk.NET 建立視窗並處理事件。Zenith.NET 透過 {surface} 描述取得原生視窗控制代碼與尺寸,再據此建立 {swapChain}。作業系統視窗仍由應用程式負責管理。' +concepts.platforms.surface.description.link: '三角形教學' +concepts.platforms.surface.details: '原生控制代碼必須與所選後端匹配:' +concepts.platforms.surface.guidance: '{appCs} 中的範例宿主支援 Windows、macOS 與 X11。Linux 視窗提供 Xlib 控制代碼,因此在 Wayland 工作階段中需要 XWayland。原生 Wayland 應用程式則透過 {surfaceWayland} 提供顯示與表面的控制代碼。' +concepts.platforms.surface.table.android.backend: 'Android 上的 Vulkan。' +concepts.platforms.surface.table.apple.backend: 'Apple 平台上的 Metal。' +concepts.platforms.surface.table.headings.backend: '後端與平台' +concepts.platforms.surface.table.headings.factory: '呈現目標工廠方法' +concepts.platforms.surface.table.headings.handles: '宿主程式提供的控制代碼' +concepts.platforms.surface.table.wayland.backend: '具有原生 Wayland 宿主程式的 Vulkan。' +concepts.platforms.surface.table.wayland.handles: 'Wayland 顯示與表面' +concepts.platforms.surface.table.win32.backend: 'Windows 上的 DirectX 12 或 Vulkan。' +concepts.platforms.surface.table.xlib.backend: 'Linux 上帶有 X11 或 XWayland 的 Vulkan。' +concepts.platforms.surface.table.xlib.handles: 'X11 顯示與視窗' +concepts.platforms.surface.title: '原生呈現目標' +concepts.platforms.title: '平台整合' +concepts.resources.allocation.context: '放置在堆積中的資源,在整個生命週期內都依賴堆積的儲存空間。最後一次 GPU 使用完成後,應先釋放資源,再釋放堆積。' +concepts.resources.allocation.description: '應用程式需要自行管理記憶體配置時,可以使用 {heap}。堆積為資源提供儲存空間,應用程式選擇明確的位元組位移來放置資源,並記錄各區域的使用情況。' +concepts.resources.allocation.details: '對每個資源,使用建立時所需的緩衝區或紋理描述呼叫 {contextGetSizeAndAlignment}。依傳回的大小預留空間,起始位移須為傳回對齊值的整數倍,而且整個區域須位於堆積內,不與其他仍有效的配置重疊。紋理可能包含後端特有的填充,因此不能只依像素數量與每像素位元組數計算配置大小。' +concepts.resources.allocation.guidance: '放置在堆積中的緩衝區,必須使用與堆積相同的駐留設定。紋理儲存使用 GPU 專用堆積。' +concepts.resources.allocation.title: '堆積配置' +concepts.resources.bufferUsages.table.constant.role: '透過常數緩衝區繫結讀取的著色器參數。' +concepts.resources.bufferUsages.table.headings.role: '作用' +concepts.resources.bufferUsages.table.headings.usage: '用途' +concepts.resources.bufferUsages.table.index.role: '索引繪圖所使用的索引。' +concepts.resources.bufferUsages.table.indirect.role: '間接繪製或分派命令讀取的引數。' +concepts.resources.bufferUsages.table.none.role: '未宣告任何緩衝區用途旗標。' +concepts.resources.bufferUsages.table.storageReadOnly.role: '透過唯讀著色器繫結存取的緩衝區資料。' +concepts.resources.bufferUsages.table.storageReadWrite.role: '透過讀寫著色器繫結存取的緩衝區資料。' +concepts.resources.bufferUsages.table.transferDst.role: 'GPU 複製作業的目的地儲存空間。' +concepts.resources.bufferUsages.table.transferSrc.role: 'GPU 複製作業的來源資料。' +concepts.resources.bufferUsages.table.vertex.role: '供繪製命令讀取的頂點屬性。' +concepts.resources.bufferUsages.title: '緩衝區用途' +concepts.resources.description: '資源描述規定應用程式如何使用其儲存空間。例如,一張紋理若要作為渲染目標、供著色器取樣,並將內容複製回 CPU,就需要宣告這三種操作的用途。記憶體放置決定 CPU 的存取方式,同步與生命週期管理則決定何時可以存取資料或釋放儲存空間。' +concepts.resources.memory.context: '對於 CPU 可存取的緩衝區,{map} 提供 CPU 讀寫資料所用的位址。映射與 {unmap} 都不會等待 GPU 工作。CPU 讀取 GPU 寫入的結果前,應用程式須先等待寫入完成;修改同一塊記憶體前,也須等待 GPU 對這些位元組的存取結束。' +concepts.resources.memory.description: '{bufferDesc} 的 {residency} 欄位指定 CPU 對所配置記憶體的預期存取方式:' +concepts.resources.memory.details: '駐留設定表達 CPU 的存取需求,即使 CPU 與 GPU 共用實體記憶體也同樣適用。三角形教學使用 {cpuWriteOnly} 直接初始化小型頂點緩衝區。較大的靜態幾何資料,則可考慮上傳到 GPU 專用儲存空間。' +concepts.resources.memory.guidance: '透過上下文直接建立的紋理使用 GPU 儲存空間,因此 {textureDesc} 沒有駐留欄位。應用程式透過上傳與回讀,在紋理與 CPU 記憶體之間交換資料。' +concepts.resources.memory.table.cpuReadOnly.cPUAccess: '唯讀' +concepts.resources.memory.table.cpuReadOnly.typicalRole: 'GPU 產生的回讀資料' +concepts.resources.memory.table.cpuWriteOnly.cPUAccess: '唯寫' +concepts.resources.memory.table.cpuWriteOnly.typicalRole: 'CPU 提供或更新的資料' +concepts.resources.memory.table.gpuOnly.cPUAccess: '無' +concepts.resources.memory.table.gpuOnly.typicalRole: '靜態幾何體與 GPU 工作資料' +concepts.resources.memory.table.headings.cPUAccess: '預期 CPU 存取' +concepts.resources.memory.table.headings.residency: '記憶體駐留' +concepts.resources.memory.table.headings.typicalRole: '典型用途' +concepts.resources.memory.title: 'CPU 存取與記憶體放置' +concepts.resources.textureUsages.description: '傳輸旗標宣告資源在 GPU 複製中作為來源或目標。CPU 能否直接存取這塊儲存空間,則由記憶體放置方式決定。' +concepts.resources.textureUsages.details: '用途旗標宣告紋理可以發揮的作用。在這些作用之間切換時,需要對應的{link};所選裝置也必須支援以該紋理格式執行所宣告的操作。' +concepts.resources.textureUsages.details.link: '佈局與同步' +concepts.resources.textureUsages.table.colorAttachment.role: '渲染通道中的色彩附件。' +concepts.resources.textureUsages.table.depthStencilAttachment.role: '渲染通道中的深度/樣板附件。' +concepts.resources.textureUsages.table.headings.role: '作用' +concepts.resources.textureUsages.table.headings.usage: '用途' +concepts.resources.textureUsages.table.none.role: '未宣告任何紋理用途旗標。' +concepts.resources.textureUsages.table.sampled.role: '透過取樣紋理繫結讀取的紋理資料。' +concepts.resources.textureUsages.table.storage.role: '透過儲存紋理繫結供著色器讀取或寫入的紋理資料。' +concepts.resources.textureUsages.table.transferDst.role: 'GPU 複製作業的目的地影像儲存空間。' +concepts.resources.textureUsages.table.transferSrc.role: 'GPU 複製作業的來源影像資料。' +concepts.resources.textureUsages.title: '紋理用途' +concepts.resources.title: '資源管理' +concepts.resources.transfers.context: '回讀先將 GPU 資料複製到內部回讀空間。程式庫回收已完成的命令緩衝區時,再將資料複製到指定的 CPU 目標。對這次回讀提交的完成值呼叫 {wait},可以完成這兩個步驟。在呼叫返回前,目標記憶體須保持已配置狀態,受控記憶體須保持固定。' +concepts.resources.transfers.description: '上傳將 CPU 資料複製到 GPU 資源,回讀則將資源資料複製到 CPU 記憶體。緩衝區與紋理上的這些方法會在傳輸完成後返回:' +concepts.resources.transfers.details: '呼叫這些方法前,先處理與其他佇列存取之間的衝突。方法內部的等待只涵蓋自身傳輸,不會建立與其他佇列的相依關係。直接透過映射記憶體複製時,則完全由呼叫端負責等待會產生衝突的 GPU 存取。' +concepts.resources.transfers.guidance: '若要將傳輸與其他 GPU 工作一起提交,可透過 {commandBufferUpload} 或 {commandBufferDownload} 記錄。上傳來源與回讀目標的記憶體生命週期要求不同:' +concepts.resources.transfers.item: '上傳呼叫期間,程式庫會將來源資料複製到內部的臨時上傳空間,也就是暫存記憶體。GPU 隨後從這塊空間讀取,因此應用程式的來源指標只需保持有效到呼叫返回。' +concepts.resources.transfers.notes: '紋理傳輸中的列跨距是 CPU 資料相鄰兩列之間的位元組距離;切片跨距則是相鄰深度切片之間的位元組距離。傳輸操作依這些值,在 CPU 資料與紋理的 GPU 儲存空間之間複製內容。GPU 完成與資料送達回讀目標為何是兩個步驟,見{link}。' +concepts.resources.transfers.notes.link: '同步' +concepts.resources.transfers.table.bufferDownload.transfer: '對於 {cpuReadOnly},直接從映射記憶體複製;否則向傳輸佇列提交回讀,並等待完成。' +concepts.resources.transfers.table.bufferUpload.transfer: '對於 {cpuWriteOnly},直接複製到映射記憶體;否則向傳輸佇列提交上傳,並等待完成。' +concepts.resources.transfers.table.headings.method: '方法' +concepts.resources.transfers.table.headings.transfer: '傳輸行為' +concepts.resources.transfers.table.textureTransfers.method: '{textureUpload} / {textureDownload}' +concepts.resources.transfers.table.textureTransfers.transfer: '將複製及其紋理轉換提交到圖形佇列,並等待完成。操作結束後,所選子資源處於指定的最終佈局。' +concepts.resources.transfers.title: '立即傳輸與命令記錄' +concepts.resources.usages.description: '{bufferUsages} 與 {textureUsages} 是宣告資源用途的旗標列舉,分別設定於 {bufferDescUsages} 與 {textureDescUsages}。資源需要多種用途時,可透過 {value} 組合對應的成員。' +concepts.resources.usages.title: '資源用途' +concepts.resources.views.description: '{bufferView} 描述緩衝區的一塊區域及其資料解讀方式。{textureView} 選擇子資源範圍,以及相容的紋理型別與格式。兩者都參考既有儲存空間,並遵循建立時宣告的用途。檢視範圍用來描述存取範圍,各後端並不因此提供一致的著色器邊界檢查。' +concepts.resources.views.details: '資源本身的控制代碼提供預設檢視。需要其他區域或相容的解讀方式時,再建立獨立檢視。檢視及其底層資源都必須保留到 GPU 使用結束;僅持有資源控制代碼,無法維持任一物件的存活。替換其中任一物件時,還須更新包含舊{link}的常數。' +concepts.resources.views.details.link: '資源控制代碼' +concepts.resources.views.title: '檢視與底層資源' +concepts.shaders.binding.context: '計算範例將 {inputTextureSampledHandle} 寫入 {input},將 {outputTextureStorageHandle} 寫入 {output}。在 Slang 中,{descriptorHandle} 的型別引數規定了著色器存取資源的方式:' +concepts.shaders.binding.description: '{setConstantBuffer} 選擇既有緩衝區與位元組位移,目前管線從該位置讀取常數。著色器使用這些參數前,先將資料上傳到對應的儲存空間。如果先前提交的 GPU 工作仍在讀取相同位元組,須等待該工作完成後再更新。' +concepts.shaders.binding.details: '準備好命令緩衝區、計算管線、已填入資料的常數緩衝區及執行緒群組數量後,依以下順序記錄分派。常數緩衝區會繫結到目前管線,因此必須先選擇管線:' +concepts.shaders.binding.guidance: '這裡,{commandBuffer} 使用 {computePipeline} 及 {constantBuffer} 中的參數記錄分派。緩衝區需要宣告 {bufferUsagesConstant} 用途,位移 0 選擇其起始位置。若多筆常數記錄共用緩衝區,每筆記錄的起始位移還須符合後端繫結的對齊要求,這與記錄內部的欄位佈局是兩項不同要求。' +concepts.shaders.binding.notes: '{resourceHandle} 包含兩個 32 位元欄位,含義由後端解釋,其值只在建立資源的上下文中有效。' +concepts.shaders.binding.reference: '保留資源及用於取得控制代碼的檢視,直到著色器完成最後一次存取。替換紋理或檢視後,應更新仍含舊控制代碼的常數。相關所有權規則見{link}。' +concepts.shaders.binding.reference.link: '資源管理' +concepts.shaders.binding.table.bufferStorageReadOnlyHandle.access: '讀取著色器型別 {t} 的結構化元素' +concepts.shaders.binding.table.bufferStorageReadWriteHandle.access: '讀寫著色器型別 {t} 的結構化元素' +concepts.shaders.binding.table.headings.access: '預期存取' +concepts.shaders.binding.table.headings.cHandle: 'C# 控制代碼' +concepts.shaders.binding.table.headings.slangFieldType: 'Slang 欄位型別' +concepts.shaders.binding.table.samplerHandle.access: '紋理取樣狀態' +concepts.shaders.binding.table.textureSampledHandle.access: '紋理讀取' +concepts.shaders.binding.table.textureStorageHandle.access: '儲存紋理的讀寫' +concepts.shaders.binding.title: '常數緩衝區與資源控制代碼' +concepts.shaders.compilation.description: '{zenithCompiler} 將指定的 Slang 進入點編譯為 {shaderDesc}。上下文的 {graphicsApi} 決定目標格式:DirectX 12 使用 DXIL,Metal 使用 Metal 程式庫,Vulkan 使用 SPIR-V。' +concepts.shaders.compilation.details: '建立名為 {context} 的圖形上下文後,可以編譯已複製到執行檔所在目錄的三角形著色器:' +concepts.shaders.compilation.guidance: '進入點名稱 {vSMain} 必須與著色器檔案中的函式宣告一致。在初始化階段編譯著色器並建立管線,渲染期間重複使用管線。管線建立完成後,即可釋放著色器物件,具體見{link}。' +concepts.shaders.compilation.guidance.link: '第一個三角形' +concepts.shaders.compilation.title: '著色器編譯' +concepts.shaders.description: 'C# 與 Slang 宣告必須約定一致的資料位置與存取方式。頂點輸入佈局描述頂點屬性,著色器緩衝區宣告描述參數與陣列,資源控制代碼則識別著色器使用的資源。' +concepts.shaders.dispatch.description: '{dispatch} 指定要執行多少個執行緒群組。計算範例宣告 {numthreads},因此每組包含 16 × 16 個執行緒。將影像寬度與高度分別除以 16,並向上取整,即可覆蓋整張影像:17 × 19 的影像需要 2 × 2 組。著色器檢查每個執行緒的座標,並跳過位於影像範圍以外的執行緒。' +concepts.shaders.dispatch.details: '{shaderDescThreadGroupSize} 提供宣告的群組大小,可用來計算傳給 {dispatch} 的群組數量。完整計算過程見 {computeShaderRendererCs}。分派完成後,存取輸出影像時仍須符合{link}中說明的要求。' +concepts.shaders.dispatch.details.link: '同步' +concepts.shaders.dispatch.title: '執行緒群組' +concepts.shaders.layout.context: '{link}透過影像尺寸與兩個紋理控制代碼展示這種排列。各欄位的起始位置由明確位移指定。以下宣告使用 {systemRuntimeInteropServices} 與 {zenithNET} 命名空間:' +concepts.shaders.layout.context.link: '計算範例的 C# 常數' +concepts.shaders.layout.description: '對於頂點輸入,{inputLayout} 描述各屬性的格式、位移與語義,以及相鄰頂點之間的跨距。三角形先儲存 {float3} 位置,再儲存 {float4} 色彩:色彩的位元組位移為 12,每個頂點占 28 位元組。{inputLayoutAdd} 根據元素格式計算這個緊密排列的佈局。若 C# 結構包含填充,就需要在位移與跨距中計入這些空間。' +concepts.shaders.layout.details: '常數緩衝區儲存著色器參數,結構化緩衝區儲存指定型別的元素陣列。它們的佈局由 Slang 宣告決定,不使用 {inputLayout}。C# 欄位位移、元素大小與填充,必須符合編譯後的著色器佈局。即使某個 C# 型別是非受控型別,可以直接依位元組複製,其記憶體排列也未必符合著色器要求;例如,頂點中緊密排列的 {float3},在著色器緩衝區中可能需要不同的對齊方式。' +concepts.shaders.layout.guidance: '著色器參數除了普通數值,也可以包含資源控制代碼。控制代碼識別的是既有儲存空間,因此將它複製到常數緩衝區,不會複製資源內容。' +concepts.shaders.layout.notes: '{computeShaderSlang} 中對應的宣告為:' +concepts.shaders.layout.reference: '兩個尺寸值占用前 8 位元組,後面是兩個各占 8 位元組的控制代碼。C# 範例為整筆記錄預留 256 位元組。其他記錄的大小,應依各自欄位以及所需的佈局與對齊方式決定。' +concepts.shaders.layout.title: '資料佈局' +concepts.shaders.matrices.description: '編譯器採用列優先的矩陣儲存方式,使同一列的元素連續排列。{link}在位移 0、64 和 128 處儲存三個 {matrix4x4} 值,其{detail}按模型、檢視和投影順序執行 {mulVectorMatrix}。' +concepts.shaders.matrices.description.detail: '著色器' +concepts.shaders.matrices.description.link: '旋轉立方體渲染器' +concepts.shaders.matrices.details: '儲存順序決定矩陣元素在記憶體中的排列,乘法順序決定變換。C# 與 Slang 應採用相互配合的約定。' +concepts.shaders.matrices.title: '矩陣約定' +concepts.shaders.title: '著色器資料與繫結' +concepts.synchronization.backends.description: 'DirectX 12 與 Vulkan 將紋理轉換記錄為佈局與存取狀態的變更。在 Zenith.NET 的 Metal 後端中,{transition} 沒有對應的 GPU 操作。Metal 後端將命令組織成渲染與計算編碼器,並在編碼器結束時插入可見性屏障。同一編碼器內彼此相依的操作,例如連續的計算分派,透過明確呼叫 {barrier} 協調。' +concepts.synchronization.backends.details: '{link}開始圖形渲染通道時,會結束計算編碼器,讓後續圖形工作能讀取計算輸出。連續兩次計算分派仍位於同一編碼器內,即使中間記錄了紋理轉換,也需要屏障來處理相依關係。因此,跨後端使用的命令序列既要考慮紋理佈局,也要處理存取之間的相依關係。' +concepts.synchronization.backends.details.link: '計算範例' +concepts.synchronization.backends.title: '後端行為' +concepts.synchronization.barriers.context: '選擇涵蓋相關存取,且目前佇列支援的階段。{barrierStagesAll} 包含所有支援的階段;若相依關係只涉及其中一部分,可選擇較小的範圍。' +concepts.synchronization.barriers.description: '假設同一個命令緩衝區內有兩次計算分派,第一次寫入模擬資料,第二次讀取這些資料。在兩次分派之間設定屏障,讓第二次分派讀到已完成的寫入結果。對於儲存緩衝區,這樣即可安排存取順序,不需要進行紋理佈局轉換:' +concepts.synchronization.barriers.details: '第一個引數指定產生資料的階段,第二個引數指定使用資料的階段。兩者共同描述兩次分派之間所需的執行順序與記憶體可見性。' +concepts.synchronization.barriers.guidance: '{link}在模擬步驟之間採用這個方式。每道屏障都位於產生資料的分派之後、使用資料的分派之前。' +concepts.synchronization.barriers.guidance.link: 'FluidTank 模擬' +concepts.synchronization.barriers.title: '管線屏障' +concepts.synchronization.dependencies.description: '逐一確認每個資源有哪些存取涉及同一份資料。只要其中包含寫入,就必須維持所需的先後順序。兩次讀取本身沒有衝突,但仍需符合紋理佈局與呈現要求。CPU 更新資料或釋放資源前,也須等待 GPU 完成對該儲存空間的使用。' +concepts.synchronization.dependencies.details: '應根據操作執行的位置選擇機制:' +concepts.synchronization.dependencies.guidance: '一項工作可能同時需要多種同步機制。例如,紋理由另一個佇列產生時,除了提交相依關係,還需為下一次使用設定正確的佈局。這兩項操作本身都不需要阻塞 CPU;只有 CPU 要存取或釋放相關資料時,才需要在 CPU 端等待。' +concepts.synchronization.dependencies.table.cpuAccess.mechanism: '針對相關完成值呼叫 {wait}。' +concepts.synchronization.dependencies.table.cpuAccess.situation: 'CPU 存取或資源釋放需要等待 GPU 完成' +concepts.synchronization.dependencies.table.crossQueue.mechanism: '將生產者的 {timelineValue} 傳給消費者的 {submit}。' +concepts.synchronization.dependencies.table.crossQueue.situation: '一個佇列使用另一個佇列產生的資料' +concepts.synchronization.dependencies.table.headings.mechanism: '機制' +concepts.synchronization.dependencies.table.headings.situation: '情況' +concepts.synchronization.dependencies.table.layoutChange.mechanism: '呼叫 {commandBufferTransition},指定先前佈局與目標佈局。' +concepts.synchronization.dependencies.table.layoutChange.situation: '紋理子資源變更其使用方式' +concepts.synchronization.dependencies.table.pipelineStages.mechanism: '呼叫 {commandBufferBarrier},指定產生資料和使用資料的階段。' +concepts.synchronization.dependencies.table.pipelineStages.situation: '命令串流中相依的 GPU 階段' +concepts.synchronization.dependencies.title: '存取相依關係' +concepts.synchronization.description: '同步確定多個操作存取共用資料的順序,並讓後續操作能讀到所需結果。在寫後讀相依關係中,寫入端稱為生產者,讀取端稱為消費者。屏障與紋理轉換協調 GPU 存取;時間線連接不同提交,並讓 CPU 等待 GPU 工作完成。' +concepts.synchronization.layouts.context: '現有內容可以丟棄時,可將先前佈局設為 {undefined},例如新建影像或即將完整清除的附件。若要保留內容以供載入、取樣或累積,則應使用前次存取時的佈局。' +concepts.synchronization.layouts.description: '紋理的用途旗標宣告允許的作用。{textureLayout} 描述命令序列中某個時點對子資源的存取方式,子資源由 mip 級別與陣列層識別。存取方式改變時,需要記錄轉換。例如,計算範例在 {storage} 佈局中寫入輸出紋理,再為圖形通道中的取樣做準備:' +concepts.synchronization.layouts.details: '這裡的 {outputTexture} 已宣告 {sampledStorage} 用途,所選子資源處於 {storage} 佈局。{default} 選擇 mip 級別 0 和陣列層 0,其他級別和層不受這次轉換影響。' +concepts.synchronization.layouts.guidance: '呼叫 {transition} 時,提供子資源上一次使用時的佈局。應用程式在記錄命令,以及在渲染階段之間傳遞紋理時,負責追蹤這個狀態。' +concepts.synchronization.layouts.title: '紋理佈局' +concepts.synchronization.readback.description: '{isCompleted} 回報 GPU 的完成狀態。透過命令記錄的回讀還需要一個步驟:將結果從內部回讀空間複製到應用程式的目標記憶體。' +concepts.synchronization.readback.details: '{commandBufferDownload} 記錄向內部回讀空間複製資料的 GPU 命令。提交完成後,程式庫在回收命令緩衝區時執行最後的 CPU 複製。對這次回讀提交的完成值呼叫 {wait},會等待 GPU 完成,並處理該佇列已完成的緩衝區,從而完成這兩個步驟。呼叫返回前,目標記憶體須保持已配置狀態,受控記憶體須保持固定。' +concepts.synchronization.readback.guidance: '只輪詢 {isCompleted} 不會執行最後的 CPU 複製;等待其他佇列,也不會回收回讀佇列中已完成的緩衝區。上傳與回讀何時使用直接記憶體存取或暫存空間,見{link}。' +concepts.synchronization.readback.guidance.link: '資源管理' +concepts.synchronization.readback.title: '回讀完成' +concepts.synchronization.reuse.description: '三角形教學在每個影格完成後才重複使用資料。若要讓影格重疊執行,應為每個尚未完成的影格準備獨立的可變儲存空間,並追蹤何時可以再次使用。修改資料前,須等待 GPU 完成對相關位元組的存取;釋放資源前,則須等待它的所有使用結束。' +concepts.synchronization.reuse.details: '調整大小與結束程式遵循相同順序:先停止新的資源存取,等待既有存取結束,再替換或釋放資源。呼叫 {swapChainResize} 或釋放資源、上下文前,須先完成上述等待。三角形教學已經逐影格等待,因此可以在回呼之間調整大小。' +concepts.synchronization.reuse.guidance: '{swapChainPresent} 在呈現後向圖形佇列發出訊號並等待。因此,即使移除明確的提交等待,三角形教學仍會在呈現時等待。獨立提交到其他佇列的工作,需要另外追蹤其完成狀態。' +concepts.synchronization.reuse.title: '資源重複使用' +concepts.synchronization.timelines.context: 'CPU 若要在消費者完成後讀取結果、覆寫共用資料或釋放資源,須先等待這次提交完成:' +concepts.synchronization.timelines.description: '時間線用遞增值識別佇列進度。{submit} 傳回的 {timelineValue} 同時包含時間線和本次提交的值。不同時間線上的 {value} 數值不能直接比較。' +concepts.synchronization.timelines.details: '設 {producer} 與 {consumer} 是同一上下文中兩個佇列上已記錄的命令緩衝區,後者使用前者寫入的資料。提交時傳入以下相依關係:' +concepts.synchronization.timelines.guidance: '消費者所在的佇列會先等待傳入的完成值,再執行命令。CPU 不必呼叫 {producedWait},可以繼續處理其他工作。共用資源須保留到 {consumed} 完成,同時仍需記錄消費者存取所要求的紋理轉換。' +concepts.synchronization.timelines.notes: '{queueTimelineSignal} 傳回的值,同樣可以透過 {wait} 等待,也可以作為另一個佇列的相依條件。{signal} 將完成點排在先前已提交的工作之後,GPU 完成這些工作後就會到達該點。' +concepts.synchronization.timelines.title: '時間線與佇列相依關係' +concepts.synchronization.title: '同步' +home.actions.reference: '瀏覽 API' +home.actions.tutorial: '從三角形開始' +home.entries.description: '教學、範例與 API 參考' +home.entries.label: '文件分類' +home.entries.reference.action: '探索 API' +home.entries.reference.category: '參考' +home.entries.reference.description: '查閱 API 型別、成員與宣告' +home.entries.reference.title: 'API 參考' +home.entries.samples.action: '瀏覽範例' +home.entries.samples.category: '範例' +home.entries.samples.description: '可直接執行的圖形與計算範例' +home.entries.samples.title: '範例' +home.entries.title: '文件' +home.entries.tutorial.action: '開始教學' +home.entries.tutorial.category: '教學' +home.entries.tutorial.description: '從空白專案開始,繪製第一個三角形' +home.entries.tutorial.title: '第一個三角形' +home.introduction.accent: '跨平台圖形應用' +home.introduction.description: 'Zenith.NET 提供統一的圖形與計算 API,支援 DirectX、Metal 與 Vulkan' +home.introduction.title: '以 .NET 開發{lineBreak}{accent}' +home.meta.description: '透過 Zenith.NET 開發跨平台圖形與計算應用程式,以共用 API 使用 DirectX、Metal 與 Vulkan' +home.scene.description: '可互動的旋轉幾何體。拖動或使用方向鍵調整視角。' +home.scene.label: '幾何體顯示' +home.scene.surface: '表面' +home.scene.wireframe: '線框' +home.title: '適用於 .NET 的現代 RHI' +learning.concepts.description: '選擇資源用途、描述著色器資料與協調 GPU 執行' +learning.concepts.execution.description: '命令記錄、提交與資源生命週期' +learning.concepts.platforms.description: '原生呈現與 UI 渲染控制項' +learning.concepts.resources.description: '資源用途、記憶體放置與檢視' +learning.concepts.shaders.description: 'C# 與 Slang 的資料佈局和繫結約定' +learning.concepts.synchronization.description: '相依關係、可見性與完成狀態' +learning.concepts.title: '核心概念' +learning.description: '初次使用 Zenith.NET,可以從三角形教學開始。完成後,再依需要查閱資源管理、著色器資料與同步等概念,或透過範例了解各種圖形技術的實作。' +learning.entries.samples.action: '瀏覽範例' +learning.entries.samples.description: '幾何體、計算、光線查詢與網格著色的 C# 和 Slang 實作' +learning.entries.tutorial.action: '開啟教學' +learning.entries.tutorial.description: '建立視窗並渲染三角形的主控台應用程式' +learning.meta.description: 'Zenith.NET 程式設計模型的入門教學與概念說明' +learning.title: '學習' +reference.description: '資源、命令與平台整合的參考文件' +reference.entries.commands.description: '圖形、計算與傳輸命令' +reference.entries.commands.label: '記錄命令' +reference.entries.context.description: '為所選後端建立 GPU 資源' +reference.entries.context.label: '從這裡開始' +reference.meta.description: 'Zenith.NET 的命名空間、型別與成員' +reference.navigation.core: '核心 API 參考' +reference.title: 'API 參考' +samples.computeShader.description: '範例載入 {assetsTexturesShokoPng},透過一次計算分派將影像轉成灰階,再顯示輸出紋理。轉換只執行一次,後續影格顯示同一結果。渲染器展示了取樣紋理與可寫紋理的繫結、向上取整群組數量以覆蓋整張影像的計算方式,以及著色器中的影像邊界檢查。' +samples.computeShader.details: '{computeShaderRendererCs} · {computeShaderSlang}' +samples.computeShader.title: '計算著色器' +samples.cube.description: '旋轉立方體加入索引繪製、常數緩衝區中的模型、檢視和投影矩陣,以及深度測試。視窗調整大小時,會重建 {d32FloatS8UInt} 深度/樣板紋理。' +samples.cube.details: '{spinningCubeRendererCs} · {spinningCubeSlang}' +samples.cube.title: '旋轉立方體' +samples.description: '每個範例均由 C# 渲染器與 Slang 著色器組成,集中說明一項技術。完整的應用程式設定與渲染順序見{link}。' +samples.description.link: '第一個三角形' +samples.execution.description: '執行 {link} 專案,並從主控台選單選擇範例。' +samples.execution.description.link: 'ZenithTutorials' +samples.execution.title: '執行範例' +samples.host.description: '{appCs} 初始化上下文、視窗和交換鏈。每個影格取得命令緩衝區,呼叫所選渲染器,提交命令並呈現結果。{iRendererCs} 規定渲染器的更新、渲染、調整大小和釋放操作。' +samples.host.details: '計算與光線追蹤渲染器產生離屏紋理。{texturePresenterCs} 與 {presentTextureSlang} 將這些紋理繪製到目前的輸出紋理,接著由共用宿主提交命令並呈現這個影格。' +samples.host.title: '宿主與呈現' +samples.indirectDrawing.description: '間接繪製透過索引繪製引數緩衝區,以及儲存各執行個體資料的結構化緩衝區,繪製多個立方體。CPU 提供繪製引數並更新變換。' +samples.indirectDrawing.details: '{indirectDrawingRendererCs} · {indirectDrawingSlang}' +samples.indirectDrawing.title: '間接繪製' +samples.meshShading.description: '任務著色器剔除球體執行個體,將保留的索引傳給負責產生幾何體的網格著色器。建立管線前,渲染器檢查 {contextCapabilitiesMeshShadingSupported}。' +samples.meshShading.details: '{meshShadingRendererCs} · {meshShadingSlang}' +samples.meshShading.title: '網格著色' +samples.rayTracing.description: '此範例為地面與程序化球體建立底層及頂層加速結構,再於計算著色器內執行內嵌光線查詢。初始化前檢查 {contextCapabilitiesRayTracingSupported}。' +samples.rayTracing.details: '{rayTracingRendererCs} · {rayTracingSlang}' +samples.rayTracing.title: '光線追蹤' +samples.title: '範例' +samples.triangle.description: '三角形範例將頂點緩衝區與對應的輸入佈局關聯,再透過圖形管線繪製三個頂點。' +samples.triangle.details: '{helloTriangleRendererCs} · {helloTriangleSlang} · {link}' +samples.triangle.details.link: '完整教學' +samples.triangle.title: 'Hello Triangle' +samples.workloads.description: '主存放庫的{link}包含規模較大的應用程式,這些專案直接參考程式庫原始碼。' +samples.workloads.description.link: 'Experiments 目錄' +samples.workloads.details: '視窗實驗專案採用相同的 Windows、macOS 和 Linux/X11 呈現路徑。Avalonia、WinForms、WPF、WinUI/Uno 和 MAUI 控制項的影格生命週期及實作程式碼見{link}。' +samples.workloads.details.link: '平台整合' +samples.workloads.table.cornellBox.example: '{link}' +samples.workloads.table.cornellBox.example.link: 'CornellBox' +samples.workloads.table.cornellBox.whatItDemonstratesAndRequires: '路徑追蹤、降噪、色調對應、影像升頻與 ImGui 控制項。需要光線追蹤支援。' +samples.workloads.table.fluidTank.example: '{link}' +samples.workloads.table.fluidTank.example.link: 'FluidTank' +samples.workloads.table.fluidTank.whatItDemonstratesAndRequires: '計算流體模擬、模擬階段之間的相依關係,以及多通道表面渲染。' +samples.workloads.table.headings.example: '範例' +samples.workloads.table.headings.whatItDemonstratesAndRequires: '技術與執行要求' +samples.workloads.table.inkCanvas.example: '{link}' +samples.workloads.table.inkCanvas.example.link: 'InkCanvas' +samples.workloads.table.inkCanvas.whatItDemonstratesAndRequires: '在原生視窗中進行 Skia 繪圖與輸入處理。需要目標平台的後端與 Skia 原生程式庫。' +samples.workloads.table.platformDetection.example: '{link}' +samples.workloads.table.platformDetection.example.link: 'PlatformDetection' +samples.workloads.table.platformDetection.whatItDemonstratesAndRequires: '嘗試為每個後端建立上下文,並回報裝置功能。建立失敗時顯示為不支援,原因可能是裝置、驅動程式或缺少執行時所需的元件。' +samples.workloads.title: '綜合應用' +tutorial.context.description: '{graphicsContext} 透過後端連接應用程式與 GPU,並提供建立渲染資源的方法。' +tutorial.context.details: '在{emphasis}插入上下文初始化程式碼:' +tutorial.context.details.emphasis: 'using 指示詞之後、{iWindowWindow} 之前' +tutorial.context.guidance: '各分支為目前平台選擇後端並要求啟用驗證。{validationMessage} 訊息會輸出到主控台。' +tutorial.context.imports: '在 {programCs} 頂端加入以下 using 指示詞:' +tutorial.context.title: '圖形上下文' +tutorial.description: '本教學從空白的 .NET 主控台專案開始,逐步建立視窗,並在其中繪製一個彩色三角形。' +tutorial.details: '本教學分三個階段確認結果:空白視窗、單色背景,以及彩色三角形。每完成一個階段,先執行程式檢查畫面,再繼續下一步。' +tutorial.draw.context: '{draw} 的引數如下:' +tutorial.draw.description: '在 {windowRender} 回呼中,用以下命令替換 {addTheTriangleDrawCommandsHereLater},位置保持在 {beginRenderPass} 與 {endRenderPass} 之間:' +tutorial.draw.details: '{setPipeline} 選擇著色器和渲染狀態。後端按管線的輸入佈局解釋頂點繫結,因此這一步必須先於頂點繫結。' +tutorial.draw.guidance: '{setVertexBufferVertexBuffer} 從緩衝區的位元組位移 0 開始,將已上傳的頂點資料繫結到輸入槽 0,對應 {inputLayouts} 中唯一的項目。' +tutorial.draw.notes: '這些呼叫記錄繪製命令。既有的 {submitWait} 提交命令並等待 GPU 完成,接著由 {present} 要求顯示完成的影像。保留通道開始時的清除操作,讓三角形以外的區域也有確定的背景色。' +tutorial.draw.table.firstInstance.meaning: '執行個體編號從零開始。' +tutorial.draw.table.firstVertex.meaning: '從緩衝區中的第一個頂點開始。' +tutorial.draw.table.headings.argument: '引數' +tutorial.draw.table.headings.description: '值' +tutorial.draw.table.headings.meaning: '意義' +tutorial.draw.table.instanceCount.meaning: '繪製一個三角形執行個體。' +tutorial.draw.table.vertexCount.meaning: '讀取三個頂點。' +tutorial.draw.title: '繪製命令' +tutorial.execution.description: '建置並執行 {firstTriangle} 專案。' +tutorial.execution.details: '視窗中應出現一個三角形:上方為紅色,右下方為綠色,左下方為藍色,背景為深色。頂點色彩經過內插,在三角形內形成平滑的漸層。' +tutorial.execution.guidance: '調整視窗大小時,影像的像素尺寸會改變,頂點座標則維持不變。視口將這些座標對應到新的寬度與高度,因此改變視窗的寬高比會拉伸三角形。' +tutorial.execution.title: '執行應用程式' +tutorial.frame.commands.context: '{endRenderPass} 之後的第二次轉換讓輸出紋理進入可呈現的佈局。{submit} 結束記錄並提交命令緩衝區,{wait} 阻塞至本次提交完成,隨後 {present} 請求顯示渲染結果。' +tutorial.frame.commands.description: '渲染通道將寫入同一組附件的繪製操作放在一起。本通道使用交換鏈的輸出紋理接收色彩結果。{colorAttachmentClear} 指定以 RGBA 色彩初始化附件,並在通道結束時保留內容。{beginRenderPass} 依這些設定記錄通道的開始命令。' +tutorial.frame.commands.details: '集合中有一個色彩附件。{null} 表示此通道不使用深度/樣板附件。' +tutorial.frame.commands.guidance: '{beginRenderPass} 預設讓視口與裁剪區域覆蓋整個附件。視口將渲染座標映射為像素位置,裁剪區域則限制可以寫入的範圍。' +tutorial.frame.commands.title: '清除、提交與呈現' +tutorial.frame.description: '先將視窗填滿單一背景色,這個操作稱為清除。背景正常顯示後,就能確認呈現目標、命令提交與呈現流程已連接完成,接著再加入三角形的頂點與著色器。' +tutorial.frame.details: 'Silk.NET 在需要繪製一個影格時呼叫渲染回呼。本範例不使用回呼傳入的時間間隔,因此將該引數命名為 {value}。在{emphasis}註冊回呼:' +tutorial.frame.details.emphasis: '{windowRun} 之前' +tutorial.frame.target.description: '{graphicsQueueCommandBuffer} 傳回可直接記錄的命令緩衝區。記錄描述 GPU 工作,提交後才開始執行。' +tutorial.frame.target.details: '紋理佈局描述操作如何存取紋理。第一次 {transition} 讓輸出紋理準備好作為色彩附件。這裡的 {default} 選擇 mip 級別 0 與陣列層 0,也就是輸出紋理的基本影像。由於這個通道會清除整張影像,可以指定 {undefined},允許丟棄先前內容。' +tutorial.frame.target.guidance: '呈現後可能換用另一張影像,因此每個影格都要重新取得目前的輸出紋理。' +tutorial.frame.target.title: '準備輸出紋理' +tutorial.frame.title: '第一個影格' +tutorial.geometry.data.description: '在{emphasis}新增頂點陣列。後續資源初始化也放在該回呼之前,順序如下。' +tutorial.geometry.data.description.emphasis: '{windowRender} 之前' +tutorial.geometry.data.details: '每個條目構造一個 {vertex},內部的兩個 {new} 表示式分別提供 {vector3} 位置和 {vector4} 顏色。三個位置對應上角、右下角和左下角。頂點著色器將 {w} 作為第四個位置座標;w 為 1 時,x、y 也就是正規化裝置座標,-1 與 +1 對應影像邊界,0 對應中心,與像素尺寸無關。' +tutorial.geometry.data.guidance: '每個色彩包含紅、綠、藍與 alpha 分量,alpha 設為 1。三個頂點的 z 座標均為 0,位於同一平面。' +tutorial.geometry.data.title: '頂點位置與顏色' +tutorial.geometry.description: '三角形的每個頂點都有位置與色彩。GPU 依三個位置決定三角形的形狀,再對頂點色彩內插,算出內部各處的色彩。' +tutorial.geometry.format.description: '在{emphasis}追加頂點宣告:' +tutorial.geometry.format.description.emphasis: '{programCs} 的結尾處、清理陳述式之後' +tutorial.geometry.format.details: '{file} 將型別的使用範圍限定在 {programCs},{layoutKindSequential} 則保留欄位的宣告順序。{position} 包含三個 32 位元浮點數,位元組位移為 0;{color} 包含四個,位元組位移為 12。因此,每個頂點占 28 位元組。稍後會透過輸入佈局描述這個排列,讓 GPU 正確讀取各欄位。' +tutorial.geometry.format.imports: '在 {programCs} 頂端加入以下 using 指示詞,以使用向量型別與結構佈局屬性:' +tutorial.geometry.format.title: '頂點表示' +tutorial.geometry.title: '頂點資料' +tutorial.geometry.upload.context: '{fixed} 可避免記憶體回收行程在位址使用期間移動陣列。對於這個 CPU 可寫緩衝區,{upload} 會映射記憶體、複製資料,再解除映射後返回,因此只需在呼叫期間固定陣列。頂點資料在初始化時上傳一次即可;緩衝區則必須保留到渲染結束。' +tutorial.geometry.upload.description: '將頂點存入 {buffer},供 GPU 在繪製時讀取。緊接在頂點陣列之後,加入配置與上傳程式碼:' +tutorial.geometry.upload.details: '配置大小為 {sizeofVertexVerticesLength},即三個 28 位元組頂點,共 84 位元組。{bufferUsagesVertex} 宣告頂點輸入用途,{cpuWriteOnly} 允許 CPU 直接初始化。描述中的跨距記錄元素大小,隨後定義的輸入佈局指定 GPU 如何讀取各個頂點屬性。' +tutorial.geometry.upload.guidance: '配置空間不會初始化緩衝區內容。{upload} 使用資料描述中的來源指標與位元組數,將陣列複製到目標位元組位移 0。' +tutorial.geometry.upload.imports: '在 {programCs} 頂端的 using 指示詞中加入 {bufferAlias},以區分 Zenith.NET 的緩衝區型別與 {systemBuffer}。' +tutorial.geometry.upload.notes: '在 {programCs} 結尾的清理程式碼中,緊接在 {swapChainDispose} 之前加入 {vertexBufferDispose}。較大型靜態幾何體所需的 GPU 專用儲存與上傳方式,見{link}。' +tutorial.geometry.upload.notes.link: '資源管理' +tutorial.geometry.upload.title: '緩衝區配置與上傳' +tutorial.input.description: 'GPU 需要知道位置、色彩等頂點屬性儲存在哪裡。輸入佈局指定各屬性的格式與位元組位移,並以跨距表示兩個相鄰頂點相隔多少位元組。在建立著色器之後加入以下程式碼:' +tutorial.input.details: '{inputLayoutAdd} 將屬性依序排列,並將每個屬性的大小加到跨距中。位移是根據這裡提供的格式計算,不是透過檢查 C# 結構取得。這兩個欄位的佈局如下:' +tutorial.input.guidance: '{semanticIndex} 預設為 0,對應著色器中的 {pOSITION0} 與 {cOLOR0}。位置與色彩存放在同一個頂點緩衝區,因此管線只需在槽 0 使用一個輸入佈局。若 C# 結構的欄位順序或填充改變,也要一併調整此佈局。' +tutorial.input.table.headings.byteOffset: '位元組位移' +tutorial.input.table.headings.cField: 'C# 欄位' +tutorial.input.table.headings.format: '格式' +tutorial.input.table.headings.shaderInput: '著色器輸入' +tutorial.input.table.nextVertex.cField: '下一個頂點' +tutorial.input.table.nextVertex.format: '總跨距:28 位元組' +tutorial.input.table.nextVertex.shaderInput: '下一筆輸入記錄' +tutorial.input.table.vertexColor.format: '{float4}(16 位元組)' +tutorial.input.table.vertexPosition.format: '{float3}(12 位元組)' +tutorial.input.title: '頂點輸入佈局' +tutorial.lifecycle.description: '每個影格依次執行以下操作:' +tutorial.lifecycle.details: '關閉視窗後,{run} 返回,程式繼續執行清理程式碼。每個影格都已等待其提交完成,因此現在可以釋放這些命令使用的資源。{windowRun} 之後完整的清理程式碼如下:' +tutorial.lifecycle.guidance: '先釋放交換鏈,再銷毀其原生視窗;先釋放應用程式資源,再釋放上下文。已提交的命令緩衝區由佇列回收,輸出紋理由交換鏈管理,兩者都不需要單獨呼叫 {dispose}。' +tutorial.lifecycle.title: '影格生命週期與清理' +tutorial.pipeline.behavior: '在輸入佈局之後建立管線:' +tutorial.pipeline.context: '{cullNone} 關閉面剔除,因此無論頂點在畫面中呈順時針或逆時針排列,三角形都會被繪製。' +tutorial.pipeline.description: '{graphicsPipeline} 將頂點佈局、兩個著色器,以及圖元組裝和附件輸出所需的設定組合在一起。' +tutorial.pipeline.details: '著色器負責處理頂點與片元。其餘管線設定決定圖元如何組裝、是否剔除特定朝向的面,以及如何執行深度測試和色彩混合:' +tutorial.pipeline.guidance: '管線顏色格式必須匹配渲染通道附件,因此直接取自 {swapChainDescFormat}。{count1} 表示每像素一個取樣點。' +tutorial.pipeline.item: '{triangleList} 將每組連續的三個頂點組裝成一個三角形。' +tutorial.pipeline.notes: '{depthNone} 關閉深度測試和深度寫入,與通道沒有深度附件的設定一致。' +tutorial.pipeline.reference: '{opaque} 關閉混合,因此片元著色器輸出直接替換三角形內部的背景色。' +tutorial.pipeline.title: '圖形管線' +tutorial.pipeline.usage: '管線建立完成後即可釋放著色器物件。渲染期間保留管線,在清理程式碼中將 {pipelineDispose} 放在 {vertexBufferDispose} 之前。' +tutorial.presentation.title: '圖形上下文與呈現' +tutorial.project.context: '在專案建置設定中啟用{emphasis}({allowUnsafeBlocks})。視窗輔助程式碼的原生呼叫和頂點上傳需要不安全程式碼。' +tutorial.project.context.emphasis: '允許不安全的程式碼' +tutorial.project.description: '建立名為 {firstTriangle} 的 C# 主控台專案,目標框架設為 .NET 10。' +tutorial.project.details: '為專案加入以下 NuGet 套件:' +tutorial.project.guidance: '{zenithNET} 提供統一渲染 API,三個後端套件提供各平台的實作。{zenithNETCompiler} 為所選後端編譯稍後介紹的 Slang 著色器。Silk.NET 負責視窗建立與事件處理。' +tutorial.project.title: '專案設定' +tutorial.requirements.context: '{link}及其{detail}提供了本教學的參考實作。' +tutorial.requirements.context.detail: '共用宿主程式' +tutorial.requirements.context.link: 'Hello Triangle 範例' +tutorial.requirements.description: '需要 {emphasis},並具備基礎 C# 知識。應用程式以 {net10} 為目標框架。GPU 與驅動程式須支援所在平台選用的後端:' +tutorial.requirements.description.emphasis: '.NET 10 SDK' +tutorial.requirements.guidance: 'Zenith.NET 渲染到應用程式提供的原生呈現目標。Silk.NET.Windowing 建立視窗並處理事件。macOS 使用由 {cAMetalLayerCs} 表示的 Metal 圖層,視窗輔助程式碼負責將它連接到視窗。' +tutorial.requirements.table.headings.graphicsBackend: '圖形後端' +tutorial.requirements.table.headings.platform: '平台' +tutorial.requirements.table.linux.graphicsBackend: 'Vulkan 1.4' +tutorial.requirements.table.linux.platform: 'Linux(X11 或 XWayland)' +tutorial.requirements.table.macOS.graphicsBackend: 'Metal 4' +tutorial.requirements.table.macOS.platform: 'macOS' +tutorial.requirements.table.windows.graphicsBackend: 'DirectX 12' +tutorial.requirements.table.windows.platform: 'Windows' +tutorial.requirements.title: '準備事項' +tutorial.resize.context: '再次建置並執行程式。調整視窗大小後,背景應繼續填滿整個視窗:每次開始新的渲染通道時,視口與裁剪區域都會依附件的新尺寸設定。保留渲染回呼,稍後將在這個通道內繪製三角形。' +tutorial.resize.description: '畫面緩衝區尺寸改變時,交換鏈也要跟著調整。在渲染回呼之後、{windowRun} 之前註冊 {framebufferResize} 回呼:' +tutorial.resize.details: '這裡接收的是以像素為單位的{link},而不是視窗邏輯尺寸的變化。視窗最小化時,畫面緩衝區的寬度或高度可能變成零。此時,尺寸變更回呼保留現有交換鏈,不進行調整。渲染回呼也會在任一尺寸為零時直接返回,直到畫面緩衝區恢復有效尺寸後才繼續繪製。' +tutorial.resize.details.link: '畫面緩衝區大小變更' +tutorial.resize.guidance: '渲染回呼會等待目前影格的提交完成,再呼叫 {present}。因此,尺寸變更回呼替換交換鏈影像時,先前影格的工作已經結束。完成狀態與資源生命週期的要求,詳見{link}。' +tutorial.resize.guidance.link: '同步' +tutorial.resize.title: '視窗尺寸變化' +tutorial.shaders.compilation.context: '{appContextBaseDirectory} 讓程式從輸出目錄載入已複製的著色器。即使從其他工作目錄啟動程式,尋找檔案的位置也不會改變。' +tutorial.shaders.compilation.description: '將 {triangleSlang} 的檔案屬性{emphasis}設為{detail},建置時便會將著色器複製到執行檔所在目錄。' +tutorial.shaders.compilation.description.detail: '有更新時才複製' +tutorial.shaders.compilation.description.emphasis: '複製到輸出目錄' +tutorial.shaders.compilation.details: '回到 {programCs},在頂點上傳之後、渲染回呼之前加入著色器初始化:' +tutorial.shaders.compilation.guidance: '{zenithCompiler} 為 {contextGraphicsApi} 指定的後端編譯原始碼,{createShader} 再依編譯後的描述建立著色器物件。進入點名稱 {vSMain} 與 {fSMain} 分別選取 Slang 檔案中定義的兩個函式。' +tutorial.shaders.compilation.title: '編譯著色器' +tutorial.shaders.context: '{fSInput} 連接兩個著色器階段。頂點著色器將裁剪空間位置寫入 {sVPOSITION},GPU 據此判斷三角形的可見部分。{cOLOR0} 欄位傳遞頂點色彩,經過三角形內部的內插後再交給片元著色器。兩個階段必須採用相同的色彩型別與語義。' +tutorial.shaders.description: '著色器是在 GPU 上執行的程式。頂點著色器決定每個頂點的位置,片元著色器則決定影像中被覆蓋位置的色彩。接下來會將兩個階段寫在同一個 Slang 檔案,並分別定義進入點,也就是各階段開始執行的函式。' +tutorial.shaders.details: '建立 {triangleSlang},先定義輸入與輸出結構:' +tutorial.shaders.fragment.description: '在同一檔案中追加片元進入點:' +tutorial.shaders.fragment.details: '光柵化判定三角形在影像中的覆蓋範圍,並在這些位置產生片元。每個片元的色彩由三個頂點的色彩內插而得。{fSMain} 傳回這個色彩,{sVTARGET} 則將結果送到第一個色彩附件。' +tutorial.shaders.fragment.title: '片元著色' +tutorial.shaders.guidance: '{vSInput} 定義頂點著色器輸入。{pOSITION0} 和 {cOLOR0} 按語義識別屬性,C# 欄位名稱本身不建立這一映射。' +tutorial.shaders.title: '著色器階段' +tutorial.shaders.vertex.description: '在 {triangleSlang} 中追加頂點進入點:' +tutorial.shaders.vertex.details: 'GPU 為每個輸入頂點呼叫這一進入點,補充齊次座標 {w} 並傳遞顏色。頂點處理結束後,位置要除以 w。本例 w 為 1,x、y、z 保持不變,可直接解釋為正規化裝置座標。' +tutorial.shaders.vertex.title: '頂點著色' +tutorial.surface.description: '在{emphasis}指定原生呈現目標:' +tutorial.surface.description.emphasis: '{windowCenter} 之後、{windowRun} 之前' +tutorial.surface.details: '畫面緩衝區是視窗用來顯示的像素影像。{surface} 描述原生呈現目標及其尺寸,{framebufferSize} 則提供像素大小。啟用顯示縮放時,這個大小可能與視窗的邏輯尺寸不同。' +tutorial.surface.guidance: '呈現目標提供後端所需的原生控制代碼:Windows 使用 Win32 視窗,Linux 使用 X11 顯示與視窗,macOS 使用已連接的 Metal 圖層。' +tutorial.surface.title: '原生呈現目標' +tutorial.swapChain.context: '交換鏈需要上下文與視窗才能運作。將 {programCs} 結尾的 {windowDispose} 換成以下釋放順序:' +tutorial.swapChain.description: '緊接呈現目標描述,建立交換鏈:' +tutorial.swapChain.details: '{swapChain} 管理視窗呈現的影像。{drawable} 以影像資源 {texture} 的形式提供目前影像。渲染後,{present} 請求顯示該影像,並推進到下一個輸出紋理。' +tutorial.swapChain.guidance: '{b8G8R8A8UNorm} 按藍、綠、紅和 alpha 順序儲存四個 8 位元通道。{uNorm} 將整數 0–255 對應到 0–1。著色器仍輸出邏輯 RGBA 值,格式只規定儲存表示;管線透過 {swapChainDescFormat} 匹配附件。' +tutorial.swapChain.title: '交換鏈' +tutorial.title: '第一個三角形' +tutorial.troubleshooting.description: '結合主控台診斷與三個檢查點定位失敗階段:' +tutorial.troubleshooting.details: '{link}與{detail}可用於核對頂點資料、輸入佈局和繪製操作。該範例將視窗與提交邏輯放入共用宿主程式,本教學則保留在 {programCs} 中。{context}進一步介紹索引繪製、變換與深度測試。' +tutorial.troubleshooting.details.context: '旋轉立方體' +tutorial.troubleshooting.details.detail: 'Slang 著色器' +tutorial.troubleshooting.details.link: '範例渲染器' +tutorial.troubleshooting.table.backend.check: '檢查選取的後端是否受到裝置與已安裝的圖形驅動程式支援。' +tutorial.troubleshooting.table.backend.symptom: '後端建立失敗' +tutorial.troubleshooting.table.drawing.check: '檢查上傳大小、輸入佈局、管線選擇,以及繪製命令是否位於渲染通道內。' +tutorial.troubleshooting.table.drawing.symptom: '背景出現但三角形未出現' +tutorial.troubleshooting.table.headings.check: '檢查項目' +tutorial.troubleshooting.table.headings.symptom: '徵狀' +tutorial.troubleshooting.table.input.check: '檢查跨距是否為 28 位元組,位置與色彩是否分別從位移 0 和 12 位元組開始。' +tutorial.troubleshooting.table.input.symptom: '頂點位置或色彩異常' +tutorial.troubleshooting.table.shaders.check: '檢查複製的 {triangleSlang}、進入點拼寫,以及編譯器回報的診斷資訊。' +tutorial.troubleshooting.table.shaders.symptom: '背景色正常顯示,但著色器載入失敗' +tutorial.troubleshooting.table.window.check: '確認 .NET 專案可成功建置,且僅含視窗的步驟可在桌面工作階段中執行。在 Linux 上,檢查 X11 或 XWayland 是否可用。' +tutorial.troubleshooting.table.window.symptom: '視窗未開啟' +tutorial.troubleshooting.title: '問題排查' +tutorial.window.description: '將 {cocoaHelperCs} 下載至專案中。此輔助類別負責將 Metal 圖層連接到 macOS 視窗。' +tutorial.window.details: '將自動產生的 {programCs} 內容換成以下程式碼。它使用最上層陳述式,依書寫順序執行,不需要明確撰寫 {main} 方法。後續各節會指出新程式碼應加入的位置:' +tutorial.window.guidance: '{graphicsAPINone} 將圖形上下文的建立交給 Zenith.NET。{initialize} 建立原生視窗,讓程式取得視窗系統的控制代碼;{center} 把視窗放在螢幕中央。{run} 持續處理事件直到視窗關閉,之後再執行 {dispose} 釋放視窗。' +tutorial.window.notes: '建置並執行程式,確認視窗可以開啟、移動、調整大小及關閉。此時尚未提交渲染命令,視窗內容還沒有定義。關閉視窗後再繼續。' +tutorial.window.title: '建立視窗' +ui.action.copy: '複製' +ui.action.navigate: '巡覽' +ui.action.open: '開啟' +ui.action.source: '檢視原始碼' +ui.api.browse: '瀏覽命名空間與型別。' +ui.api.clearTypeSearch: '清除型別搜尋' +ui.api.findType: '尋找型別' +ui.api.loadError: '無法載入型別。重新載入此頁面以重試。' +ui.api.loadingNamespaces: '正在載入命名空間…' +ui.api.loadingTypes: '正在載入型別…' +ui.api.matchingTypes: '相符的型別' +ui.api.namespace: '命名空間' +ui.api.namespaces: '命名空間' +ui.api.noNamespaceTypes: '此命名空間中沒有型別。' +ui.api.noTypes: '沒有相符的型別。' +ui.api.types: '型別' +ui.content.reference: '參考' +ui.content.source: '原始碼' +ui.content.tutorial: '教學' +ui.contents.close: '關閉目錄' +ui.contents.open: '開啟目錄' +ui.contents.title: '目錄' +ui.footer.caption: '面向 .NET 的現代 RHI' +ui.footer.label: '頁尾' +ui.language.label: '語言' +ui.language.unavailable: '未翻譯' +ui.members.clear: '清除成員搜尋' +ui.members.close: '關閉成員尋找工具' +ui.members.empty: '沒有相符的成員。' +ui.members.open: '前往成員' +ui.members.placeholder: '名稱或簽章…' +ui.members.search: '搜尋成員' +ui.members.title: '尋找成員' +ui.members.undeclared: '此型別沒有宣告的成員。' +ui.navigation.api: 'API' +ui.navigation.concepts: '概念' +ui.navigation.home: '首頁' +ui.navigation.label: '主要導覽' ui.navigation.skip: 跳至正文 -ui.navigation.toggle: "切換導覽" -ui.outline.title: "本頁內容" -ui.reference.assembly: "組件" -ui.reference.classes: "類別" -ui.reference.constructors: "建構函式" -ui.reference.declaration: "C# 型別宣告" -ui.reference.delegates: "委派" -ui.reference.derived: "衍生型別" -ui.reference.enums: "列舉" -ui.reference.events: "事件" -ui.reference.examples: "範例" -ui.reference.exceptions: "例外狀況" -ui.reference.extensionMethods: "擴充方法" -ui.reference.fields: "欄位" -ui.reference.implementations: "明確介面實作" -ui.reference.implements: "實作" -ui.reference.inheritance: "繼承" -ui.reference.inheritedMembers: "繼承的成員" -ui.reference.interfaces: "介面" -ui.reference.metadata: "型別中繼資料" -ui.reference.methods: "方法" -ui.reference.namespace: "命名空間" -ui.reference.open: "開啟 {name} 的參考" -ui.reference.operators: "運算子" -ui.reference.parameters: "參數" -ui.reference.properties: "屬性" -ui.reference.related: "請參閱" -ui.reference.relationships: "繼承與中繼資料" -ui.reference.remarks: "備註" -ui.reference.returns: "傳回" -ui.reference.structs: "結構" -ui.reference.typeParameters: "型別參數" -ui.reference.value: "值" -ui.reference.values: "值" -ui.search.close: "關閉搜尋" -ui.search.empty: "找不到「{query}」的結果。" -ui.search.hint: "搜尋教學、概念、範例與 API 參考。" -ui.search.loading: "正在載入搜尋…" -ui.search.more: "顯示更多結果" -ui.search.pending: "正在搜尋…" -ui.search.placeholder: "輸入搜尋內容" -ui.search.resultCount: "結果:{count}" -ui.search.title: "搜尋文件" -ui.search.unavailable: "搜尋暫時無法使用,可直接開啟下方頁面。" +ui.navigation.toggle: '切換導覽' +ui.outline.title: '本頁內容' +ui.reference.assembly: '組件' +ui.reference.classes: '類別' +ui.reference.constructors: '建構函式' +ui.reference.declaration: 'C# 型別宣告' +ui.reference.delegates: '委派' +ui.reference.derived: '衍生型別' +ui.reference.enums: '列舉' +ui.reference.events: '事件' +ui.reference.examples: '範例' +ui.reference.exceptions: '例外狀況' +ui.reference.extensionMethods: '擴充方法' +ui.reference.fields: '欄位' +ui.reference.implementations: '明確介面實作' +ui.reference.implements: '實作' +ui.reference.inheritance: '繼承' +ui.reference.inheritedMembers: '繼承的成員' +ui.reference.interfaces: '介面' +ui.reference.metadata: '型別中繼資料' +ui.reference.methods: '方法' +ui.reference.namespace: '命名空間' +ui.reference.open: '開啟 {name} 的參考' +ui.reference.operators: '運算子' +ui.reference.parameters: '參數' +ui.reference.properties: '屬性' +ui.reference.related: '請參閱' +ui.reference.relationships: '繼承與中繼資料' +ui.reference.remarks: '備註' +ui.reference.returns: '傳回' +ui.reference.structs: '結構' +ui.reference.typeParameters: '型別參數' +ui.reference.value: '值' +ui.reference.values: '值' +ui.search.close: '關閉搜尋' +ui.search.empty: '找不到「{query}」的結果。' +ui.search.hint: '搜尋教學、概念、範例與 API 參考。' +ui.search.loading: '正在載入搜尋…' +ui.search.more: '顯示更多結果' +ui.search.pending: '正在搜尋…' +ui.search.placeholder: '輸入搜尋內容' +ui.search.resultCount: '結果:{count}' +ui.search.title: '搜尋文件' +ui.search.unavailable: '搜尋暫時無法使用,可直接開啟下方頁面。' diff --git a/documents/locales/zh-TW/translation.md b/documents/locales/zh-TW/translation.md index e0f22b6f..3a968e68 100644 --- a/documents/locales/zh-TW/translation.md +++ b/documents/locales/zh-TW/translation.md @@ -2,7 +2,7 @@ ## 資源與結構 -[英文資源字典](../en-US/strings.yml)是唯一原文;專案規範請參閱[文件維護指南](../../authoring.md)。建立新譯本時,將英文檔案完整複製為本目錄的 `strings.yml`,保留首行 `### YamlMime:Resources`,並使用 UTF-8 編碼。後續更新應對照英文變更修訂既有譯文,不要重新覆寫整個檔案。本檔案 `translation.md` 永久保留,不發布至網站。 +[英文資源字典](../en-US/strings.yml)是唯一原文;專案規範請參閱[文件維護指南](../../maintenance.md)。建立新譯本時,將英文檔案完整複製為本目錄的 `strings.yml`,保留首行 `### YamlMime:Resources`,並使用 UTF-8 編碼。後續更新應對照英文變更修訂既有譯文,不要重新覆寫整個檔案。本檔案 `translation.md` 永久保留,不發布至網站。 導覽、章節順序、錨點、連結、格式、程式碼和圖片都在 `locales/` 外統一維護。不要在語言目錄內新增文章、TOC、範本、指令碼或設定。 @@ -65,39 +65,39 @@ docfx serve documents/_site --hostname 127.0.0.1 --port 8080 ## 術語 -| 英文 | 約定用語 | -| --- | --- | -| API / GPU / RHI | 保留縮寫,首次依原文說明 | -| barrier | 屏障 | -| bindless | 無繫結 | -| buffer | 緩衝區;`Buffer` 不變 | -| color attachment | 色彩附件 | -| command buffer | 命令緩衝區 | -| command queue | 命令佇列 | -| command recording | 命令記錄 | -| depth/stencil | 深度/樣板 | -| drawable | 目前影格的輸出紋理;`Drawable` 不變,不一律稱為交換鏈影像 | -| framebuffer | 畫面緩衝區,尺寸依原文的像素單位表述 | -| graphics context | 圖形上下文 | -| heap | 堆積 | -| pipeline | 管線;依情境區分圖形或計算管線 | -| rasterization | 光柵化 | -| readback | 從 GPU 回讀資料;下載檔案另用「下載」 | -| render pass | 渲染通道 | -| render target | 渲染目標 | -| resource | 資源 | -| resource ownership / lifetime | 資源所有權/生命週期 | -| resource usage | 資源用途 | -| shader / entry point | 著色器/進入點 | -| submit / submission | 提交/提交操作,與 GPU 執行區分 | -| surface | 呈現情境使用「原生呈現目標」;`Surface` 不變 | -| swap chain / presentation | 交換鏈/呈現 | -| texture | 紋理 | -| timeline | 時間線 | -| undefined | 未定義,不能改寫為某個預設結果 | -| upload | 上傳資料 | -| vertex / fragment | 頂點/片元 | -| view | 資源檢視;與 UI 檢視區分 | -| viewport / scissor | 視口/裁剪區域 | +| 英文 | 約定用語 | +| ----------------------------- | --------------------------------------------------------- | +| API / GPU / RHI | 保留縮寫,首次依原文說明 | +| barrier | 屏障 | +| bindless | 無繫結 | +| buffer | 緩衝區;`Buffer` 不變 | +| color attachment | 色彩附件 | +| command buffer | 命令緩衝區 | +| command queue | 命令佇列 | +| command recording | 命令記錄 | +| depth/stencil | 深度/樣板 | +| drawable | 目前影格的輸出紋理;`Drawable` 不變,不一律稱為交換鏈影像 | +| framebuffer | 畫面緩衝區,尺寸依原文的像素單位表述 | +| graphics context | 圖形上下文 | +| heap | 堆積 | +| pipeline | 管線;依情境區分圖形或計算管線 | +| rasterization | 光柵化 | +| readback | 從 GPU 回讀資料;下載檔案另用「下載」 | +| render pass | 渲染通道 | +| render target | 渲染目標 | +| resource | 資源 | +| resource ownership / lifetime | 資源所有權/生命週期 | +| resource usage | 資源用途 | +| shader / entry point | 著色器/進入點 | +| submit / submission | 提交/提交操作,與 GPU 執行區分 | +| surface | 呈現情境使用「原生呈現目標」;`Surface` 不變 | +| swap chain / presentation | 交換鏈/呈現 | +| texture | 紋理 | +| timeline | 時間線 | +| undefined | 未定義,不能改寫為某個預設結果 | +| upload | 上傳資料 | +| vertex / fragment | 頂點/片元 | +| view | 資源檢視;與 UI 檢視區分 | +| viewport / scissor | 視口/裁剪區域 | 列與行的用法依臺灣慣例:row 譯為「列」,column 譯為「行」。row-major 為「列優先」,row stride 為「列跨距」。記憶體配置與資料佈局須依語境區分。 diff --git a/documents/authoring.md b/documents/maintenance.md similarity index 93% rename from documents/authoring.md rename to documents/maintenance.md index 1c3a6a2b..428aeb4e 100644 --- a/documents/authoring.md +++ b/documents/maintenance.md @@ -1,4 +1,4 @@ -# Documentation authoring and maintenance +# Documentation maintenance guide This is the contributor reference for maintaining the documentation and its translations. It is excluded from the published site and its navigation. @@ -20,17 +20,17 @@ Keep scratch pages, validation scripts and preview fixtures outside the reposito Shared page paths below are relative to `documents/`. English text lives exclusively in `locales/en-US/strings.yml`. A Markdown filename determines its corresponding `.html` route. -| Page | Responsibility | -| --- | --- | -| `index.md` | The shared homepage composition, bound to `home.*` text resources. | -| `learn/index.md` | Orient readers and link to the tutorial, samples and concepts. Keep the existing card structure. | -| `learn/first-triangle.md` | One complete, runnable triangle tutorial, from an empty project to the first rendered frame. | -| `learn/samples.md` | Curated links to actual sample source, with a short explanation of what each demonstrates and any prerequisites. | -| `learn/concepts/execution-model.md` | Contexts, queues, command recording, submission and ownership. | -| `learn/concepts/resource-management.md` | Resource creation, usages, memory placement, heaps, views and lifetime. | -| `learn/concepts/shader-data-and-binding.md` | Slang shaders, data layout and resource handles/binding. | -| `learn/concepts/synchronization.md` | Execution order, resource visibility, barriers, timelines and CPU/GPU coordination. | -| `learn/concepts/platform-integration.md` | Surfaces, presentation, resize/lifecycle and integration with supported UI frameworks. | +| Page | Responsibility | +| -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | +| `index.md` | The shared homepage composition, bound to `home.*` text resources. | +| `learn/index.md` | Orient readers and link to the tutorial, samples and concepts. Keep the existing card structure. | +| `learn/first-triangle.md` | One complete, runnable triangle tutorial, from an empty project to the first rendered frame. | +| `learn/samples.md` | Curated links to actual sample source, with a short explanation of what each demonstrates and any prerequisites. | +| `learn/concepts/execution-model.md` | Contexts, queues, command recording, submission and ownership. | +| `learn/concepts/resource-management.md` | Resource creation, usages, memory placement, heaps, views and lifetime. | +| `learn/concepts/shader-data-and-binding.md` | Slang shaders, data layout and resource handles/binding. | +| `learn/concepts/synchronization.md` | Execution order, resource visibility, barriers, timelines and CPU/GPU coordination. | +| `learn/concepts/platform-integration.md` | Surfaces, presentation, resize/lifecycle and integration with supported UI frameworks. | | `api/index.md` and generated reference pages | Look up namespaces, declarations and members. API behavior comes from source and any intentional source XML comments. | Do not turn the samples index into a sequence of advanced tutorials. The triangle can have ordered sections within its single page; other examples remain independent. Concepts explain decisions and constraints, linking to the tutorial, samples or API instead of duplicating them. @@ -209,7 +209,7 @@ docfx documents/docfx.json --warningsAsErrors Once API metadata has been generated and matches the current source, Markdown, resource-dictionary, or theme-only changes can use `docfx build documents/docfx.json --warningsAsErrors`. -The build produces ignored API YAML and `.manifest` files under `documents/api/`, and the published site under `documents/_site/`. Commit the authored `api/index.md`, shared pages, dictionaries, images, and templates; keep generated output out of the PR. `authoring.md` and the permanent `locales/*/translation.md` files are contributor documentation, not temporary files. +The build produces ignored API YAML and `.manifest` files under `documents/api/`, and the published site under `documents/_site/`. Commit the authored `api/index.md`, shared pages, dictionaries, images, and templates; keep generated output out of the PR. `maintenance.md` and the permanent `locales/*/translation.md` files are contributor documentation, not temporary files. Preview the generated site from the repository root: diff --git a/documents/templates/ManagedReference.extension.js b/documents/templates/ManagedReference.extension.js index ba8aea37..fa035230 100644 --- a/documents/templates/ManagedReference.extension.js +++ b/documents/templates/ManagedReference.extension.js @@ -16,7 +16,9 @@ function prepareSignature(syntax, strings) { }; } syntax.apiParameterDescriptions = (syntax.parameters || []).filter(parameter => parameter.description?.trim()); - syntax.apiTypeParameterDescriptions = (syntax.typeParameters || []).filter(parameter => parameter.description?.trim()); + syntax.apiTypeParameterDescriptions = (syntax.typeParameters || []).filter(parameter => + parameter.description?.trim() + ); } function uidSuffix(uid) { @@ -32,19 +34,22 @@ exports.postTransform = function (model) { model.apiHasMemberFinder = !model.isNamespace; model.apiSeeAlsoId = 'seealso'; const hasRelationships = relationshipKeys.some(key => model[key]?.length > 0); - model.apiHasTypeDetails = !model.isNamespace && (hasRelationships || !!model.namespace?.uid || !!model.assemblies?.length); + model.apiHasTypeDetails = + !model.isNamespace && (hasRelationships || !!model.namespace?.uid || !!model.assemblies?.length); model.apiTypeDetailsKey = 'ui.reference.' + (hasRelationships ? 'relationships' : 'metadata'); model.apiTypeDetailsLabel = resources.get(strings, model.apiTypeDetailsKey); prepareSignature(model.syntax, strings); if (model.syntax) { model.syntax.apiBaseReferences = [...(model.inheritance || []), ...(model.implements || [])] - .map(type => ({ type: type.specName?.[0]?.value })).filter(reference => reference.type); + .map(type => ({ type: type.specName?.[0]?.value })) + .filter(reference => reference.type); } const anchors = new Set([model.id]); const overloads = new Set(); for (const group of model.children || []) { - group.apiTitleKey = 'ui.reference.' + (model.isEnum ? 'values' : group.id === 'eii' ? 'implementations' : group.id); + group.apiTitleKey = + 'ui.reference.' + (model.isEnum ? 'values' : group.id === 'eii' ? 'implementations' : group.id); group.apiTitle = resources.get(strings, group.apiTitleKey); for (const item of group.children || []) { item.apiName = item.name?.[0]?.value || item.uid; diff --git a/documents/templates/ManagedReference.html.primary.tmpl b/documents/templates/ManagedReference.html.primary.tmpl index ca828994..cf7172f4 100644 --- a/documents/templates/ManagedReference.html.primary.tmpl +++ b/documents/templates/ManagedReference.html.primary.tmpl @@ -1,10 +1,31 @@ {{!master(layout/_master.tmpl)}}
    - {{>partials/api.header}} - {{#isNamespace}}{{>partials/api.namespace}}{{/isNamespace}} - {{#isEnum}}{{>partials/api.enum}}{{/isEnum}} - {{^isNamespace}}{{^isEnum}}{{>partials/api.type}}{{/isEnum}}{{/isNamespace}} - {{#remarks}}

    {{r.ui.reference.remarks}}

    {{{remarks}}}
    {{/remarks}} - {{#example.0}}

    {{r.ui.reference.examples}}

    {{#example}}{{{.}}}{{/example}}
    {{/example.0}} - {{^isNamespace}}{{>partials/api.seealso}}{{/isNamespace}} + {{>partials/api.header}} + {{#isNamespace}} + {{>partials/api.namespace}} + {{/isNamespace}} + {{#isEnum}} + {{>partials/api.enum}} + {{/isEnum}} + {{^isNamespace}} + {{^isEnum}} + {{>partials/api.type}} + {{/isEnum}} + {{/isNamespace}} + {{#remarks}} +
    +

    {{r.ui.reference.remarks}}

    {{{remarks}}} +
    + {{/remarks}} + {{#example.0}} +
    +

    {{r.ui.reference.examples}}

    + {{#example}} + {{{.}}} + {{/example}} +
    + {{/example.0}} + {{^isNamespace}} + {{>partials/api.seealso}} + {{/isNamespace}}
    diff --git a/documents/templates/layout/_master.tmpl b/documents/templates/layout/_master.tmpl index aecf36cb..437114d7 100644 --- a/documents/templates/layout/_master.tmpl +++ b/documents/templates/layout/_master.tmpl @@ -2,73 +2,96 @@ {{!include(/^public/.*/)}} - - - - {{#title}}{{title}}{{/title}}{{^title}}{{>partials/title}}{{/title}} {{#_appTitle}}| {{_appTitle}} {{/_appTitle}} - - - {{#description}}{{/description}} - {{^description}}{{#_description}}{{/_description}}{{/description}} - - - {{#_apiReference}}{{/_apiReference}} + + + + {{#title}}{{title}}{{/title}}{{^title}}{{>partials/title}}{{/title}} {{#_appTitle}}| {{_appTitle}} {{/_appTitle}} + + + {{#description}} + + {{/description}} + {{^description}} + {{#_description}} + + {{/_description}} + {{/description}} - + + + {{#_apiReference}} + + {{/_apiReference}} - {{#_apiReference}}{{/_apiReference}} - {{#_noindex}}{{/_noindex}} + + {{#_apiReference}} + + {{/_apiReference}} + {{#_noindex}} + + {{/_noindex}} - + - - {{#_resourceTitle}}{{/_resourceTitle}} - {{#_resourceDescription}}{{/_resourceDescription}} - + + {{#_resourceTitle}} + + {{/_resourceTitle}} + {{#_resourceDescription}} + + {{/_resourceDescription}} + - - + + - - {{>partials/site.header}} + + {{>partials/site.header}} -
    - {{>partials/site.sidebar}} +
    + {{>partials/site.sidebar}} -
    - {{^_disableToc}} - {{#apiHasMemberFinder}}
    {{/apiHasMemberFinder}} - - {{#apiHasMemberFinder}} - {{>partials/api.member-launcher}} -
    - {{/apiHasMemberFinder}} - {{/_disableToc}} +
    + {{^_disableToc}} + {{#apiHasMemberFinder}}
    {{/apiHasMemberFinder}} + + {{#apiHasMemberFinder}} + {{>partials/api.member-launcher}} +
    + {{/apiHasMemberFinder}} + {{/_disableToc}} -
    - {{!body}} -
    -
    +
    + {{!body}} +
    +
    - {{^_disableAffix}} - - {{/_disableAffix}} -
    + {{^_disableAffix}} + + {{/_disableAffix}} +
    - {{! Keep translation slot templates outside the article indexed by DocFX.}} - {{{_resourceTemplates}}} + {{! Keep translation slot templates outside the article indexed by DocFX.}} + {{{_resourceTemplates}}} - {{>partials/site.member-finder}} + {{>partials/site.member-finder}} + {{>partials/site.search}} - {{>partials/site.search}} - - {{#_isLanding}}{{>partials/site.footer}}{{/_isLanding}} - + {{#_isLanding}} + {{>partials/site.footer}} + {{/_isLanding}} + diff --git a/documents/templates/partials/api.code.tmpl.partial b/documents/templates/partials/api.code.tmpl.partial index 166bcbea..e32c58e2 100644 --- a/documents/templates/partials/api.code.tmpl.partial +++ b/documents/templates/partials/api.code.tmpl.partial @@ -1,8 +1,14 @@ {{#syntax.content.0.value}} -
    {{syntax.content.0.value}}
    - +
    {{syntax.content.0.value}}
    + {{/syntax.content.0.value}} diff --git a/documents/templates/partials/api.enum.tmpl.partial b/documents/templates/partials/api.enum.tmpl.partial index 7dc9996d..242a1142 100644 --- a/documents/templates/partials/api.enum.tmpl.partial +++ b/documents/templates/partials/api.enum.tmpl.partial @@ -1,15 +1,22 @@ {{!Based on the .NET Foundation DocFX templates, licensed under the MIT license.}} {{#children}} -
    -

    {{apiTitle}}

    -
    - {{#children}} -
    -

    {{syntax.content.0.value}}

    - {{#summary}}
    {{{summary}}}
    {{/summary}} - {{#remarks}}
    {{{remarks}}}
    {{/remarks}} -
    - {{/children}} -
    -
    +
    +
    +

    {{apiTitle}}

    +
    +
    + {{#children}} +
    +

    {{syntax.content.0.value}} +

    + {{#summary}} +
    {{{summary}}}
    + {{/summary}} + {{#remarks}} +
    {{{remarks}}}
    + {{/remarks}} +
    + {{/children}} +
    +
    {{/children}} diff --git a/documents/templates/partials/api.header.tmpl.partial b/documents/templates/partials/api.header.tmpl.partial index 8bac0aef..a21f1bac 100644 --- a/documents/templates/partials/api.header.tmpl.partial +++ b/documents/templates/partials/api.header.tmpl.partial @@ -1,14 +1,23 @@ {{!Based on the .NET Foundation DocFX templates, licensed under the MIT license.}}
    -

    {{apiName}}

    - {{#summary}}
    {{{summary}}}
    {{/summary}} - {{#conceptual}}
    {{{conceptual}}}
    {{/conceptual}} +

    {{apiName}}

    + {{#summary}} +
    {{{summary}}}
    + {{/summary}} + {{#conceptual}} +
    {{{conceptual}}}
    + {{/conceptual}}
    {{#syntax.content.0.value}} -
    - {{>partials/api.source}} - {{>partials/api.code}} -
    +
    + {{>partials/api.source}} + {{>partials/api.code}} +
    {{/syntax.content.0.value}} -{{#syntax}}{{>partials/api.signature}}{{/syntax}} -{{#apiHasTypeDetails}}{{>partials/api.relationships}}{{/apiHasTypeDetails}} +{{#syntax}} + {{>partials/api.signature}} +{{/syntax}} +{{#apiHasTypeDetails}} + {{>partials/api.relationships}} +{{/apiHasTypeDetails}} diff --git a/documents/templates/partials/api.member-launcher.tmpl.partial b/documents/templates/partials/api.member-launcher.tmpl.partial index 16ac712c..5f644305 100644 --- a/documents/templates/partials/api.member-launcher.tmpl.partial +++ b/documents/templates/partials/api.member-launcher.tmpl.partial @@ -1,5 +1,6 @@ - diff --git a/documents/templates/partials/api.namespace.tmpl.partial b/documents/templates/partials/api.namespace.tmpl.partial index fc3e8df5..6d1a4cdf 100644 --- a/documents/templates/partials/api.namespace.tmpl.partial +++ b/documents/templates/partials/api.namespace.tmpl.partial @@ -1,11 +1,18 @@ {{!Based on the .NET Foundation DocFX templates, licensed under the MIT license.}} {{#children}} -
    -

    {{apiTitle}}

    -
    - {{#children}} -
    {{name.0.value}}{{#summary}}
    {{{summary}}}
    {{/summary}}
    - {{/children}} -
    -
    +
    +
    +

    {{apiTitle}}

    +
    +
    + {{#children}} +
    + {{name.0.value}} + {{#summary}} +
    {{{summary}}}
    + {{/summary}} +
    + {{/children}} +
    +
    {{/children}} diff --git a/documents/templates/partials/api.relationships.tmpl.partial b/documents/templates/partials/api.relationships.tmpl.partial index 96757882..ddd02d0a 100644 --- a/documents/templates/partials/api.relationships.tmpl.partial +++ b/documents/templates/partials/api.relationships.tmpl.partial @@ -1,48 +1,85 @@ {{!Based on the .NET Foundation DocFX templates, licensed under the MIT license.}}
    - {{apiTypeDetailsLabel}} -
    - - {{#inheritance.0}} -
    -

    {{r.ui.reference.inheritance}}

    -
      {{#inheritance}}
    • {{{specName.0.value}}}
    • {{/inheritance}}
    • {{apiName}}
    + {{apiTypeDetailsLabel}} +
    + + {{#inheritance.0}} +
    +

    {{r.ui.reference.inheritance}}

    +
      + {{#inheritance}} +
    • {{{specName.0.value}}}
    • + {{/inheritance}} +
    • {{apiName}}
    • +
    +
    + {{/inheritance.0}} + {{#implements.0}} +
    +

    {{r.ui.reference.interfaces}}

    +
      + {{#implements}} +
    • {{{specName.0.value}}}
    • + {{/implements}} +
    +
    + {{/implements.0}} + {{#derivedClasses.0}} +
    +

    {{r.ui.reference.derived}}

    +
      + {{#derivedClasses}} +
    • {{{specName.0.value}}}
    • + {{/derivedClasses}} +
    +
    + {{/derivedClasses.0}} + {{#inheritedMembers.0}} +
    +

    {{r.ui.reference.inheritedMembers}}

    +
      + {{#inheritedMembers}} +
    • + {{#definition}} + + {{/definition}} + {{^definition}} + + {{/definition}} +
    • + {{/inheritedMembers}} +
    +
    + {{/inheritedMembers.0}} + {{#extensionMethods.0}} +
    +

    {{r.ui.reference.extensionMethods}}

    +
      + {{#extensionMethods}} +
    • + {{#definition}} + + {{/definition}} + {{^definition}} + + {{/definition}} +
    • + {{/extensionMethods}} +
    +
    + {{/extensionMethods.0}}
    - {{/inheritance.0}} - {{#implements.0}} -
    -

    {{r.ui.reference.interfaces}}

    -
      {{#implements}}
    • {{{specName.0.value}}}
    • {{/implements}}
    -
    - {{/implements.0}} - {{#derivedClasses.0}} -
    -

    {{r.ui.reference.derived}}

    -
      {{#derivedClasses}}
    • {{{specName.0.value}}}
    • {{/derivedClasses}}
    -
    - {{/derivedClasses.0}} - {{#inheritedMembers.0}} -
    -

    {{r.ui.reference.inheritedMembers}}

    -
      - {{#inheritedMembers}} -
    • {{#definition}}{{/definition}}{{^definition}}{{/definition}}
    • - {{/inheritedMembers}} -
    -
    - {{/inheritedMembers.0}} - {{#extensionMethods.0}} -
    -

    {{r.ui.reference.extensionMethods}}

    -
      - {{#extensionMethods}} -
    • {{#definition}}{{/definition}}{{^definition}}{{/definition}}
    • - {{/extensionMethods}} -
    -
    - {{/extensionMethods.0}} -
    diff --git a/documents/templates/partials/api.seealso.tmpl.partial b/documents/templates/partials/api.seealso.tmpl.partial index 498b02d5..0417a071 100644 --- a/documents/templates/partials/api.seealso.tmpl.partial +++ b/documents/templates/partials/api.seealso.tmpl.partial @@ -1,9 +1,18 @@ {{!Based on the .NET Foundation DocFX templates, licensed under the MIT license.}} {{#seealso.0}} - + {{/seealso.0}} diff --git a/documents/templates/partials/api.signature.tmpl.partial b/documents/templates/partials/api.signature.tmpl.partial index 28822e42..ba2d3e57 100644 --- a/documents/templates/partials/api.signature.tmpl.partial +++ b/documents/templates/partials/api.signature.tmpl.partial @@ -1,37 +1,49 @@ {{!Based on the .NET Foundation DocFX templates, licensed under the MIT license.}} {{#apiTypeParameterDescriptions.0}} -
    -

    {{r.ui.reference.typeParameters}}

    -
    - {{#apiTypeParameterDescriptions}} -
    {{id}}
    {{{description}}}
    - {{/apiTypeParameterDescriptions}} -
    -
    +
    +

    {{r.ui.reference.typeParameters}}

    +
    + {{#apiTypeParameterDescriptions}} +
    +
    {{id}} +
    +
    {{{description}}}
    +
    + {{/apiTypeParameterDescriptions}} +
    +
    {{/apiTypeParameterDescriptions.0}} {{#apiParameterDescriptions.0}} -
    -

    {{r.ui.reference.parameters}}

    -
    - {{#apiParameterDescriptions}} -
    {{id}}
    {{{description}}}
    - {{/apiParameterDescriptions}} -
    -
    +
    +

    {{r.ui.reference.parameters}}

    +
    + {{#apiParameterDescriptions}} +
    +
    {{id}} +
    +
    {{{description}}}
    +
    + {{/apiParameterDescriptions}} +
    +
    {{/apiParameterDescriptions.0}} {{#apiResult}} -{{#showType}} -
    -
    {{label}}
    -
    {{{type}}}{{#description}}
    {{{description}}}
    {{/description}}
    -
    -{{/showType}} -{{^showType}} -{{#description}} -
    -

    {{label}}

    -
    {{{description}}}
    -
    -{{/description}} -{{/showType}} + {{#showType}} +
    +
    {{label}}
    +
    {{{type}}} + {{#description}} +
    {{{description}}}
    + {{/description}} +
    +
    + {{/showType}} + {{^showType}} + {{#description}} +
    +

    {{label}}

    +
    {{{description}}}
    +
    + {{/description}} + {{/showType}} {{/apiResult}} diff --git a/documents/templates/partials/api.source.tmpl.partial b/documents/templates/partials/api.source.tmpl.partial index 15aa6b5d..965f7dad 100644 --- a/documents/templates/partials/api.source.tmpl.partial +++ b/documents/templates/partials/api.source.tmpl.partial @@ -1,5 +1,7 @@ {{#sourceurl}} - - - + + + {{/sourceurl}} diff --git a/documents/templates/partials/api.type.tmpl.partial b/documents/templates/partials/api.type.tmpl.partial index b108e9ab..d51c094c 100644 --- a/documents/templates/partials/api.type.tmpl.partial +++ b/documents/templates/partials/api.type.tmpl.partial @@ -1,25 +1,62 @@ {{!Based on the .NET Foundation DocFX templates, licensed under the MIT license.}} {{#children}} -
    -

    {{apiTitle}}

    -
    - {{#children}} - {{#apiOverload}}{{/apiOverload}} -
    -
    -

    {{apiName}}

    - {{>partials/api.source}} -
    - {{>partials/api.code}} - {{#summary}}
    {{{summary}}}
    {{/summary}} - {{#conceptual}}
    {{{conceptual}}}
    {{/conceptual}} - {{#syntax}}{{>partials/api.signature}}{{/syntax}} - {{#remarks}}

    {{r.ui.reference.remarks}}

    {{{remarks}}}
    {{/remarks}} - {{#example.0}}

    {{r.ui.reference.examples}}

    {{#example}}{{{.}}}{{/example}}
    {{/example.0}} - {{#exceptions.0}}

    {{r.ui.reference.exceptions}}

    {{#exceptions}}
    {{{type.specName.0.value}}}
    {{{description}}}
    {{/exceptions}}
    {{/exceptions.0}} - {{>partials/api.seealso}} +
    +
    +

    {{apiTitle}}

    +
    +
    + {{#children}} + {{#apiOverload}} + + {{/apiOverload}} +
    +
    +

    {{apiName}}

    + {{>partials/api.source}} +
    + {{>partials/api.code}} + {{#summary}} +
    {{{summary}}}
    + {{/summary}} + {{#conceptual}} +
    {{{conceptual}}}
    + {{/conceptual}} + {{#syntax}} + {{>partials/api.signature}} + {{/syntax}} + {{#remarks}} +
    +

    + {{r.ui.reference.remarks}} +

    {{{remarks}}} +
    + {{/remarks}} + {{#example.0}} +
    +

    + {{r.ui.reference.examples}} +

    + {{#example}} + {{{.}}} + {{/example}} +
    + {{/example.0}} + {{#exceptions.0}} +
    +

    {{r.ui.reference.exceptions}}

    +
    + {{#exceptions}} +
    +
    {{{type.specName.0.value}}}
    +
    {{{description}}}
    +
    + {{/exceptions}} +
    +
    + {{/exceptions.0}} + {{>partials/api.seealso}} +
    + {{/children}} +
    - {{/children}} -
    -
    {{/children}} diff --git a/documents/templates/partials/site.footer.tmpl.partial b/documents/templates/partials/site.footer.tmpl.partial index f1cab0bc..eb5bf3f5 100644 --- a/documents/templates/partials/site.footer.tmpl.partial +++ b/documents/templates/partials/site.footer.tmpl.partial @@ -1,13 +1,13 @@  diff --git a/documents/templates/partials/site.header.tmpl.partial b/documents/templates/partials/site.header.tmpl.partial index 75ed6aef..1b59e538 100644 --- a/documents/templates/partials/site.header.tmpl.partial +++ b/documents/templates/partials/site.header.tmpl.partial @@ -1,22 +1,37 @@  diff --git a/documents/templates/partials/site.language.tmpl.partial b/documents/templates/partials/site.language.tmpl.partial index 63eb5f23..5b7550a1 100644 --- a/documents/templates/partials/site.language.tmpl.partial +++ b/documents/templates/partials/site.language.tmpl.partial @@ -1,9 +1,19 @@ 
    - - + + + +
    diff --git a/documents/templates/partials/site.member-finder.tmpl.partial b/documents/templates/partials/site.member-finder.tmpl.partial index ca0c8572..63cf1ed8 100644 --- a/documents/templates/partials/site.member-finder.tmpl.partial +++ b/documents/templates/partials/site.member-finder.tmpl.partial @@ -1,23 +1,41 @@ {{#apiHasMemberFinder}} - -
    -
    -

    {{r.ui.members.title}}

    -

    {{fullName.0.value}}

    -
    - -
    - -
    -
    - -
    - -
    + +
    +
    +

    {{r.ui.members.title}}

    +

    {{fullName.0.value}}

    +
    + +
    + +
    +
    + +
    + +
    {{/apiHasMemberFinder}} diff --git a/documents/templates/partials/site.search.tmpl.partial b/documents/templates/partials/site.search.tmpl.partial index f6769150..71e66aa2 100644 --- a/documents/templates/partials/site.search.tmpl.partial +++ b/documents/templates/partials/site.search.tmpl.partial @@ -1,21 +1,46 @@ {{#_enableSearch}} - -

    {{r.ui.search.title}}

    - - - -
    + +

    {{r.ui.search.title}}

    + + + +
    {{/_enableSearch}} diff --git a/documents/templates/partials/site.sidebar.tmpl.partial b/documents/templates/partials/site.sidebar.tmpl.partial index f66eee79..3dbec45c 100644 --- a/documents/templates/partials/site.sidebar.tmpl.partial +++ b/documents/templates/partials/site.sidebar.tmpl.partial @@ -1,37 +1,65 @@ {{^_disableToc}} -
    -
    -
    -
    {{r.ui.contents.title}}
    - -
    -
    - {{#_apiReference}} - - {{/_apiReference}} - {{^_apiReference}} - - {{/_apiReference}}
    -
    -
    {{/_disableToc}} diff --git a/documents/templates/public/api.css b/documents/templates/public/api.css index b235864a..08a67a24 100644 --- a/documents/templates/public/api.css +++ b/documents/templates/public/api.css @@ -1,9 +1,9 @@ /* Zenith API reference: generated content, site-owned presentation. */ -body.zenith-theme[data-section="api"] > main > .content { +body.zenith-theme[data-section='api'] > main > .content { padding-block: 40px 72px; } -body.zenith-theme[data-section="api"] > main > .toc-offcanvas { +body.zenith-theme[data-section='api'] > main > .toc-offcanvas { padding: 40px 22px 24px 0; } @@ -64,16 +64,21 @@ body.zenith-theme[data-section="api"] > main > .toc-offcanvas { outline: none; } -.api-namespace-picker, .api-type-search { - transition: box-shadow var(--zenith-state-duration), background-color var(--zenith-state-duration); +.api-namespace-picker, +.api-type-search { + transition: + box-shadow var(--zenith-state-duration), + background-color var(--zenith-state-duration); } -.api-namespace-picker:hover, .api-type-search:hover { +.api-namespace-picker:hover, +.api-type-search:hover { background: var(--zenith-control-bg); } /* The focus edge stays inside the field, clear of the scrolling sidebar's clip. */ -.api-namespace-picker:focus-within, .api-type-search:focus-within { +.api-namespace-picker:focus-within, +.api-type-search:focus-within { box-shadow: inset 0 0 0 2px var(--zenith-focus); } @@ -116,7 +121,8 @@ body.zenith-theme[data-section="api"] > main > .toc-offcanvas { color: var(--zenith-muted); } -.api-type-search input::-webkit-search-cancel-button, .api-type-search input::-webkit-search-decoration { +.api-type-search input::-webkit-search-cancel-button, +.api-type-search input::-webkit-search-decoration { display: none; } @@ -183,7 +189,9 @@ body.zenith-theme[data-section="api"] > main > .toc-offcanvas { line-height: 1.5; text-decoration: none; overflow-wrap: anywhere; - transition: background-color var(--zenith-state-duration), color var(--zenith-state-duration); + transition: + background-color var(--zenith-state-duration), + color var(--zenith-state-duration); } #api-type-list a:hover { @@ -224,7 +232,7 @@ body.zenith-theme[data-section="api"] > main > .toc-offcanvas { font-size: clamp(30px, 3.1vw, 46px); font-weight: 600; line-height: 1.15; - letter-spacing: -.045em; + letter-spacing: -0.045em; overflow-wrap: anywhere; } @@ -269,7 +277,8 @@ body.zenith-theme[data-section="api"] > main > .toc-offcanvas { background: var(--zenith-surface); } -.api-reference pre, .api-reference pre[data-language] { +.api-reference pre, +.api-reference pre[data-language] { margin: 14px 0; padding: 15px 44px 15px 16px; border: 1px solid var(--zenith-border); @@ -300,7 +309,8 @@ body.zenith-theme[data-section="api"] > main > .toc-offcanvas { background: none; } -.api-declaration pre > code, .api-member > pre > code { +.api-declaration pre > code, +.api-member > pre > code { white-space: pre-wrap; overflow-wrap: anywhere; } @@ -323,8 +333,10 @@ body.zenith-theme[data-section="api"] > main > .toc-offcanvas { font-size: 15px; line-height: 1; text-decoration: none; - opacity: .45; - transition: opacity var(--zenith-state-duration), background-color var(--zenith-state-duration); + opacity: 0.45; + transition: + opacity var(--zenith-state-duration), + background-color var(--zenith-state-duration); } .api-reference .api-source { @@ -339,13 +351,15 @@ body.zenith-theme[data-section="api"] > main > .toc-offcanvas { opacity: 1; } -.api-reference .api-source:hover, .api-reference :is(.api-declaration, .api-member) > pre .code-action:hover { +.api-reference .api-source:hover, +.api-reference :is(.api-declaration, .api-member) > pre .code-action:hover { background: var(--zenith-hover); } @media (hover: none) { - .api-reference .api-source, .api-reference :is(.api-declaration, .api-member) > pre .code-action { - opacity: .8; + .api-reference .api-source, + .api-reference :is(.api-declaration, .api-member) > pre .code-action { + opacity: 0.8; } } @@ -389,7 +403,7 @@ body.zenith-theme[data-section="api"] > main > .toc-offcanvas { } .api-reference summary::after { - content: "+"; + content: '+'; flex-shrink: 0; width: 20px; color: #c4daf6; @@ -460,7 +474,8 @@ body.zenith-theme[data-section="api"] > main > .toc-offcanvas { font-size: 12px; } -.api-relation ul, .api-related ul { +.api-relation ul, +.api-related ul { display: flex; flex-wrap: wrap; gap: 6px; @@ -513,11 +528,12 @@ body.zenith-theme[data-section="api"] > main > .toc-offcanvas { border: 0; font-size: 22px; font-weight: 550; - letter-spacing: -.5px; + letter-spacing: -0.5px; } /* Namespace directories use one dense, scannable grid. */ -.api-type-grid, .api-enum-values { +.api-type-grid, +.api-enum-values { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0; @@ -546,11 +562,13 @@ body.zenith-theme[data-section="api"] > main > .toc-offcanvas { pointer-events: auto; } -.api-type-entry, .api-enum-value { +.api-type-entry, +.api-enum-value { box-shadow: inset -1px -1px 0 var(--zenith-border); } -.api-type-entry:hover, .api-type-entry:focus-within { +.api-type-entry:hover, +.api-type-entry:focus-within { background: var(--zenith-hover); } @@ -564,7 +582,7 @@ body.zenith-theme[data-section="api"] > main > .toc-offcanvas { } .api-type-entry > a::after { - content: ""; + content: ''; position: absolute; inset: 0; } @@ -629,12 +647,13 @@ body.zenith-theme[data-section="api"] > main > .toc-offcanvas { background: var(--zenith-surface); } -.api-member:target, .api-member:has(:target) { +.api-member:target, +.api-member:has(:target) { border-color: var(--zenith-focus); } /* Focus from the finder belongs to the member block, not a box around static text. */ -.api-reference :is(.api-member-heading h3, .api-enum-value h3)[tabindex="-1"]:focus { +.api-reference :is(.api-member-heading h3, .api-enum-value h3)[tabindex='-1']:focus { outline: none; } @@ -666,7 +685,7 @@ body.zenith-theme[data-section="api"] > main > .toc-offcanvas { margin: 0; color: var(--zenith-text); font: 550 17px/1.5 var(--bs-font-monospace); - letter-spacing: -.04em; + letter-spacing: -0.04em; overflow-wrap: anywhere; } @@ -703,7 +722,9 @@ body.zenith-theme[data-section="api"] > main > .toc-offcanvas { font-size: 13px; } -.api-signature-section, .api-member-notes, .api-related { +.api-signature-section, +.api-member-notes, +.api-related { margin-top: 18px; } @@ -867,7 +888,9 @@ body.zenith-theme[data-section="api"] > main > .toc-offcanvas { color: var(--zenith-action); font: 500 12px/1.5 var(--bs-body-font-family); cursor: pointer; - transition: color var(--zenith-state-duration), background-color var(--zenith-state-duration); + transition: + color var(--zenith-state-duration), + background-color var(--zenith-state-duration); } .api-member-launcher:focus-visible { @@ -891,11 +914,13 @@ body.zenith-theme[data-section="api"] > main > .toc-offcanvas { font: 10px/1.5 var(--bs-font-monospace); } -.api-mobile-tools, .api-menu-member { +.api-mobile-tools, +.api-menu-member { display: none; } -.api-menu-member kbd, .api-mobile-tools .api-member-launcher kbd { +.api-menu-member kbd, +.api-mobile-tools .api-member-launcher kbd { display: none; } @@ -906,17 +931,19 @@ body.zenith-theme[data-section="api"] > main > .toc-offcanvas { } @media (min-width: 768px) and (max-width: 999.98px) { - .api-type-grid, .api-enum-values, .api-start-grid { + .api-type-grid, + .api-enum-values, + .api-start-grid { grid-template-columns: 1fr; } } @media (max-width: 767.98px) { - body.zenith-theme[data-section="api"] > main > .content { + body.zenith-theme[data-section='api'] > main > .content { padding-top: 0; } - body.zenith-theme[data-section="api"] > main > .toc-offcanvas { + body.zenith-theme[data-section='api'] > main > .toc-offcanvas { padding: 0; } @@ -979,7 +1006,9 @@ body.zenith-theme[data-section="api"] > main > .toc-offcanvas { } @media (max-width: 479.98px) { - .api-type-grid, .api-enum-values, .api-namespace-grid { + .api-type-grid, + .api-enum-values, + .api-namespace-grid { grid-template-columns: 1fr; } diff --git a/documents/templates/public/api.js b/documents/templates/public/api.js index 72c2a701..dd39858b 100644 --- a/documents/templates/public/api.js +++ b/documents/templates/public/api.js @@ -27,24 +27,34 @@ export async function initializeApi() { const response = await fetch(tocUrl, { cache: 'no-cache' }); if (!response.ok) throw new Error('API navigation could not be loaded.'); const documentToc = new DOMParser().parseFromString(await response.text(), 'text/html'); - const readLink = link => ({ name: link.textContent.trim(), href: pageUrl(new URL(link.getAttribute('href'), tocUrl).href) }); - const namespaces = [...documentToc.querySelectorAll('.nav.level1 > li')].map(item => { - const link = item.querySelector(':scope > a'); - return { ...readLink(link), types: [...item.querySelectorAll(':scope > ul > li > a')].map(readLink) }; - }).sort((a, b) => { - const rank = name => name === 'Zenith.NET' ? 0 : name.startsWith('Zenith.NET.') ? 1 : 2; - return rank(a.name) - rank(b.name) || a.name.localeCompare(b.name); + const readLink = link => ({ + name: link.textContent.trim(), + href: pageUrl(new URL(link.getAttribute('href'), tocUrl).href) }); + const namespaces = [...documentToc.querySelectorAll('.nav.level1 > li')] + .map(item => { + const link = item.querySelector(':scope > a'); + return { ...readLink(link), types: [...item.querySelectorAll(':scope > ul > li > a')].map(readLink) }; + }) + .sort((a, b) => { + const rank = name => (name === 'Zenith.NET' ? 0 : name.startsWith('Zenith.NET.') ? 1 : 2); + return rank(a.name) - rank(b.name) || a.name.localeCompare(b.name); + }); const current = href => new URL(href).pathname === location.pathname; - const activeNamespace = namespaces.find(item => current(item.href) || item.types.some(type => current(type.href))) || namespaces[0]; + const activeNamespace = + namespaces.find(item => current(item.href) || item.types.some(type => current(type.href))) || namespaces[0]; if (!activeNamespace) throw new Error('No namespaces were generated.'); - const allTypes = namespaces.flatMap(namespace => namespace.types.map(type => ({ ...type, namespace: namespace.name }))); - picker.replaceChildren(...namespaces.map(item => { - const option = document.createElement('option'); - option.value = item.href; - option.textContent = item.name; - return option; - })); + const allTypes = namespaces.flatMap(namespace => + namespace.types.map(type => ({ ...type, namespace: namespace.name })) + ); + picker.replaceChildren( + ...namespaces.map(item => { + const option = document.createElement('option'); + option.value = item.href; + option.textContent = item.name; + return option; + }) + ); picker.disabled = false; filter.disabled = false; picker.value = activeNamespace.href; @@ -107,10 +117,12 @@ export async function initializeApi() { const active = list.querySelector('[aria-current="page"]'); if (active) scroller.scrollTop = active.offsetTop - (scroller.clientHeight - active.offsetHeight) / 2; // Apply page-owned state after history restores the browser's form values. - window.addEventListener('pageshow', () => setTimeout(() => { - picker.value = activeNamespace.href; - renderTypes(false); - }, 0)); + window.addEventListener('pageshow', () => + setTimeout(() => { + picker.value = activeNamespace.href; + renderTypes(false); + }, 0) + ); const grid = document.getElementById('api-namespace-grid'); if (grid) { diff --git a/documents/templates/public/content.css b/documents/templates/public/content.css index 6cce60f3..ed35ed18 100644 --- a/documents/templates/public/content.css +++ b/documents/templates/public/content.css @@ -4,7 +4,7 @@ article :not(pre) > code { border-radius: 4px; background: var(--zenith-graphite); color: var(--zenith-text); - font-size: .875em; + font-size: 0.875em; } article pre { @@ -18,7 +18,9 @@ article pre { font-size: 14px; line-height: 1.65; scrollbar-width: thin; - box-shadow: 0 8px 24px rgb(0 0 0 / 12%), inset 0 1px rgb(255 255 255 / 3%); + box-shadow: + 0 8px 24px rgb(0 0 0 / 12%), + inset 0 1px rgb(255 255 255 / 3%); } article pre[data-language] { @@ -199,18 +201,22 @@ article .xref { } /* References in prose and code keep the same meaning on API and tutorial pages. */ -article code a.code-reference, article a.xref > code { +article code a.code-reference, +article a.xref > code { color: var(--zenith-code-link); font-weight: 500; text-decoration: none; - transition: color var(--zenith-state-duration), background-color var(--zenith-state-duration); + transition: + color var(--zenith-state-duration), + background-color var(--zenith-state-duration); } .zenith-theme article code a.code-reference * { color: inherit; } -article code a.code-reference:hover, article a.xref:hover > code { +article code a.code-reference:hover, +article a.xref:hover > code { color: #fff; background: #2d3b4c; } @@ -234,7 +240,6 @@ article code[data-api-symbol] a.code-reference:hover * { color: #fff; } - @media (max-width: 767.98px) { article pre { padding-inline: 14px; diff --git a/documents/templates/public/dialog.js b/documents/templates/public/dialog.js index e8280067..74a43387 100644 --- a/documents/templates/public/dialog.js +++ b/documents/templates/public/dialog.js @@ -1,27 +1,39 @@ export function isBackdropClick(event, dialog) { if (event.target !== dialog) return false; const bounds = dialog.getBoundingClientRect(); - return event.clientX < bounds.left || event.clientX > bounds.right - || event.clientY < bounds.top || event.clientY > bounds.bottom; + return ( + event.clientX < bounds.left || + event.clientX > bounds.right || + event.clientY < bounds.top || + event.clientY > bounds.bottom + ); } // Escape closes once, including Safari search inputs; arrows stay within visible results. export function bindDialogKeys(dialog, { items, close }) { - dialog.addEventListener('keydown', event => { - if (event.isComposing) return; - if (event.key === 'Escape') { + dialog.addEventListener( + 'keydown', + event => { + if (event.isComposing) return; + if (event.key === 'Escape') { + event.preventDefault(); + event.stopPropagation(); + close(); + return; + } + if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') return; + const links = [...dialog.querySelectorAll(items)].filter(link => link.getClientRects().length); + if (!links.length) return; event.preventDefault(); - event.stopPropagation(); - close(); - return; - } - if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') return; - const links = [...dialog.querySelectorAll(items)].filter(link => link.getClientRects().length); - if (!links.length) return; - event.preventDefault(); - const current = links.indexOf(document.activeElement); - const next = event.key === 'ArrowDown' ? (current + 1) % links.length - : (current <= 0 ? links.length - 1 : current - 1); - links[next].focus(); - }, { capture: true }); + const current = links.indexOf(document.activeElement); + const next = + event.key === 'ArrowDown' + ? (current + 1) % links.length + : current <= 0 + ? links.length - 1 + : current - 1; + links[next].focus(); + }, + { capture: true } + ); } diff --git a/documents/templates/public/home.css b/documents/templates/public/home.css index 0114d1ef..4ed7ffa3 100644 --- a/documents/templates/public/home.css +++ b/documents/templates/public/home.css @@ -1,9 +1,9 @@ /* Home: typography and an interactive geometry study */ -body.zenith-theme[data-layout="landing"] > main.container-xxl { +body.zenith-theme[data-layout='landing'] > main.container-xxl { display: block; } -body.zenith-theme[data-layout="landing"] > main.container-xxl > .content { +body.zenith-theme[data-layout='landing'] > main.container-xxl > .content { padding: 0; } @@ -29,7 +29,7 @@ body.zenith-theme[data-layout="landing"] > main.container-xxl > .content { margin: 0 0 24px; font-size: clamp(46px, 5.1vw, 88px); font-weight: 600; - letter-spacing: -.035em; + letter-spacing: -0.035em; line-height: 1.08; } @@ -137,23 +137,26 @@ body.zenith-theme[data-layout="landing"] > main.container-xxl > .content { } .scene-options button::before { - content: ""; + content: ''; width: 8px; height: 8px; border: 1px solid #69788b; border-radius: 50%; - transition: background-color 240ms, border-color 240ms, box-shadow 240ms; + transition: + background-color 240ms, + border-color 240ms, + box-shadow 240ms; } .scene-options button:hover { color: #fff; } -.scene-options button[aria-pressed="true"] { +.scene-options button[aria-pressed='true'] { color: #e9f3ff; } -.scene-options button[aria-pressed="true"]::before { +.scene-options button[aria-pressed='true']::before { border-color: var(--zenith-action); background: var(--zenith-action); box-shadow: 0 0 10px #c6ddfa4d; @@ -225,7 +228,7 @@ body.zenith-theme[data-layout="landing"] > main.container-xxl > .content { right: 22px; width: 136px; height: 76px; - opacity: .8; + opacity: 0.8; pointer-events: none; transition: opacity 240ms; } @@ -235,7 +238,7 @@ body.zenith-theme[data-layout="landing"] > main.container-xxl > .content { color: var(--zenith-text); font-size: 24px; font-weight: 550; - letter-spacing: -.65px; + letter-spacing: -0.65px; } .path-card p { @@ -246,7 +249,8 @@ body.zenith-theme[data-layout="landing"] > main.container-xxl > .content { line-height: 1.8; } -.path-cta, .entry-action { +.path-cta, +.entry-action { align-self: flex-start; margin-top: auto; color: var(--zenith-action); @@ -288,7 +292,9 @@ body.zenith-theme[data-layout="landing"] > main.container-xxl > .content { .learning-entry:hover { border-color: var(--zenith-border-hover); color: var(--zenith-text); - box-shadow: inset 0 0 0 1px #c3d6f029, inset 0 0 36px #c3d6f009; + box-shadow: + inset 0 0 0 1px #c3d6f029, + inset 0 0 36px #c3d6f009; } .learning-entry h2 { @@ -296,7 +302,7 @@ body.zenith-theme[data-layout="landing"] > main.container-xxl > .content { padding: 0; border: 0; font-size: 22px; - letter-spacing: -.6px; + letter-spacing: -0.6px; } .learning-entry p { @@ -465,7 +471,7 @@ body.zenith-theme > footer { .render-copy h1 { font-size: clamp(38px, 8.8vw, 56px); - letter-spacing: -.03em; + letter-spacing: -0.03em; } .render-description { @@ -518,7 +524,7 @@ body.zenith-theme > footer { top: 48px; width: 96px; height: 54px; - opacity: .6; + opacity: 0.6; } .path-card p { diff --git a/documents/templates/public/home.js b/documents/templates/public/home.js index a4735dfe..6dfed7da 100644 --- a/documents/templates/public/home.js +++ b/documents/templates/public/home.js @@ -10,8 +10,8 @@ export function initializeHomeScene() { const faces = []; const steps = 144; const sides = 12; - let yaw = .4; - let pitch = -.45; + let yaw = 0.4; + let pitch = -0.45; let mode = 'surface'; let pointer; let visible = false; @@ -21,31 +21,42 @@ export function initializeHomeScene() { let speed = 0; let pauseUntil = 0; let dirty = true; - let width = 0, height = 0, ratio = 1; + let width = 0, + height = 0, + ratio = 1; const normalize = vector => { const length = Math.hypot(...vector); return vector.map(value => value / length); }; const cross = (a, b) => [a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]]; - const lightDirection = normalize([-.55, -.8, 1]); + const lightDirection = normalize([-0.55, -0.8, 1]); const halfDirection = normalize([lightDirection[0], lightDirection[1], lightDirection[2] + 1]); const dot = (a, b) => a.reduce((sum, value, i) => sum + value * b[i], 0); - const center = t => [(1.2 + .38 * Math.cos(3 * t)) * Math.cos(2 * t), (1.2 + .38 * Math.cos(3 * t)) * Math.sin(2 * t), .58 * Math.sin(3 * t)]; + const center = t => [ + (1.2 + 0.38 * Math.cos(3 * t)) * Math.cos(2 * t), + (1.2 + 0.38 * Math.cos(3 * t)) * Math.sin(2 * t), + 0.58 * Math.sin(3 * t) + ]; const point = (step, side) => { - const t = step / steps * Math.PI * 2; + const t = (step / steps) * Math.PI * 2; const c = center(t); - const next = center(t + .001); + const next = center(t + 0.001); const tangent = normalize(next.map((v, i) => v - c[i])); const normal = normalize(cross(tangent, [0, 0, 1])); const binormal = cross(tangent, normal); - const angle = side / sides * Math.PI * 2; - return c.map((v, i) => v + .26 * (normal[i] * Math.cos(angle) + binormal[i] * Math.sin(angle))); + const angle = (side / sides) * Math.PI * 2; + return c.map((v, i) => v + 0.26 * (normal[i] * Math.cos(angle) + binormal[i] * Math.sin(angle))); }; for (let i = 0; i < steps; i++) { for (let j = 0; j < sides; j++) { const vertices = [point(i, j), point(i + 1, j), point(i + 1, j + 1), point(i, j + 1)]; - const normal = normalize(cross(vertices[3].map((v, index) => v - vertices[0][index]), vertices[1].map((v, index) => v - vertices[0][index]))); + const normal = normalize( + cross( + vertices[3].map((v, index) => v - vertices[0][index]), + vertices[1].map((v, index) => v - vertices[0][index]) + ) + ); faces.push({ vertices, normal }); } } @@ -54,36 +65,42 @@ export function initializeHomeScene() { if (!width || !height) return; context.setTransform(ratio, 0, 0, ratio, 0, 0); context.clearRect(0, 0, width, height); - const cy = Math.cos(yaw), sy = Math.sin(yaw), cp = Math.cos(pitch), sp = Math.sin(pitch); + const cy = Math.cos(yaw), + sy = Math.sin(yaw), + cp = Math.cos(pitch), + sp = Math.sin(pitch); const rotate = ([x, y, z]) => { - const a = x * cy + z * sy, b = z * cy - x * sy; + const a = x * cy + z * sy, + b = z * cy - x * sy; return [a, y * cp - b * sp, y * sp + b * cp]; }; - const scale = Math.min(width, height) * .24; + const scale = Math.min(width, height) * 0.24; const project = ([x, y, z]) => { const perspective = 5 / (5 - z); return [width / 2 + x * scale * perspective, height / 2 + y * scale * perspective]; }; - const transformed = faces.map(face => { - const vertices = face.vertices.map(rotate); - return { vertices, normal: rotate(face.normal), depth: vertices.reduce((sum, v) => sum + v[2], 0) / 4 }; - }).sort((a, b) => a.depth - b.depth); + const transformed = faces + .map(face => { + const vertices = face.vertices.map(rotate); + return { vertices, normal: rotate(face.normal), depth: vertices.reduce((sum, v) => sum + v[2], 0) / 4 }; + }) + .sort((a, b) => a.depth - b.depth); for (const { vertices, normal, depth } of transformed) { const diffuse = Math.max(0, dot(normal, lightDirection)); const highlight = Math.pow(Math.max(0, dot(normal, halfDirection)), 28); const brightness = Math.round(18 + diffuse * 135 + highlight * 70 + (depth + 2) * 5); const points = vertices.map(project); context.beginPath(); - points.forEach(([x, y], i) => i ? context.lineTo(x, y) : context.moveTo(x, y)); + points.forEach(([x, y], i) => (i ? context.lineTo(x, y) : context.moveTo(x, y))); context.closePath(); if (mode === 'surface') { context.fillStyle = `rgb(${brightness}, ${brightness + 4}, ${brightness + 10})`; context.fill(); context.strokeStyle = 'rgba(220,230,244,.07)'; - context.lineWidth = .5; + context.lineWidth = 0.5; } else { - context.strokeStyle = `rgba(200,211,226,${.1 + (depth + 1.7) * .12})`; - context.lineWidth = .6; + context.strokeStyle = `rgba(200,211,226,${0.1 + (depth + 1.7) * 0.12})`; + context.lineWidth = 0.6; } context.stroke(); } @@ -95,12 +112,12 @@ export function initializeHomeScene() { function tick(time) { frame = 0; - const elapsed = lastTime ? Math.min((time - lastTime) / 1000, .05) : 0; + const elapsed = lastTime ? Math.min((time - lastTime) / 1000, 0.05) : 0; lastTime = time; const rotating = !preference.matches && !pointer && time >= pauseUntil; if (rotating) { // Ease back into a roughly 40-second revolution after manual input. - speed = Math.min(.16, speed + elapsed * .2); + speed = Math.min(0.16, speed + elapsed * 0.2); yaw = (yaw - speed * elapsed) % (Math.PI * 2); } if (dirty || rotating) draw(); @@ -113,7 +130,7 @@ export function initializeHomeScene() { frame = 0; lastTime = 0; speed = 0; - if (dirty || !preference.matches && !pointer) schedule(); + if (dirty || (!preference.matches && !pointer)) schedule(); } function render() { @@ -139,8 +156,8 @@ export function initializeHomeScene() { }); canvas.addEventListener('pointermove', event => { if (!pointer || pointer.id !== event.pointerId) return; - yaw += (event.clientX - pointer.x) * .008; - pitch += (event.clientY - pointer.y) * .008; + yaw += (event.clientX - pointer.x) * 0.008; + pitch += (event.clientY - pointer.y) * 0.008; pointer.x = event.clientX; pointer.y = event.clientY; render(); @@ -155,7 +172,9 @@ export function initializeHomeScene() { canvas.addEventListener('pointercancel', release); canvas.addEventListener('lostpointercapture', release); canvas.addEventListener('keydown', event => { - const delta = { ArrowLeft: [-.15, 0], ArrowRight: [.15, 0], ArrowUp: [0, -.15], ArrowDown: [0, .15] }[event.key]; + const delta = { ArrowLeft: [-0.15, 0], ArrowRight: [0.15, 0], ArrowUp: [0, -0.15], ArrowDown: [0, 0.15] }[ + event.key + ]; if (!delta) return; event.preventDefault(); yaw += delta[0]; @@ -167,7 +186,8 @@ export function initializeHomeScene() { new ResizeObserver(() => { ({ width, height } = canvas.getBoundingClientRect()); ratio = Math.min(devicePixelRatio || 1, 2); - const pixelWidth = Math.round(width * ratio), pixelHeight = Math.round(height * ratio); + const pixelWidth = Math.round(width * ratio), + pixelHeight = Math.round(height * ratio); if (canvas.width !== pixelWidth || canvas.height !== pixelHeight) { canvas.width = pixelWidth; canvas.height = pixelHeight; diff --git a/documents/templates/public/languages.js b/documents/templates/public/languages.js index 8dc23e77..5094c057 100644 --- a/documents/templates/public/languages.js +++ b/documents/templates/public/languages.js @@ -8,7 +8,11 @@ const preferenceKey = 'zenith-language:' + siteRoot.pathname; const available = resourceState.languages.filter(language => language.available); function savedLanguage() { - try { return localStorage.getItem(preferenceKey); } catch { return null; } + try { + return localStorage.getItem(preferenceKey); + } catch { + return null; + } } function matchLanguage(code) { @@ -16,10 +20,16 @@ function matchLanguage(code) { const exact = available.find(language => language.code.toLowerCase() === code.toLowerCase()); if (exact) return exact.code; let locale; - try { locale = new Intl.Locale(code); } catch { return; } - return (locale.language === 'zh' - ? available.find(language => language.code === (locale.maximize().script === 'Hant' ? 'zh-TW' : 'zh-CN')) - : available.find(language => language.code.split('-')[0] === locale.language))?.code; + try { + locale = new Intl.Locale(code); + } catch { + return; + } + return ( + locale.language === 'zh' + ? available.find(language => language.code === (locale.maximize().script === 'Hant' ? 'zh-TW' : 'zh-CN')) + : available.find(language => language.code.split('-')[0] === locale.language) + )?.code; } function preferredLanguage() { @@ -30,7 +40,12 @@ function preferredLanguage() { export function pageUrl(path) { const url = new URL(path, siteRoot); - if (url.origin === siteRoot.origin && url.pathname.startsWith(siteRoot.pathname) && (url.pathname.endsWith('.html') || url.pathname.endsWith('/'))) url.searchParams.set('lang', edition.code); + if ( + url.origin === siteRoot.origin && + url.pathname.startsWith(siteRoot.pathname) && + (url.pathname.endsWith('.html') || url.pathname.endsWith('/')) + ) + url.searchParams.set('lang', edition.code); return url.href; } @@ -39,7 +54,10 @@ export async function initializeLanguages() { edition.code = preferredLanguage(); if (edition.code !== sourceLanguage) { try { - const response = await fetch(new URL(`locales/${edition.code}/strings.json`, siteRoot), { cache: 'no-cache', signal: AbortSignal.timeout(8000) }); + const response = await fetch(new URL(`locales/${edition.code}/strings.json`, siteRoot), { + cache: 'no-cache', + signal: AbortSignal.timeout(8000) + }); if (!response.ok) throw new Error('Language resources unavailable'); setStrings(await response.json()); } catch { @@ -47,11 +65,16 @@ export async function initializeLanguages() { } } applyResources(edition.code); - if (location.hash) requestAnimationFrame(() => { - let id; - try { id = decodeURIComponent(location.hash.slice(1)); } catch { return; } - document.getElementById(id)?.scrollIntoView({ block: 'start', behavior: 'auto' }); - }); + if (location.hash) + requestAnimationFrame(() => { + let id; + try { + id = decodeURIComponent(location.hash.slice(1)); + } catch { + return; + } + document.getElementById(id)?.scrollIntoView({ block: 'start', behavior: 'auto' }); + }); const current = new URL(location.href); if (current.searchParams.has('lang') || edition.code !== sourceLanguage) { current.searchParams.set('lang', edition.code); @@ -91,10 +114,16 @@ function initializeMenu() { menu.addEventListener('click', event => { const link = event.target.closest('a[data-language-code]'); if (link) { - try { localStorage.setItem(preferenceKey, link.dataset.languageCode); } catch { /* Optional preference. */ } + try { + localStorage.setItem(preferenceKey, link.dataset.languageCode); + } catch { + /* Optional preference. */ + } } }); - document.addEventListener('click', event => { if (!menu.contains(event.target)) menu.open = false; }); + document.addEventListener('click', event => { + if (!menu.contains(event.target)) menu.open = false; + }); document.addEventListener('keydown', event => { if (event.key === 'Escape' && menu.open) { menu.open = false; diff --git a/documents/templates/public/layout.css b/documents/templates/public/layout.css index bce11f44..55f91015 100644 --- a/documents/templates/public/layout.css +++ b/documents/templates/public/layout.css @@ -105,7 +105,9 @@ html:has(.site-search[open], #tocOffcanvas:is(.showing, .show, .hiding)) { gap: 4px; } -.search-launcher, .source-link, .language-menu > summary { +.search-launcher, +.source-link, +.language-menu > summary { display: grid; place-items: center; width: 44px; @@ -120,7 +122,9 @@ html:has(.site-search[open], #tocOffcanvas:is(.showing, .show, .hiding)) { cursor: pointer; } -.search-launcher:hover, .source-link:hover, .language-menu > summary:hover { +.search-launcher:hover, +.source-link:hover, +.language-menu > summary:hover { color: #fff; background: var(--zenith-hover); } @@ -171,7 +175,8 @@ html:has(.site-search[open], #tocOffcanvas:is(.showing, .show, .hiding)) { text-decoration: none; } -.language-options a:hover, .language-options a[aria-current] { +.language-options a:hover, +.language-options a[aria-current] { background: var(--zenith-graphite); color: var(--zenith-text); } @@ -232,7 +237,7 @@ body.zenith-theme > main.container-xxl > .content { } /* Keep prose readable inside the same shell used by the home and API pages. */ -body.zenith-theme[data-section="learn"]:not([data-page-kind="hub"]) > main > .content { +body.zenith-theme[data-section='learn']:not([data-page-kind='hub']) > main > .content { max-width: var(--zenith-reading-width); justify-self: center; } @@ -264,7 +269,7 @@ body.zenith-theme > main.container-xxl > .toc-offcanvas { --bs-offcanvas-bg: var(--zenith-surface); --bs-offcanvas-width: min(320px, 90vw); --bs-offcanvas-color: var(--zenith-body); - --bs-offcanvas-transition: transform var(--zenith-panel-duration) cubic-bezier(.16, 1, .3, 1); + --bs-offcanvas-transition: transform var(--zenith-panel-duration) cubic-bezier(0.16, 1, 0.3, 1); } .zenith-theme #tocOffcanvas .offcanvas-body { @@ -328,7 +333,8 @@ body.zenith-theme > main.container-xxl > .toc-offcanvas { display: none; } -.contents-toggle, .contents-close { +.contents-toggle, +.contents-close { align-items: center; justify-content: center; gap: 8px; @@ -347,7 +353,8 @@ body.zenith-theme > main.container-xxl > .toc-offcanvas { width: 40px; } -.contents-toggle:hover, .contents-close:hover { +.contents-toggle:hover, +.contents-close:hover { color: #fff; background: var(--zenith-hover); } @@ -413,7 +420,9 @@ body.zenith-theme > main.container-xxl > .toc-offcanvas { color: var(--zenith-muted); overflow-wrap: break-word; text-decoration: none; - transition: color var(--zenith-state-duration), background-color var(--zenith-state-duration); + transition: + color var(--zenith-state-duration), + background-color var(--zenith-state-duration); } .outline-section-current > .outline-link { @@ -492,7 +501,10 @@ body.zenith-theme > main.container-xxl > .toc-offcanvas { opacity: 0; visibility: hidden; clip-path: inset(0 0 100%); - transition: clip-path var(--zenith-panel-duration) cubic-bezier(.16, 1, .3, 1), opacity var(--zenith-state-duration), visibility var(--zenith-panel-duration); + transition: + clip-path var(--zenith-panel-duration) cubic-bezier(0.16, 1, 0.3, 1), + opacity var(--zenith-state-duration), + visibility var(--zenith-panel-duration); } .menu-open .site-menu { @@ -561,7 +573,9 @@ body.zenith-theme > main.container-xxl > .toc-offcanvas { gap: 2px; } - .language-menu > summary, .search-launcher, .menu-toggle { + .language-menu > summary, + .search-launcher, + .menu-toggle { width: 36px; } } diff --git a/documents/templates/public/main.css b/documents/templates/public/main.css index 201aa778..e6bc6d79 100644 --- a/documents/templates/public/main.css +++ b/documents/templates/public/main.css @@ -1,8 +1,8 @@ /* DocFX entry point. Keep framework styles below the site-owned theme. */ -@import url("./docfx.min.css") layer(docfx); -@import url("./theme.css"); -@import url("./layout.css"); -@import url("./search.css"); -@import url("./content.css"); -@import url("./home.css"); -@import url("./motion.css"); +@import url('./docfx.min.css') layer(docfx); +@import url('./theme.css'); +@import url('./layout.css'); +@import url('./search.css'); +@import url('./content.css'); +@import url('./home.css'); +@import url('./motion.css'); diff --git a/documents/templates/public/member-finder.js b/documents/templates/public/member-finder.js index da6c6f4d..1e7c06cc 100644 --- a/documents/templates/public/member-finder.js +++ b/documents/templates/public/member-finder.js @@ -12,14 +12,20 @@ export function initializeMemberFinder() { const empty = document.getElementById('api-member-empty'); const clear = document.getElementById('api-member-clear'); const launchers = [...document.querySelectorAll('[data-member-find]')]; - const groups = [...document.querySelectorAll('.api-reference > .api-group')].map(section => ({ - name: section.querySelector('.api-group-heading h2')?.textContent.trim(), - members: [...section.querySelectorAll('.api-member-heading h3[id], .api-enum-value h3[id]')].map(heading => ({ - heading, - name: heading.textContent.trim(), - signature: heading.closest('.api-member')?.querySelector(':scope > pre > code')?.textContent || heading.textContent + const groups = [...document.querySelectorAll('.api-reference > .api-group')] + .map(section => ({ + name: section.querySelector('.api-group-heading h2')?.textContent.trim(), + members: [...section.querySelectorAll('.api-member-heading h3[id], .api-enum-value h3[id]')].map( + heading => ({ + heading, + name: heading.textContent.trim(), + signature: + heading.closest('.api-member')?.querySelector(':scope > pre > code')?.textContent || + heading.textContent + }) + ) })) - })).filter(group => group.members.length); + .filter(group => group.members.length); if (!groups.length) empty.textContent = t('ui.members.undeclared'); let opener; @@ -65,9 +71,15 @@ export function initializeMemberFinder() { } function isVisible(button) { - if (!button || !button.getClientRects().length || getComputedStyle(button).visibility !== 'visible') return false; + if (!button || !button.getClientRects().length || getComputedStyle(button).visibility !== 'visible') + return false; const drawer = button.closest('#tocOffcanvas'); - if (drawer && window.matchMedia('(max-width: 767.98px)').matches && (!drawer.classList.contains('show') || drawer.classList.contains('hiding'))) return false; + if ( + drawer && + window.matchMedia('(max-width: 767.98px)').matches && + (!drawer.classList.contains('show') || drawer.classList.contains('hiding')) + ) + return false; const bounds = button.getBoundingClientRect(); return bounds.right > 0 && bounds.left < innerWidth && bounds.bottom > 0 && bounds.top < innerHeight; } @@ -129,7 +141,16 @@ export function initializeMemberFinder() { }); bindDialogKeys(dialog, { items: '#api-member-results a', close: () => dialog.close() }); document.addEventListener('keydown', event => { - if (event.isComposing || !event.altKey || event.ctrlKey || event.metaKey || event.shiftKey || event.repeat || event.code !== 'KeyM' && event.key.toLowerCase() !== 'm') return; + if ( + event.isComposing || + !event.altKey || + event.ctrlKey || + event.metaKey || + event.shiftKey || + event.repeat || + (event.code !== 'KeyM' && event.key.toLowerCase() !== 'm') + ) + return; if (isEditing(event.target)) return; event.preventDefault(); if (dialog.open) dialog.close(); diff --git a/documents/templates/public/motion.css b/documents/templates/public/motion.css index c9e4dc56..72cb7f7a 100644 --- a/documents/templates/public/motion.css +++ b/documents/templates/public/motion.css @@ -3,12 +3,12 @@ --diagram-line: #adc6e7; --diagram-light: #edf6ff; --diagram-duration: 1500ms; - --diagram-ease: cubic-bezier(.35, 0, .25, 1); + --diagram-ease: cubic-bezier(0.35, 0, 0.25, 1); pointer-events: none; } .card-art .art-wire { - --art-rest-opacity: .7; + --art-rest-opacity: 0.7; fill: none; stroke: var(--diagram-line); stroke-width: 1.35; @@ -16,7 +16,7 @@ } .card-art .art-detail { - --art-rest-opacity: .22; + --art-rest-opacity: 0.22; fill: none; stroke: var(--diagram-line); stroke-width: 1; @@ -28,14 +28,14 @@ } .triangle-diagram .art-detail { - --art-rest-opacity: .35; + --art-rest-opacity: 0.35; stroke-width: 1.5; } .card-art .art-face { fill: #b8d8ff; stroke: none; - opacity: .055; + opacity: 0.055; } .card-art .art-node { @@ -49,7 +49,7 @@ fill: none; stroke: var(--diagram-line); stroke-width: 3.5; - opacity: .45; + opacity: 0.45; } .card-art .art-flow { @@ -99,8 +99,9 @@ stroke-dashoffset: 100; } - 18%, 65% { - opacity: .95; + 18%, + 65% { + opacity: 0.95; } 100% { @@ -110,7 +111,8 @@ } @keyframes diagram-node { - 0%, 100% { + 0%, + 100% { transform: scale(1); filter: none; } @@ -122,32 +124,37 @@ } @keyframes diagram-face { - 0%, 100% { - opacity: .055; + 0%, + 100% { + opacity: 0.055; } 48% { - opacity: .2; + opacity: 0.2; } } @keyframes diagram-mark { - 0%, 100% { + 0%, + 100% { opacity: var(--art-rest-opacity); } 48% { - opacity: .95; + opacity: 0.95; } } @keyframes diagram-cursor { - 0%, 35%, 100% { + 0%, + 35%, + 100% { opacity: 0; } - 50%, 78% { - opacity: .9; + 50%, + 78% { + opacity: 0.9; } } @@ -199,8 +206,11 @@ transition-duration: var(--zenith-press-duration); } -#primary-navigation .nav-link:active, .build-button.secondary:active, -.search-launcher:active, .source-link:active, .scene-options button:active { +#primary-navigation .nav-link:active, +.build-button.secondary:active, +.search-launcher:active, +.source-link:active, +.scene-options button:active { color: #92afd3; } @@ -219,19 +229,23 @@ border-color: #586a82; } -.concept-list > a:active, #toc li > a:active { +.concept-list > a:active, +#toc li > a:active { background: #1a2432; } -.search-shortcuts > a:active, #site-search-results a:active { +.search-shortcuts > a:active, +#site-search-results a:active { background: #1c2838; } -#search-close:hover, .search-more:hover { +#search-close:hover, +.search-more:hover { color: #fff; } -#search-close:active, .search-more:active { +#search-close:active, +.search-more:active { color: #92afd3; } @@ -251,7 +265,7 @@ } :is(.build-button, .path-card, .learning-entry)::before { - content: ""; + content: ''; position: absolute; inset: 0; z-index: -1; @@ -262,12 +276,15 @@ @media (hover: hover) { :is(.build-button, .path-card, .learning-entry):hover::before { - animation: zenith-sweep 620ms cubic-bezier(.2, .65, .3, 1); + animation: zenith-sweep 620ms cubic-bezier(0.2, 0.65, 0.3, 1); } } .concept-list > a > i:first-child { - transition: background-color 240ms, border-color 240ms, color 240ms; + transition: + background-color 240ms, + border-color 240ms, + color 240ms; } .concept-list > a:is(:hover, :focus-visible) > i:first-child { @@ -275,7 +292,7 @@ } .motion-enter { - animation: zenith-reveal 480ms cubic-bezier(.16, 1, .3, 1) var(--entrance-delay, 0ms) backwards; + animation: zenith-reveal 480ms cubic-bezier(0.16, 1, 0.3, 1) var(--entrance-delay, 0ms) backwards; } @keyframes zenith-sweep { @@ -299,7 +316,7 @@ @keyframes zenith-panel-in { from { opacity: 0; - transform: translateY(-10px) scale(.98); + transform: translateY(-10px) scale(0.98); } to { @@ -311,7 +328,7 @@ @keyframes zenith-panel-out { to { opacity: 0; - transform: translateY(-6px) scale(.99); + transform: translateY(-6px) scale(0.99); } } @@ -334,9 +351,11 @@ scroll-behavior: auto; } - *, *::before, *::after, *::backdrop { + *, + *::before, + *::after, + *::backdrop { animation: none !important; transition: none !important; } } - diff --git a/documents/templates/public/motion.js b/documents/templates/public/motion.js index a68db8e3..76fe246b 100644 --- a/documents/templates/public/motion.js +++ b/documents/templates/public/motion.js @@ -6,25 +6,28 @@ export function initializeMotion() { const selector = document.querySelector('.home-page') ? '.render-copy > *, .geometry-stage, .paths-intro, .path-grid' : document.querySelector('.learn-hub') - ? '.learn-hub > h1, .page-intro, .learning-entries, .hub-section-title, .section-description, .concept-list > a' - : document.querySelector('.api-reference') - ? '.api-heading, .api-declaration, .api-start-grid, .api-group-heading' - : 'article > h1, article > p, article > section'; - const observer = new IntersectionObserver(entries => { - let order = 0; - for (const { target, isIntersecting } of entries) { - if (!isIntersecting) continue; - observer.unobserve(target); - target.style.setProperty('--entrance-delay', `${Math.min(order++, 3) * 55}ms`); - target.classList.add('motion-enter'); - target.addEventListener('animationend', event => { - if (event.target === target && event.animationName === 'zenith-reveal') { - target.classList.remove('motion-enter'); - target.style.removeProperty('--entrance-delay'); - } - }); - } - }, { threshold: 0 }); + ? '.learn-hub > h1, .page-intro, .learning-entries, .hub-section-title, .section-description, .concept-list > a' + : document.querySelector('.api-reference') + ? '.api-heading, .api-declaration, .api-start-grid, .api-group-heading' + : 'article > h1, article > p, article > section'; + const observer = new IntersectionObserver( + entries => { + let order = 0; + for (const { target, isIntersecting } of entries) { + if (!isIntersecting) continue; + observer.unobserve(target); + target.style.setProperty('--entrance-delay', `${Math.min(order++, 3) * 55}ms`); + target.classList.add('motion-enter'); + target.addEventListener('animationend', event => { + if (event.target === target && event.animationName === 'zenith-reveal') { + target.classList.remove('motion-enter'); + target.style.removeProperty('--entrance-delay'); + } + }); + } + }, + { threshold: 0 } + ); document.querySelectorAll(selector).forEach(element => observer.observe(element)); const finish = () => { diff --git a/documents/templates/public/navigation.js b/documents/templates/public/navigation.js index 02d8ed2b..32edeb57 100644 --- a/documents/templates/public/navigation.js +++ b/documents/templates/public/navigation.js @@ -3,20 +3,23 @@ import { t } from './resources.js'; let navigationPromise; export function loadNavigation() { - return navigationPromise ??= fetch(new URL('toc.json', siteRoot), { cache: 'no-cache' }).then(response => { - if (!response.ok) throw new Error('Navigation unavailable'); - return response.json(); - }).then(model => model.items).catch(error => { - navigationPromise = undefined; - throw error; - }); + return (navigationPromise ??= fetch(new URL('toc.json', siteRoot), { cache: 'no-cache' }) + .then(response => { + if (!response.ok) throw new Error('Navigation unavailable'); + return response.json(); + }) + .then(model => model.items) + .catch(error => { + navigationPromise = undefined; + throw error; + })); } export async function initializeNavigation() { const items = await loadNavigation(); const currentPath = location.pathname.slice(siteRoot.pathname.length).replace(/\/$/, '/index.html'); const active = items.find(item => (item.topicHref || item.href)?.split('/')[0] === currentPath.split('/')[0]); - const label = item => item.resourceKey ? t(item.resourceKey) : item.name; + const label = item => (item.resourceKey ? t(item.resourceKey) : item.name); const linkFor = item => { const link = document.createElement('a'); link.href = pageUrl(item.topicHref || item.href); @@ -34,7 +37,8 @@ export async function initializeNavigation() { link.classList.add('active'); link.setAttribute('aria-current', 'true'); } - li.append(link); navbar.append(li); + li.append(link); + navbar.append(li); } document.getElementById('primary-navigation').replaceChildren(navbar); const toc = document.getElementById('toc'); @@ -55,7 +59,9 @@ export async function initializeNavigation() { } else { li.className = 'expander expanded'; const title = document.createElement('span'); - title.className = 'toc-group-title'; title.textContent = label(item); li.append(title); + title.className = 'toc-group-title'; + title.textContent = label(item); + li.append(title); } if (item.items?.length) li.append(listFor(item.items, level + 1)); list.append(li); diff --git a/documents/templates/public/outline.js b/documents/templates/public/outline.js index b101e38e..c423daa2 100644 --- a/documents/templates/public/outline.js +++ b/documents/templates/public/outline.js @@ -58,7 +58,8 @@ export function initializeOutline() { } const page = document.scrollingElement; // The last section may never reach the header in a tall viewport. - if (page.scrollTop > 0 && Math.ceil(page.scrollTop + page.clientHeight) >= page.scrollHeight) current = entries.at(-1); + if (page.scrollTop > 0 && Math.ceil(page.scrollTop + page.clientHeight) >= page.scrollHeight) + current = entries.at(-1); if (active === current && !forceReveal) return; active?.link.removeAttribute('aria-current'); active?.group.classList.remove('outline-section-current'); diff --git a/documents/templates/public/resource-format.js b/documents/templates/public/resource-format.js index 882497cf..5b5452d9 100644 --- a/documents/templates/public/resource-format.js +++ b/documents/templates/public/resource-format.js @@ -11,10 +11,23 @@ if (offset < value.length) parts.push({ text: value.slice(offset) }); return parts; }; - api.placeholders = value => [...new Set(api.parts(value).filter(part => part.slot).map(part => part.slot))].sort(); - api.format = (value, slots) => api.parts(value).map(part => { - if (part.text !== undefined) return part.text; - if (!Object.prototype.hasOwnProperty.call(slots, part.slot)) throw new Error(`Missing resource placeholder: ${part.slot}`); - return slots[part.slot]; - }).join(''); + api.placeholders = value => + [ + ...new Set( + api + .parts(value) + .filter(part => part.slot) + .map(part => part.slot) + ) + ].sort(); + api.format = (value, slots) => + api + .parts(value) + .map(part => { + if (part.text !== undefined) return part.text; + if (!Object.prototype.hasOwnProperty.call(slots, part.slot)) + throw new Error(`Missing resource placeholder: ${part.slot}`); + return slots[part.slot]; + }) + .join(''); })(typeof exports === 'object' ? exports : (globalThis.zenithResourceFormat = {})); diff --git a/documents/templates/public/resources.js b/documents/templates/public/resources.js index 087db608..eca48f16 100644 --- a/documents/templates/public/resources.js +++ b/documents/templates/public/resources.js @@ -5,12 +5,18 @@ let strings = resourceState.strings; export const getStrings = () => strings; const has = (dictionary, key) => Object.prototype.hasOwnProperty.call(dictionary, key); const format = globalThis.zenithResourceFormat; -const slotTemplate = element => element.dataset.resourceSlots ? document.getElementById(element.dataset.resourceSlots) : null; +const slotTemplate = element => + element.dataset.resourceSlots ? document.getElementById(element.dataset.resourceSlots) : null; const resourceAttributes = { label: 'aria-label', title: 'title', placeholder: 'placeholder', alt: 'alt' }; // Validate before changing the DOM: an old or incomplete download must not mix languages. export function setStrings(value) { - if (!value || Array.isArray(value) || typeof value !== 'object' || Object.values(value).some(text => typeof text !== 'string' || !text.trim())) { + if ( + !value || + Array.isArray(value) || + typeof value !== 'object' || + Object.values(value).some(text => typeof text !== 'string' || !text.trim()) + ) { throw new Error('Invalid resource dictionary'); } if (Object.keys(value).length !== Object.keys(resourceState.placeholders).length) { @@ -25,12 +31,17 @@ export function setStrings(value) { for (const [key, slots] of Object.entries(resourceState.placeholders)) requireKey(key, slots); for (const element of document.querySelectorAll('[data-resource]')) { const slots = slotTemplate(element)?.content.children || []; - requireKey(element.dataset.resource, [...slots].map(slot => slot.dataset.slot)); + requireKey( + element.dataset.resource, + [...slots].map(slot => slot.dataset.slot) + ); } for (const attribute of Object.keys(resourceAttributes)) { - for (const element of document.querySelectorAll(`[data-resource-${attribute}]`)) requireKey(element.getAttribute(`data-resource-${attribute}`), []); + for (const element of document.querySelectorAll(`[data-resource-${attribute}]`)) + requireKey(element.getAttribute(`data-resource-${attribute}`), []); } - for (const meta of document.querySelectorAll('meta[name="resource:title"], meta[name="resource:description"]')) requireKey(meta.content, []); + for (const meta of document.querySelectorAll('meta[name="resource:title"], meta[name="resource:description"]')) + requireKey(meta.content, []); strings = value; } @@ -77,7 +88,8 @@ export function applyResources(code) { const title = document.querySelector('meta[name="resource:title"]')?.content; if (title) document.title = `${t(title)} | Zenith.NET`; const description = document.querySelector('meta[name="resource:description"]')?.content; - if (description && has(strings, description)) document.querySelector('meta[name="description"]').content = t(description); + if (description && has(strings, description)) + document.querySelector('meta[name="description"]').content = t(description); document.querySelector('meta[name="loc:copy"]').content = t('ui.action.copy'); for (const copy of document.querySelectorAll('.code-action[title]')) copy.title = t('ui.action.copy'); } diff --git a/documents/templates/public/search.css b/documents/templates/public/search.css index 4f4aa744..3fc7162d 100644 --- a/documents/templates/public/search.css +++ b/documents/templates/public/search.css @@ -16,7 +16,8 @@ box-shadow: 0 32px 120px #0009; } -#search-close:hover, #api-member-close:hover { +#search-close:hover, +#api-member-close:hover { color: var(--zenith-text); background: var(--zenith-hover); } @@ -30,7 +31,7 @@ .site-search[open] { display: block; transform-origin: 50% 0; - animation: zenith-panel-in var(--zenith-panel-duration) cubic-bezier(.16, 1, .3, 1); + animation: zenith-panel-in var(--zenith-panel-duration) cubic-bezier(0.16, 1, 0.3, 1); } .site-search[open]::backdrop { @@ -64,7 +65,8 @@ border-bottom-color: var(--zenith-focus); } -#site-search-input, #api-member-query { +#site-search-input, +#api-member-query { width: 100%; min-width: 0; padding: 0; @@ -80,15 +82,18 @@ font: 400 21px/1.5 var(--bs-body-font-family); } -#site-search-input::placeholder, #api-member-query::placeholder { +#site-search-input::placeholder, +#api-member-query::placeholder { color: var(--zenith-muted); } -#site-search-input::-webkit-search-cancel-button, #api-member-query::-webkit-search-cancel-button { +#site-search-input::-webkit-search-cancel-button, +#api-member-query::-webkit-search-cancel-button { display: none; } -#search-close, #api-member-close { +#search-close, +#api-member-close { min-height: 32px; padding: 4px 6px; border: 0; @@ -109,7 +114,8 @@ font: 12px/1.5 var(--bs-body-font-family); } -#site-search-results, #api-member-results ul { +#site-search-results, +#api-member-results ul { margin: 0; padding: 0; list-style: none; @@ -205,7 +211,7 @@ font-size: 20px; line-height: 1.35; font-weight: 600; - letter-spacing: -.4px; + letter-spacing: -0.4px; } .api-finder-heading p { @@ -265,7 +271,8 @@ overflow-wrap: anywhere; } -#api-member-results a:hover, #api-member-results a:focus-visible { +#api-member-results a:hover, +#api-member-results a:focus-visible { background: var(--zenith-hover); } diff --git a/documents/templates/public/search.js b/documents/templates/public/search.js index 5d2005d2..a14fe324 100644 --- a/documents/templates/public/search.js +++ b/documents/templates/public/search.js @@ -8,7 +8,10 @@ const resultsPerPage = 30; const excerptLength = 160; function pageTitles(items) { - const titles = new Map([['index.html', 'home.title'], ['api/index.html', 'reference.title']]); + const titles = new Map([ + ['index.html', 'home.title'], + ['api/index.html', 'reference.title'] + ]); const visit = item => { const href = item.topicHref || item.href; if (href && item.resourceKey?.endsWith('.title')) titles.set(href, item.resourceKey); @@ -22,7 +25,9 @@ async function loadPageCatalog() { const response = await fetch(new URL('index.json', siteRoot), { cache: 'no-cache' }); if (!response.ok) throw new Error('Page index unavailable'); const index = await response.json(); - return Object.keys(index).sort().map(key => index[key]); + return Object.keys(index) + .sort() + .map(key => index[key]); } // Custom search presentation using DocFX's generated index and search worker. @@ -45,13 +50,20 @@ export function initializeSearch() { let hits = []; let shown = 0; let closeRequest; - const normalize = text => String(text || '').normalize('NFKD').replace(/\p{M}/gu, '').toLowerCase(); + const normalize = text => + String(text || '') + .normalize('NFKD') + .replace(/\p{M}/gu, '') + .toLowerCase(); function rememberSearch(open = dialog.open) { - history.replaceState({ - ...history.state, - zenithSearch: { open, query: input.value } - }, ''); + history.replaceState( + { + ...history.state, + zenithSearch: { open, query: input.value } + }, + '' + ); } const shortcut = isApplePlatform ? '⌘ K' : 'Ctrl K'; @@ -74,14 +86,24 @@ export function initializeSearch() { const terms = normalizedQuery.split(/\s+/).filter(Boolean); const matches = localEntries .filter(item => terms.every(term => item.body.includes(term))) - .map(item => ({ page: item.page, score: item.title === normalizedQuery ? terms.length + 1 : terms.filter(term => item.title.includes(term)).length })) + .map(item => ({ + page: item.page, + score: + item.title === normalizedQuery + ? terms.length + 1 + : terms.filter(term => item.title.includes(term)).length + })) .sort((a, b) => b.score - a.score) .map(item => item.page); showResults(query, matches); return; } // Use the same separators as DocFX's index for filenames and qualified API names. - const terms = query.split(/[\s\-.()]+/).filter(Boolean).map(term => '+' + term.replace(/[+\-:^~*\\]/g, '\\$&')).join(' '); + const terms = query + .split(/[\s\-.()]+/) + .filter(Boolean) + .map(term => '+' + term.replace(/[+\-:^~*\\]/g, '\\$&')) + .join(' '); if (!terms) return showResults(query, []); pendingQueries.push(query); worker.postMessage({ q: terms }); @@ -91,7 +113,9 @@ export function initializeSearch() { hits = matches; shown = 0; results.replaceChildren(); - status.textContent = hits.length ? t('ui.search.resultCount', { count: hits.length }) : t('ui.search.empty', { query }); + status.textContent = hits.length + ? t('ui.search.resultCount', { count: hits.length }) + : t('ui.search.empty', { query }); appendResults(); } @@ -109,14 +133,23 @@ export function initializeSearch() { link.setAttribute('data-search-item', ''); heading.className = 'search-result-heading'; title.textContent = hit.title.replace(/\s*\|\s*Zenith\.NET\s*$/, ''); - category.textContent = apiResult ? 'API' : path === 'index.html' ? t('ui.navigation.home') : t('learning.title'); + category.textContent = apiResult + ? 'API' + : path === 'index.html' + ? t('ui.navigation.home') + : t('learning.title'); heading.append(title, category); link.append(heading); if (apiResult || hit.summary) { const excerpt = document.createElement('p'); // API results identify the fully qualified type, without indexing UI labels into the preview. let text = apiResult - ? path === 'api/index.html' ? t('ui.api.browse') : decodeURIComponent(new URL(hit.href, siteRoot).pathname.split('/').pop()).replace(/\.html$/, '') + ? path === 'api/index.html' + ? t('ui.api.browse') + : decodeURIComponent(new URL(hit.href, siteRoot).pathname.split('/').pop()).replace( + /\.html$/, + '' + ) : hit.summary.replace(/\s+/g, ' ').trim(); if (text.startsWith(title.textContent)) text = text.slice(title.textContent.length).trim(); if (text) { @@ -146,27 +179,42 @@ export function initializeSearch() { if (ready) runQuery(); else if (!loadingCatalog) { loadingCatalog = true; - Promise.all([loadPageCatalog(), loadNavigation()]).then(([index, navigation]) => { - const titles = pageTitles(navigation); - const strings = getStrings(); - localEntries = index.map(original => { - const key = titles.get(original.href); - if (!key) return { - page: original, - title: normalize(original.title.replace(/\s*\|\s*Zenith\.NET\s*$/, '')), - body: normalize(`${original.href} ${original.title} ${original.keywords || ''} ${original.summary || ''}`) - }; - const prefix = key.slice(0, -'.title'.length); - const values = Object.entries(strings).filter(([key]) => key.startsWith(prefix + '.')).map(([, value]) => value); - const description = strings[prefix + '.description'] || strings[prefix + '.meta.description']; - const page = { ...original, title: t(key), summary: description && !description.includes('{') ? description : '' }; - // Keep shared code, filenames and API identifiers searchable in every language. - const body = `${values.join(' ')} ${original.href} ${original.keywords || ''} ${original.summary || ''}`; - return { page, title: normalize(page.title), body: normalize(body) }; + Promise.all([loadPageCatalog(), loadNavigation()]) + .then(([index, navigation]) => { + const titles = pageTitles(navigation); + const strings = getStrings(); + localEntries = index.map(original => { + const key = titles.get(original.href); + if (!key) + return { + page: original, + title: normalize(original.title.replace(/\s*\|\s*Zenith\.NET\s*$/, '')), + body: normalize( + `${original.href} ${original.title} ${original.keywords || ''} ${original.summary || ''}` + ) + }; + const prefix = key.slice(0, -'.title'.length); + const values = Object.entries(strings) + .filter(([key]) => key.startsWith(prefix + '.')) + .map(([, value]) => value); + const description = + strings[prefix + '.description'] || strings[prefix + '.meta.description']; + const page = { + ...original, + title: t(key), + summary: description && !description.includes('{') ? description : '' + }; + // Keep shared code, filenames and API identifiers searchable in every language. + const body = `${values.join(' ')} ${original.href} ${original.keywords || ''} ${original.summary || ''}`; + return { page, title: normalize(page.title), body: normalize(body) }; + }); + ready = true; + runQuery(); + }) + .catch(showUnavailable) + .finally(() => { + loadingCatalog = false; }); - ready = true; - runQuery(); - }).catch(showUnavailable).finally(() => { loadingCatalog = false; }); } return; } @@ -242,7 +290,7 @@ export function initializeSearch() { if (event.isComposing || event.repeat) return; const command = (event.metaKey || event.ctrlKey) && event.key.toLowerCase() === 'k'; const slash = event.key === '/' && !event.metaKey && !event.ctrlKey && !event.altKey; - if (command || slash && !isEditing(event.target)) { + if (command || (slash && !isEditing(event.target))) { event.preventDefault(); if (dialog.open && command && !closeRequest) closeSearch(); else openSearch(); diff --git a/documents/templates/public/signature-links.js b/documents/templates/public/signature-links.js index 826ef035..fc1cbf87 100644 --- a/documents/templates/public/signature-links.js +++ b/documents/templates/public/signature-links.js @@ -1,7 +1,10 @@ import { collectCodeReferences, linkCodeRange } from './code-links.js'; const escapeRegex = value => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); -const maskLiterals = text => text.replace(/@"(?:""|[^"])*"|"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\/\/[^\n]*|\/\*[\s\S]*?\*\//g, match => ' '.repeat(match.length)); +const maskLiterals = text => + text.replace(/@"(?:""|[^"])*"|"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\/\/[^\n]*|\/\*[\s\S]*?\*\//g, match => + ' '.repeat(match.length) + ); // Generated declarations link local reference pages only. Authored xrefs are explicit. export function isLocalTypeReference(link) { @@ -34,7 +37,7 @@ function parameterTypeRanges(text, open, parameters) { defaultStart = -1; } else if (!stack.length && char === '=' && defaultStart < 0) { defaultStart = pos; - } else if ('([{'.includes(char) || char === '<' && defaultStart < 0) { + } else if ('([{'.includes(char) || (char === '<' && defaultStart < 0)) { stack.push({ '(': ')', '[': ']', '{': '}', '<': '>' }[char]); } else if (stack.length && char === stack[stack.length - 1]) { stack.pop(); @@ -53,9 +56,12 @@ export function linkSignatureType({ el, text }) { const masked = maskLiterals(text); const declaration = new RegExp(`(?:^|\\s)${escapeRegex(symbol)}(?=\\s*(?:[({\\[;=:]|$))`).exec(masked); // The value type precedes the member name; conversion operators put it before "(". - const end = el.dataset.apiKind === 'operator' - ? text.indexOf('(', declaration ? declaration.index + declaration[0].length : 0) - : declaration ? declaration.index + declaration[0].length - symbol.length : -1; + const end = + el.dataset.apiKind === 'operator' + ? text.indexOf('(', declaration ? declaration.index + declaration[0].length : 0) + : declaration + ? declaration.index + declaration[0].length - symbol.length + : -1; const valueReferences = references.querySelector('[data-signature-value]'); if (end >= 0 && valueReferences) linkRange(el, 0, end, valueReferences); @@ -72,8 +78,11 @@ export function linkSignatureType({ el, text }) { } const opening = /[([]/.exec(text.slice(afterSymbol)); const parameters = [...references.querySelectorAll('[data-signature-parameter]')]; - const ranges = parameterTypeRanges(text, opening ? afterSymbol + opening.index : -1, - parameters.map(parameter => parameter.dataset.signatureParameter)); + const ranges = parameterTypeRanges( + text, + opening ? afterSymbol + opening.index : -1, + parameters.map(parameter => parameter.dataset.signatureParameter) + ); for (const range of ranges) linkRange(el, range.start, range.end, parameters[range.index]); } @@ -82,9 +91,14 @@ function linkRange(el, start, end, references) { if (!links.length) return; // Match the whole type expression. Equal spellings can refer to different symbols. // Nullable annotations may be absent from DocFX's type display, but remain in copied code. - const tokenize = (text, offset = 0) => [...text.matchAll(/@?[\p{ID_Start}_][\p{ID_Continue}]*|[^\s]/gu)] - .filter(match => match[0] !== '?') - .map(match => ({ value: match[0].replace(/^@/, ''), start: offset + match.index, end: offset + match.index + match[0].length })); + const tokenize = (text, offset = 0) => + [...text.matchAll(/@?[\p{ID_Start}_][\p{ID_Continue}]*|[^\s]/gu)] + .filter(match => match[0] !== '?') + .map(match => ({ + value: match[0].replace(/^@/, ''), + start: offset + match.index, + end: offset + match.index + match[0].length + })); const expected = tokenize(references.textContent); const actual = tokenize(el.textContent.slice(start, end), start); if (!expected.length) return; @@ -104,12 +118,17 @@ function linkRange(el, start, end, references) { const previous = expected[index - 1]?.value; const next = expected[index + 1]?.value; // Tuple element names are labels, even when DocFX supplies a member xref for them. - token.label = tupleDepth > 0 && /^[\p{ID_Start}_]/u.test(token.value) - && [',', ')'].includes(next) && previous && !['(', ',', '<', '.'].includes(previous); + token.label = + tupleDepth > 0 && + /^[\p{ID_Start}_]/u.test(token.value) && + [',', ')'].includes(next) && + previous && + !['(', ',', '<', '.'].includes(previous); if (token.value === ')') tupleDepth--; } for (const reference of links.reverse()) { - const positions = expected.map((token, index) => ({ token, index })) + const positions = expected + .map((token, index) => ({ token, index })) .filter(({ token }) => !token.label && token.start >= reference.start && token.end <= reference.end); if (!positions.length) continue; const first = actual[offset + positions[0].index]; diff --git a/documents/templates/public/site.js b/documents/templates/public/site.js index a1b53232..eb66e447 100644 --- a/documents/templates/public/site.js +++ b/documents/templates/public/site.js @@ -44,7 +44,8 @@ export function initializeSite() { } // Preserve deep-link IDs while disabling DocFX's decorative heading anchors. - for (const heading of document.querySelectorAll('article h2, article h3, article h4')) heading.classList.add('no-anchor'); + for (const heading of document.querySelectorAll('article h2, article h3, article h4')) + heading.classList.add('no-anchor'); labelCodeBlocks(); // DocFX adds scrolling wrappers after this hook; the table retains its focus target. for (const table of document.querySelectorAll('article table')) table.tabIndex = 0; @@ -52,13 +53,24 @@ export function initializeSite() { function labelCodeBlocks() { const labels = { - bash: 'Shell', console: 'Console', cs: 'C#', csharp: 'C#', json: 'JSON', - powershell: 'PowerShell', sh: 'Shell', shell: 'Shell', slang: 'Slang', text: 'Text', - xml: 'XML', yaml: 'YAML', yml: 'YAML' + bash: 'Shell', + console: 'Console', + cs: 'C#', + csharp: 'C#', + json: 'JSON', + powershell: 'PowerShell', + sh: 'Shell', + shell: 'Shell', + slang: 'Slang', + text: 'Text', + xml: 'XML', + yaml: 'YAML', + yml: 'YAML' }; for (const code of document.querySelectorAll('article pre > code')) { - const language = [...code.classList].find(name => /^(?:lang|language)-/.test(name)) - ?.replace(/^(?:lang|language)-/, '') || 'text'; + const language = + [...code.classList].find(name => /^(?:lang|language)-/.test(name))?.replace(/^(?:lang|language)-/, '') || + 'text'; if (language === 'mermaid') continue; code.parentElement.dataset.language = labels[language] || language; // Native keyboard scrolling for examples; API declarations already wrap. diff --git a/documents/templates/public/syntax.js b/documents/templates/public/syntax.js index 747ac72b..4824bd95 100644 --- a/documents/templates/public/syntax.js +++ b/documents/templates/public/syntax.js @@ -4,8 +4,11 @@ const configured = new WeakSet(); function expressionModes(keywords) { - const reserved = new Set(Object.values(keywords).flatMap(words => - (Array.isArray(words) ? words : words.split(/\s+/)).map(word => word.split('|')[0]))); + const reserved = new Set( + Object.values(keywords).flatMap(words => + (Array.isArray(words) ? words : words.split(/\s+/)).map(word => word.split('|')[0]) + ) + ); return [ { scope: 'title.function', @@ -45,7 +48,8 @@ export function configureSyntax(hljs) { function slang(hljs) { const keywords = { - keyword: 'struct class interface extension enum namespace using import public private internal static const uniform groupshared in out inout ref let var typedef typealias generic where __init __subscript if else for while do break continue return discard switch case default true false nullptr this sizeof reinterpret_cast no_diff differentiable', + keyword: + 'struct class interface extension enum namespace using import public private internal static const uniform groupshared in out inout ref let var typedef typealias generic where __init __subscript if else for while do break continue return discard switch case default true false nullptr this sizeof reinterpret_cast no_diff differentiable', type: 'void bool int uint half float double int8_t uint8_t int16_t uint16_t int32_t uint32_t int64_t uint64_t' }; return { @@ -59,7 +63,10 @@ function slang(hljs) { hljs.APOS_STRING_MODE, { scope: 'meta', begin: /^\s*#/, end: /$/, contains: [hljs.QUOTE_STRING_MODE] }, hljs.C_NUMBER_MODE, - { scope: 'meta', match: /(?<=\[)(?:shader|numthreads|unroll|loop|branch|flatten|earlydepthstencil|outputtopology|mesh|domain|partitioning|patchconstantfunc|outputcontrolpoints)\b/ }, + { + scope: 'meta', + match: /(?<=\[)(?:shader|numthreads|unroll|loop|branch|flatten|earlydepthstencil|outputtopology|mesh|domain|partitioning|patchconstantfunc|outputcontrolpoints)\b/ + }, { scope: 'type', match: /\b(?:bool|int|uint|half|float|double)[1-4](?:x[1-4])?\b/ }, { scope: 'meta', match: /\b(?:SV_\w+|(?:POSITION|NORMAL|TEXCOORD|COLOR|TANGENT|BINORMAL)\d*)\b/ }, ...expressionModes(keywords) diff --git a/documents/templates/public/theme.css b/documents/templates/public/theme.css index 34b28293..cc26e8d1 100644 --- a/documents/templates/public/theme.css +++ b/documents/templates/public/theme.css @@ -7,7 +7,7 @@ --zenith-press-duration: 60ms; --zenith-panel-duration: 280ms; --zenith-panel-exit-duration: 160ms; - --zenith-state-ease: cubic-bezier(.2, 0, .2, 1); + --zenith-state-ease: cubic-bezier(0.2, 0, 0.2, 1); --zenith-canvas: #101216; --zenith-surface: #181b21; --zenith-graphite: #262a32; @@ -33,8 +33,8 @@ --zenith-outline-width: 208px; --zenith-gap: 40px; --zenith-gutter: clamp(40px, 3vw, 64px); - --bs-body-font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; - --bs-font-monospace: "SFMono-Regular", Consolas, "Liberation Mono", monospace; + --bs-body-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; + --bs-font-monospace: 'SFMono-Regular', Consolas, 'Liberation Mono', monospace; --bs-body-bg: var(--zenith-canvas); --bs-body-bg-rgb: 16, 18, 22; --bs-body-color: var(--zenith-body); @@ -138,7 +138,7 @@ article h2 { padding-bottom: 12px; border-bottom: 1px solid var(--zenith-border); font-size: 25px; - letter-spacing: -.5px; + letter-spacing: -0.5px; } article h3 { @@ -172,7 +172,6 @@ article :is(img, video, svg) { max-width: 100%; } - article img { height: auto; border-radius: var(--zenith-radius); diff --git a/documents/templates/resources.common.js b/documents/templates/resources.common.js index 5833824d..059283cc 100644 --- a/documents/templates/resources.common.js +++ b/documents/templates/resources.common.js @@ -1,6 +1,10 @@ const format = require('./public/resource-format.js'); const keyPattern = /^[a-z][a-zA-Z0-9]*(\.[a-z][a-zA-Z0-9]*)+$/; -const escape = value => String(value).replace(/[&<>"']/g, character => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[character])); +const escape = value => + String(value).replace( + /[&<>"']/g, + character => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' })[character] + ); const json = value => JSON.stringify(value).replace(/ model[key] ?? model._metadata?.[key]; @@ -30,7 +34,8 @@ exports.get = function (dictionary, key) { exports.validate = function (model) { const code = model._key.split('/').at(-2); const languages = setting(model, '_languages'); - if (!languages.some(language => language.code === code)) throw new Error(`Unregistered dictionary language: ${code}`); + if (!languages.some(language => language.code === code)) + throw new Error(`Unregistered dictionary language: ${code}`); const source = exports.source(model); const dictionary = exports.dictionary(model); for (const key of new Set([...Object.keys(source), ...Object.keys(dictionary)])) { @@ -66,7 +71,9 @@ exports.prepare = function (model) { model._resourceState = json({ sourceLanguage: model._sourceLanguage, languages: model._languages, - placeholders: Object.fromEntries(Object.entries(source).map(([key, value]) => [key, format.placeholders(value)])), + placeholders: Object.fromEntries( + Object.entries(source).map(([key, value]) => [key, format.placeholders(value)]) + ), strings: Object.fromEntries(interfaceEntries) }); return source; @@ -80,7 +87,8 @@ exports.bind = function (html, dictionary, templates) { for (const match of html.matchAll(/<\/?(resource|slot)\b[^>]*>/g)) { stack.at(-1).children.push(html.slice(offset, match.index)); if (match[0].startsWith(' part.text !== undefined ? escape(part.text) : slots[part.slot]).join(''); + const content = format + .parts(value) + .map(part => (part.text !== undefined ? escape(part.text) : slots[part.slot])) + .join(''); let reference = ''; if (Object.keys(slots).length) { const id = `resource-slots-${templates.length}`; - templates.push(``); + templates.push( + `` + ); reference = ` data-resource-slots="${id}"`; } return `${content}`; }; - return renderChildren(root).replace(/(aria-label|title|placeholder|alt)="@([^"]+)"/g, (_, attribute, key) => `${attribute}="${escape(exports.get(dictionary, key))}"`); + return renderChildren(root).replace( + /(aria-label|title|placeholder|alt)="@([^"]+)"/g, + (_, attribute, key) => `${attribute}="${escape(exports.get(dictionary, key))}"` + ); }; From bbb6a42e680b5401481fb863d23d82da8c49c8eb Mon Sep 17 00:00:00 2001 From: qian-o <1324771795@qq.com> Date: Mon, 21 Sep 2026 23:19:45 +0800 Subject: [PATCH 29/35] Refactor CSS and JavaScript for improved readability and consistency - Updated CSS files to use shorthand for numeric values and consolidated selectors for hover states. - Refactored JavaScript files to enhance readability by reducing line breaks and simplifying conditional statements. - Improved the handling of resource strings and placeholders in resource-format.js and resources.js. - Streamlined the search functionality in search.js, ensuring consistent formatting and error handling. - Enhanced the navigation loading process in navigation.js for better performance and clarity. - Made minor adjustments to syntax highlighting in syntax.js for better keyword management. --- documents/api/index.md | 38 +- documents/images/Zenith.NET-Logo.svg | 61 +- documents/images/Zenith.NET.svg | 54 +- documents/index.md | 110 +-- documents/learn/concepts/execution-model.md | 202 +--- .../learn/concepts/platform-integration.md | 322 ++----- .../learn/concepts/resource-management.md | 409 ++------- .../learn/concepts/shader-data-and-binding.md | 227 +---- documents/learn/concepts/synchronization.md | 239 +---- documents/learn/first-triangle.md | 861 ++++-------------- documents/learn/index.md | 112 +-- documents/learn/samples.md | 275 ++---- .../templates/ManagedReference.extension.js | 13 +- documents/templates/layout/_master.tmpl | 10 +- .../templates/partials/api.enum.tmpl.partial | 3 +- .../partials/api.header.tmpl.partial | 3 +- .../partials/api.member-launcher.tmpl.partial | 3 +- .../partials/api.namespace.tmpl.partial | 3 +- .../partials/api.signature.tmpl.partial | 6 +- .../partials/api.source.tmpl.partial | 4 +- .../templates/partials/api.type.tmpl.partial | 8 +- .../partials/site.header.tmpl.partial | 23 +- .../partials/site.language.tmpl.partial | 10 +- .../partials/site.member-finder.tmpl.partial | 29 +- .../partials/site.search.tmpl.partial | 44 +- .../partials/site.sidebar.tmpl.partial | 45 +- documents/templates/public/api.css | 97 +- documents/templates/public/api.js | 50 +- documents/templates/public/content.css | 17 +- documents/templates/public/dialog.js | 48 +- documents/templates/public/home.css | 34 +- documents/templates/public/home.js | 76 +- documents/templates/public/languages.js | 57 +- documents/templates/public/layout.css | 34 +- documents/templates/public/main.css | 14 +- documents/templates/public/member-finder.js | 41 +- documents/templates/public/motion.css | 80 +- documents/templates/public/motion.js | 41 +- documents/templates/public/navigation.js | 26 +- documents/templates/public/outline.js | 3 +- documents/templates/public/resource-format.js | 25 +- documents/templates/public/resources.js | 24 +- documents/templates/public/search.css | 25 +- documents/templates/public/search.js | 114 +-- documents/templates/public/signature-links.js | 45 +- documents/templates/public/site.js | 24 +- documents/templates/public/syntax.js | 15 +- documents/templates/public/theme.css | 9 +- documents/templates/resources.common.js | 32 +- 49 files changed, 948 insertions(+), 3097 deletions(-) diff --git a/documents/api/index.md b/documents/api/index.md index d686959c..665c67fc 100644 --- a/documents/api/index.md +++ b/documents/api/index.md @@ -5,46 +5,24 @@ description: '@reference.meta.description' diff --git a/documents/images/Zenith.NET-Logo.svg b/documents/images/Zenith.NET-Logo.svg index be82c480..062d1848 100644 --- a/documents/images/Zenith.NET-Logo.svg +++ b/documents/images/Zenith.NET-Logo.svg @@ -1,18 +1,6 @@ - + Zenith.NET - - A graphite Z icon with a fine top-lit edge reflection, paired with a silver-white Zenith.NET wordmark for dark - backgrounds. - + A graphite Z icon with a fine top-lit edge reflection, paired with a silver-white Zenith.NET wordmark for dark backgrounds. - + diff --git a/documents/images/Zenith.NET.svg b/documents/images/Zenith.NET.svg index b059fb56..4e06193a 100644 --- a/documents/images/Zenith.NET.svg +++ b/documents/images/Zenith.NET.svg @@ -1,18 +1,6 @@ - + Zenith.NET - - A white Z on a vertically shaded graphite background, with a fine edge reflection that fades softly from top to - bottom. - + A white Z on a vertically shaded graphite background, with a fine edge reflection that fades softly from top to bottom. @@ -33,45 +21,15 @@ - + - - + + - + diff --git a/documents/index.md b/documents/index.md index c3f4bbc1..cc556272 100644 --- a/documents/index.md +++ b/documents/index.md @@ -9,56 +9,32 @@ _disableAffix: true
    -

    - - -
    -
    -

    -

    - -

    +


    +

    - - - - - - + +

    DirectX · Metal · Vulkan

    - +
    -
    - - +
    + +
    -

    - -

    -

    - -

    +

    +

    diff --git a/documents/learn/concepts/execution-model.md b/documents/learn/concepts/execution-model.md index 12dad46d..cfebfb95 100644 --- a/documents/learn/concepts/execution-model.md +++ b/documents/learn/concepts/execution-model.md @@ -2,198 +2,80 @@ title: '@concepts.execution.title' --- -

    - -

    -

    - -

    -

    - -

    -

    - - GraphicsContext - -

    -

    - - Capabilities - RayTracingSupported - MeshShadingSupported - - - -

    -

    - -

    -

    - -

    -

    - - GraphicsQueue - -

    +

    +

    +

    +

    GraphicsContext

    +

    CapabilitiesRayTracingSupportedMeshShadingSupported

    +

    +

    +

    GraphicsQueue

    - - + + - - + + - - + + - - + +
    - - - -
    - GraphicsQueue - - - - GraphicsQueue
    - ComputeQueue - - - - ComputeQueue
    - TransferQueue - - - - TransferQueue
    -

    - -

    -

    - - - -

    -

    - -

    -

    - - queue.CommandBuffer() - CommandBuffer - Submit() - TimelineValue - -

    -

    - commandBuffer - -

    +

    +

    +

    +

    queue.CommandBuffer()CommandBufferSubmit()TimelineValue

    +

    commandBuffer

    ```csharp commandBuffer.Submit().Wait(); ``` -

    - - Submit() - Wait() - -

    -

    - - queue.CommandBuffer() - -

    -

    - -

    -

    - -

    -

    - -

    -

    - - - - -

    -

    - -

    -

    - -

    +

    Submit()Wait()

    +

    queue.CommandBuffer()

    +

    +

    +

    +

    +

    +

    - - + + - - + + - - + + - - + + - - + +
    - - - -
    - - - -
    - - - -
    - SwapChain.Drawable - - - - SwapChain.Drawable
    - - - -
    -

    - - Dispose() - -

    -

    - -

    -

    - - - -

    +

    Dispose()

    +

    +

    diff --git a/documents/learn/concepts/platform-integration.md b/documents/learn/concepts/platform-integration.md index 679d0eff..1b43110a 100644 --- a/documents/learn/concepts/platform-integration.md +++ b/documents/learn/concepts/platform-integration.md @@ -2,164 +2,59 @@ title: '@concepts.platforms.title' --- -

    - -

    -

    - -

    -

    - -

    -

    - -

    -

    - - - Surface - SwapChain - -

    -

    - -

    +

    +

    +

    +

    +

    SurfaceSwapChain

    +

    - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + +
    - - - - - -
    - - Win32 - - HWND - - - Win32HWND
    - - Wayland - - - - - - Wayland
    - - Xlib - - - - - - Xlib
    - - Android - - ANativeWindow - - - AndroidANativeWindow
    - - Apple - - CAMetalLayer - - - AppleCAMetalLayer
    -

    - - App.cs - Surface.Wayland - -

    -

    - -

    -

    - -

    -

    - - SwapChain.Drawable - -

    -

    - - SwapChain.Resize - SwapChain.Refresh - -

    -

    - - - -

    -

    - -

    -

    - -

    -

    - - IZenithView - GraphicsContext - UpdateRequested - RenderRequested - RenderEventArgs - -

    -

    - - ColorAttachment - -

    -

    - - IZenithView - view - using Zenith.NET; - -

    +

    App.csSurface.Wayland

    +

    +

    +

    SwapChain.Drawable

    +

    SwapChain.ResizeSwapChain.Refresh

    +

    +

    +

    +

    IZenithViewGraphicsContextUpdateRequestedRenderRequestedRenderEventArgs

    +

    ColorAttachment

    +

    IZenithViewviewusing Zenith.NET;

    ```csharp view.RenderRequested += (_, args) => @@ -170,144 +65,51 @@ view.RenderRequested += (_, args) => }; ``` -

    - - ColorAttachment - -

    -

    - - Undefined - -

    -

    - - ZenithViewHelper.DrawableFormat - -

    -

    - - Desc.Width - Desc.Height - Desc.Format - Desc.SampleCount - -

    -

    - -

    -

    - -

    +

    ColorAttachment

    +

    Undefined

    +

    ZenithViewHelper.DrawableFormat

    +

    Desc.WidthDesc.HeightDesc.FormatDesc.SampleCount

    +

    +

    - - + + - - + + - - + + - - + + - - + + - - + + - - + +
    - - - -
    - - - - WriteableBitmap - ZenithView.cs - Surface.cs - - WriteableBitmapZenithView.csSurface.cs
    - - - - HWND - ZenithView.cs - - HWNDZenithView.cs
    - - - - D3DImage - Surface.cs - - D3DImageSurface.cs
    - - - - SwapChainPanel - ZenithView.WinUI.cs - - SwapChainPanelZenithView.WinUI.cs
    - - - - WriteableBitmap - ZenithView.Uno.cs - - WriteableBitmapZenithView.Uno.cs
    - - - - - -
    -

    - - RenderRequested - -

    -

    - - Zenith.NET.Views.Avalonia - -

    +

    RenderRequested

    +

    Zenith.NET.Views.Avalonia

    -

    - UseZenithView - Extensions.cs - -

    -

    - -

    -

    - - GraphicsContext - -

    -

    - -

    -

    - - FrameScheduler.cs - -

    +

    UseZenithViewExtensions.cs

    +

    +

    GraphicsContext

    +

    +

    FrameScheduler.cs

    diff --git a/documents/learn/concepts/resource-management.md b/documents/learn/concepts/resource-management.md index be4afc4d..208a12df 100644 --- a/documents/learn/concepts/resource-management.md +++ b/documents/learn/concepts/resource-management.md @@ -2,404 +2,167 @@ title: '@concepts.resources.title' --- -

    - -

    -

    - -

    -

    - -

    -

    - - BufferUsages - TextureUsages - BufferDesc.Usages - TextureDesc.Usages - | - -

    -

    - -

    +

    +

    +

    +

    BufferUsagesTextureUsagesBufferDesc.UsagesTextureDesc.Usages|

    +

    - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + +
    - - - -
    - None - - - - None
    - Vertex - - - - Vertex
    - Index - - - - Index
    - Indirect - - - - Indirect
    - Constant - - - - Constant
    - StorageReadOnly - - - - StorageReadOnly
    - StorageReadWrite - - - - StorageReadWrite
    - TransferSrc - - - - TransferSrc
    - TransferDst - - - - TransferDst
    -

    - -

    +

    - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + +
    - - - -
    - None - - - - None
    - Sampled - - - - Sampled
    - Storage - - - - Storage
    - ColorAttachment - - - - ColorAttachment
    - - DepthStencilAttachment - - - - DepthStencilAttachment
    - TransferSrc - - - - TransferSrc
    - TransferDst - - - - TransferDst
    -

    - -

    -

    - - - -

    -

    - -

    -

    - -

    -

    - - BufferDesc - Residency - -

    +

    +

    +

    +

    +

    BufferDescResidency

    - - - + + + - - - + + + - - - + + + - - - + + +
    - - - - - -
    - GpuOnly - - - - - - GpuOnly
    - CpuReadOnly - - - - - - CpuReadOnly
    - CpuWriteOnly - - - - - - CpuWriteOnly
    -

    - - CpuWriteOnly - -

    -

    - - TextureDesc - -

    -

    - - Map() - Unmap() - -

    -

    - -

    -

    - -

    +

    CpuWriteOnly

    +

    TextureDesc

    +

    Map()Unmap()

    +

    +

    - - + + - - + + - - + + - - + +
    - - - -
    - - Buffer.Upload - - - - CpuWriteOnly - - Buffer.UploadCpuWriteOnly
    - - Buffer.Download - - - - CpuReadOnly - - Buffer.DownloadCpuReadOnly
    - - Texture.Upload - Texture.Download - - - - Texture.UploadTexture.Download
    -

    - -

    -

    - - CommandBuffer.Upload - CommandBuffer.Download - -

    +

    +

    CommandBuffer.UploadCommandBuffer.Download

    -

    - - - -

    -

    - -

    -

    - - Heap - -

    -

    - - context.GetSizeAndAlignment - -

    -

    - -

    -

    - -

    -

    - -

    -

    - -

    -

    - - BufferView - TextureView - -

    -

    - - - -

    +

    +

    +

    Heap

    +

    context.GetSizeAndAlignment

    +

    +

    +

    +

    +

    BufferViewTextureView

    +

    diff --git a/documents/learn/concepts/shader-data-and-binding.md b/documents/learn/concepts/shader-data-and-binding.md index d059bd98..39cf1a73 100644 --- a/documents/learn/concepts/shader-data-and-binding.md +++ b/documents/learn/concepts/shader-data-and-binding.md @@ -2,26 +2,11 @@ title: '@concepts.shaders.title' --- -

    - -

    -

    - -

    -

    - -

    -

    - - ZenithCompiler - ShaderDesc - GraphicsApi - -

    -

    - context - -

    +

    +

    +

    +

    ZenithCompilerShaderDescGraphicsApi

    +

    context

    ```csharp string shaderPath = Path.Combine(AppContext.BaseDirectory, "Triangle.slang"); @@ -29,41 +14,13 @@ string shaderPath = Path.Combine(AppContext.BaseDirectory, "Triangle.slang"); Shader vertexShader = context.CreateShader(ZenithCompiler.CompileFromFile(context.GraphicsApi, shaderPath, "VSMain")); ``` -

    - VSMain - - -

    -

    - -

    -

    - -

    -

    - - InputLayout - Float3 - Float4 - InputLayout.Add - -

    -

    - - InputLayout - float3 - -

    -

    - -

    -

    - - - System.Runtime.InteropServices - Zenith.NET - -

    +

    VSMain

    +

    +

    +

    InputLayoutFloat3Float4InputLayout.Add

    +

    InputLayoutfloat3

    +

    +

    System.Runtime.InteropServicesZenith.NET

    ```csharp [StructLayout(LayoutKind.Explicit, Size = 256)] @@ -83,11 +40,7 @@ file struct Constants } ``` -

    - - ComputeShader.slang - -

    +

    ComputeShader.slang

    ```slang struct Constants @@ -104,37 +57,14 @@ struct Constants ConstantBuffer constants; ``` -

    - -

    -

    - -

    -

    - - - Matrix4x4 - - mul(vector, matrix) - -

    -

    - -

    -

    - -

    -

    - -

    -

    - - SetConstantBuffer - -

    -

    - -

    +

    +

    +

    Matrix4x4mul(vector, matrix)

    +

    +

    +

    +

    SetConstantBuffer

    +

    ```csharp commandBuffer.SetPipeline(computePipeline); @@ -142,111 +72,46 @@ commandBuffer.SetConstantBuffer(constantBuffer, 0); commandBuffer.Dispatch(groupCountX, groupCountY, 1); ``` -

    - commandBuffer - computePipeline - constantBuffer - BufferUsages.Constant - -

    -

    - Input - inputTexture.SampledHandle - Output - outputTexture.StorageHandle - DescriptorHandle - -

    +

    commandBuffercomputePipelineconstantBufferBufferUsages.Constant

    +

    InputinputTexture.SampledHandleOutputoutputTexture.StorageHandleDescriptorHandle

    - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + +
    - - - - - -
    texture.SampledHandle - DescriptorHandle<Texture2D> - - - texture.SampledHandleDescriptorHandle<Texture2D>
    texture.StorageHandle - DescriptorHandle<RWTexture2D<float4>> - - - texture.StorageHandleDescriptorHandle<RWTexture2D<float4>>
    buffer.StorageReadOnlyHandle - DescriptorHandle<StructuredBuffer<T>> - - - T - - buffer.StorageReadOnlyHandleDescriptorHandle<StructuredBuffer<T>>T
    buffer.StorageReadWriteHandle - DescriptorHandle<RWStructuredBuffer<T>> - - - T - - buffer.StorageReadWriteHandleDescriptorHandle<RWStructuredBuffer<T>>T
    sampler.Handle - DescriptorHandle<SamplerState> - - - sampler.HandleDescriptorHandle<SamplerState>
    -

    - - ResourceHandle - -

    -

    - - - -

    -

    - -

    -

    - - Dispatch - [numthreads(16, 16, 1)] - -

    -

    - - ShaderDesc.ThreadGroupSize - Dispatch - ComputeShaderRenderer.cs - - -

    +

    ResourceHandle

    +

    +

    +

    Dispatch[numthreads(16, 16, 1)]

    +

    ShaderDesc.ThreadGroupSizeDispatchComputeShaderRenderer.cs

    diff --git a/documents/learn/concepts/synchronization.md b/documents/learn/concepts/synchronization.md index 01397cbc..e1eb63f4 100644 --- a/documents/learn/concepts/synchronization.md +++ b/documents/learn/concepts/synchronization.md @@ -2,173 +2,67 @@ title: '@concepts.synchronization.title' --- -

    - -

    -

    - -

    -

    - -

    -

    - -

    -

    - -

    +

    +

    +

    +

    +

    - - + + - - + + - - + + - - + + - - + +
    - - - -
    - - - - CommandBuffer.Barrier - - CommandBuffer.Barrier
    - - - - CommandBuffer.Transition - - CommandBuffer.Transition
    - - - - TimelineValue - Submit - - TimelineValueSubmit
    - - - - Wait() - - Wait()
    -

    - -

    -

    - -

    -

    - -

    -

    - -

    +

    +

    +

    +

    ```csharp commandBuffer.Barrier(BarrierStages.ComputeShading, BarrierStages.ComputeShading); ``` -

    - -

    -

    - - - -

    -

    - - BarrierStages.All - -

    -

    - -

    -

    - -

    -

    - - TextureLayout - Storage - -

    +

    +

    +

    BarrierStages.All

    +

    +

    +

    TextureLayoutStorage

    ```csharp commandBuffer.Transition(outputTexture, default, TextureLayout.Storage, TextureLayout.Sampled); ``` -

    - - outputTexture - Sampled | Storage - Storage - default - -

    -

    - - Transition - -

    -

    - - Undefined - -

    -

    - -

    -

    - - Transition - Barrier - -

    -

    - - - -

    -

    - -

    -

    - -

    -

    - - Submit() - TimelineValue - Value - -

    -

    - producer - consumer - -

    +

    outputTextureSampled | StorageStoragedefault

    +

    Transition

    +

    Undefined

    +

    +

    TransitionBarrier

    +

    +

    +

    +

    Submit()TimelineValueValue

    +

    producerconsumer

    ```csharp TimelineValue produced = producer.Submit(); @@ -176,60 +70,19 @@ TimelineValue produced = producer.Submit(); TimelineValue consumed = consumer.Submit(produced); ``` -

    - - produced.Wait() - consumed - -

    -

    - -

    +

    produced.Wait()consumed

    +

    ```csharp consumed.Wait(); ``` -

    - - Wait() - queue.Timeline.Signal() - Signal() - -

    -

    - -

    -

    - - IsCompleted - -

    -

    - - CommandBuffer.Download - Wait() - -

    -

    - - IsCompleted - - -

    -

    - -

    -

    - -

    -

    - - SwapChain.Resize - -

    -

    - - SwapChain.Present() - -

    +

    Wait()queue.Timeline.Signal()Signal()

    +

    +

    IsCompleted

    +

    CommandBuffer.DownloadWait()

    +

    IsCompleted

    +

    +

    +

    SwapChain.Resize

    +

    SwapChain.Present()

    diff --git a/documents/learn/first-triangle.md b/documents/learn/first-triangle.md index e114091f..fe0485cd 100644 --- a/documents/learn/first-triangle.md +++ b/documents/learn/first-triangle.md @@ -2,127 +2,54 @@ title: '@tutorial.title' --- -

    - -

    -

    - -

    -

    - -

    -

    - -

    -

    1. -

    -

    - - - net10.0 - -

    +

    +

    +

    +

    +

    1.

    +

    net10.0

    - - + + - - + + - - + + - - + +
    - - - -
    - - - -
    - - - -
    - - - -
    -

    - - CAMetalLayer.cs - -

    -

    - - - - -

    -

    - -

    -

    2. -

    -

    - FirstTriangle - -

    -

    - -

    +

    CAMetalLayer.cs

    +

    +

    +

    2.

    +

    FirstTriangle

    +

      -
    • Silk.NET.Windowing -
    • -
    • Zenith.NET -
    • -
    • Zenith.NET.Compiler -
    • -
    • Zenith.NET.DirectX12 -
    • -
    • Zenith.NET.Metal -
    • -
    • Zenith.NET.Vulkan -
    • +
    • Silk.NET.Windowing
    • +
    • Zenith.NET
    • +
    • Zenith.NET.Compiler
    • +
    • Zenith.NET.DirectX12
    • +
    • Zenith.NET.Metal
    • +
    • Zenith.NET.Vulkan
    -

    - Zenith.NET - Zenith.NET.Compiler - -

    -

    - - - AllowUnsafeBlocks - -

    -

    - -

    -

    3. -

    -

    - - CocoaHelper.cs - -

    -

    - Program.cs - Main - -

    +

    Zenith.NETZenith.NET.Compiler

    +

    AllowUnsafeBlocks

    +

    +

    3.

    +

    CocoaHelper.cs

    +

    Program.csMain

    ```csharp using Silk.NET.Windowing; @@ -141,32 +68,13 @@ window.Run(); window.Dispose(); ``` -

    - GraphicsAPI.None - Initialize()Center() - Run()Dispose() - -

    -

    - -

    -

    - -

    -

    4. -

    -

    - -

    -

    - - GraphicsContext - -

    -

    - Program.cs - -

    +

    GraphicsAPI.NoneInitialize()Center()Run()Dispose()

    +

    +

    +

    4.

    +

    +

    GraphicsContext

    +

    Program.cs

    ```csharp using Zenith.NET; @@ -175,14 +83,7 @@ using Zenith.NET.Metal; using Zenith.NET.Vulkan; ``` -

    - - IWindow window - - - - -

    +

    IWindow window

    ```csharp GraphicsContext context; @@ -202,23 +103,9 @@ else context.ValidationMessage += static (_, args) => Console.WriteLine($"[{args.Severity}] {args.Message}"); ``` -

    - - ValidationMessage - -

    -

    - -

    -

    - - window.Center() - window.Run() - - - - -

    +

    ValidationMessage

    +

    +

    window.Center()window.Run()

    ```csharp uint width = (uint)window.FramebufferSize.X; @@ -239,21 +126,10 @@ else } ``` -

    - - Surface - FramebufferSize - -

    -

    - -

    -

    - -

    -

    - -

    +

    SurfaceFramebufferSize

    +

    +

    +

    ```csharp SwapChain swapChain = context.CreateSwapChain(new() @@ -263,26 +139,9 @@ SwapChain swapChain = context.CreateSwapChain(new() }); ``` -

    - - SwapChain - Drawable - Texture - Present() - -

    -

    - - B8G8R8A8UNorm - UNorm - swapChain.Desc.Format - -

    -

    - window.Dispose(); - Program.cs - -

    +

    SwapChainDrawableTexturePresent()

    +

    B8G8R8A8UNormUNormswapChain.Desc.Format

    +

    window.Dispose();Program.cs

    ```csharp swapChain.Dispose(); @@ -291,22 +150,10 @@ window.Dispose(); context.Dispose(); ``` -

    - -

    -

    5. -

    -

    - -

    -

    - _ - window.Run(); - - - - -

    +

    +

    5.

    +

    +

    _window.Run();

    ```csharp window.Render += _ => @@ -334,58 +181,17 @@ window.Render += _ => }; ``` -

    - -

    -

    - - GraphicsQueue.CommandBuffer() - -

    -

    - - Transition - default - Undefined - -

    -

    - -

    -

    - -

    -

    - - ColorAttachment.Clear - BeginRenderPass - -

    -

    - null - -

    -

    - - BeginRenderPass - -

    -

    - - EndRenderPass - Submit() - Wait() - Present() - -

    -

    - -

    -

    - FramebufferResize - window.Run(); - -

    +

    +

    GraphicsQueue.CommandBuffer()

    +

    TransitiondefaultUndefined

    +

    +

    +

    ColorAttachment.ClearBeginRenderPass

    +

    null

    +

    BeginRenderPass

    +

    EndRenderPassSubmit()Wait()Present()

    +

    +

    FramebufferResizewindow.Run();

    ```csharp window.FramebufferResize += _ => @@ -402,49 +208,21 @@ window.FramebufferResize += _ => }; ``` -

    - - - -

    -

    - - Present() - - -

    -

    - -

    -

    - -

    -

    6. -

    -

    - -

    -

    - -

    -

    - Program.cs - -

    +

    +

    Present()

    +

    +

    +

    6.

    +

    +

    +

    Program.cs

    ```csharp using System.Numerics; using System.Runtime.InteropServices; ``` -

    - - Program.cs - - - - -

    +

    Program.cs

    ```csharp [StructLayout(LayoutKind.Sequential)] @@ -456,24 +234,9 @@ file struct Vertex(Vector3 position, Vector4 color) } ``` -

    - file - Program.cs - LayoutKind.Sequential - PositionColor - -

    -

    - -

    -

    - - window.Render += _ => - - - - -

    +

    fileProgram.csLayoutKind.SequentialPositionColor

    +

    +

    window.Render += _ =>

    ```csharp Vertex[] vertices = @@ -484,29 +247,11 @@ Vertex[] vertices = ]; ``` -

    - Vertex - newVector3 - Vector4w = 1 - -

    -

    - -

    -

    - -

    -

    - Program.cs - using Buffer = Zenith.NET.Buffer; - System.Buffer - -

    -

    - - Buffer - -

    +

    VertexnewVector3Vector4w = 1

    +

    +

    +

    Program.csusing Buffer = Zenith.NET.Buffer;System.Buffer

    +

    Buffer

    ```csharp Buffer vertexBuffer; @@ -532,43 +277,14 @@ unsafe } ``` -

    - - sizeof(Vertex) * vertices.Length - BufferUsages.Vertex - CpuWriteOnly - -

    -

    - - Upload - -

    -

    - fixed - Upload - -

    -

    - - vertexBuffer.Dispose(); - swapChain.Dispose(); - Program.cs - - -

    -

    - -

    -

    7. -

    -

    - -

    -

    - Triangle.slang - -

    +

    sizeof(Vertex) * vertices.LengthBufferUsages.VertexCpuWriteOnly

    +

    Upload

    +

    fixedUpload

    +

    vertexBuffer.Dispose();swapChain.Dispose();Program.cs

    +

    +

    7.

    +

    +

    Triangle.slang

    ```slang struct VSInput @@ -586,23 +302,10 @@ struct FSInput }; ``` -

    - VSInput - POSITION0COLOR0 - -

    -

    - FSInput - SV_POSITIONCOLOR0 - -

    -

    - -

    -

    - Triangle.slang - -

    +

    VSInputPOSITION0COLOR0

    +

    FSInputSV_POSITIONCOLOR0

    +

    +

    Triangle.slang

    ```slang [shader("vertex")] @@ -616,16 +319,9 @@ FSInput VSMain(VSInput input) } ``` -

    - w = 1 - -

    -

    - -

    -

    - -

    +

    w = 1

    +

    +

    ```slang [shader("fragment")] @@ -635,25 +331,10 @@ float4 FSMain(FSInput input) : SV_TARGET } ``` -

    - FSMain - SV_TARGET - -

    -

    - -

    -

    - - Triangle.slang - - - -

    -

    - Program.cs - -

    +

    FSMainSV_TARGET

    +

    +

    Triangle.slang

    +

    Program.cs

    ```csharp string shaderPath = Path.Combine(AppContext.BaseDirectory, "Triangle.slang"); @@ -662,27 +343,11 @@ Shader vertexShader = context.CreateShader(ZenithCompiler.CompileFromFile(contex Shader fragmentShader = context.CreateShader(ZenithCompiler.CompileFromFile(context.GraphicsApi, shaderPath, "FSMain")); ``` -

    - - ZenithCompiler - CreateShader - context.GraphicsApi - VSMainFSMain - -

    -

    - - AppContext.BaseDirectory - -

    -

    - -

    -

    8. -

    -

    - -

    +

    ZenithCompilerCreateShadercontext.GraphicsApiVSMainFSMain

    +

    AppContext.BaseDirectory

    +

    +

    8.

    +

    ```csharp InputLayout inputLayout = new(); @@ -690,117 +355,50 @@ inputLayout.Add(new() { Format = ElementFormat.Float3, Semantic = ElementSemanti inputLayout.Add(new() { Format = ElementFormat.Float4, Semantic = ElementSemantic.Color }); ``` -

    - - InputLayout.Add - -

    +

    InputLayout.Add

    - - - - + + + + - + - - + + - + - - + + - + - - + +
    - - - - - - - -
    Vertex.Position - Vertex.Position 0 - - Float3 - - POSITION0 - Float3POSITION0
    Vertex.Color - Vertex.Color 12 - - Float4 - - COLOR0 - Float4COLOR0
    - - 28 - - - -
    -

    - - SemanticIndex - POSITION0COLOR0 - -

    -

    - -

    -

    9. -

    -

    - - GraphicsPipeline - -

    -

    - -

    +

    SemanticIndexPOSITION0COLOR0

    +

    +

    9.

    +

    GraphicsPipeline

    +

    -

    - -

    +

    ```csharp GraphicsPipeline pipeline = context.CreateGraphicsPipeline(new() @@ -826,24 +424,10 @@ vertexShader.Dispose(); fragmentShader.Dispose(); ``` -

    - - pipeline.Dispose(); - vertexBuffer.Dispose(); - -

    -

    - -

    -

    10. -

    -

    - window.Render - // Add the triangle draw commands here later. - BeginRenderPass - EndRenderPass - -

    +

    pipeline.Dispose();vertexBuffer.Dispose();

    +

    +

    10.

    +

    window.Render// Add the triangle draw commands here later.BeginRenderPassEndRenderPass

    ```csharp commandBuffer.SetPipeline(pipeline); @@ -852,99 +436,49 @@ commandBuffer.SetVertexBuffer(vertexBuffer, 0, 0); commandBuffer.Draw(3, 1, 0, 0); ``` -

    - - SetPipeline - -

    -

    - - SetVertexBuffer(vertexBuffer, 0, 0) - InputLayouts - -

    -

    - - Draw - -

    +

    SetPipeline

    +

    SetVertexBuffer(vertexBuffer, 0, 0)InputLayouts

    +

    Draw

    - - - + + + - + - + - + - + - + - + - + - +
    - - - - - -
    vertexCount - vertexCount 3 - -
    instanceCount - instanceCount 1 - -
    firstVertex - firstVertex 0 - -
    firstInstance - firstInstance 0 - -
    -

    - - Submit().Wait() - Present() - -

    -

    - -

    -

    11. -

    -

    - FirstTriangle - -

    - -

    - -

    -

    - -

    -

    - -

    -

    - -

    +

    Submit().Wait()Present()

    +

    +

    11.

    +

    FirstTriangle

    + +

    +

    +

    +

    ```text Get the current drawable @@ -960,11 +494,7 @@ Submit and wait Present ``` -

    - Run - window.Run(); - -

    +

    Runwindow.Run();

    ```csharp pipeline.Dispose(); @@ -975,78 +505,37 @@ window.Dispose(); context.Dispose(); ``` -

    - - Dispose() - -

    -

    - -

    -

    - -

    +

    Dispose()

    +

    +

    - - + + - - + + - - + + - - + + - - + + - - + +
    - - - -
    - - - -
    - - - -
    - - - - Triangle.slang - - Triangle.slang
    - - - -
    - - - -
    -

    - - - - Program.cs - - -

    +

    Program.cs

    diff --git a/documents/learn/index.md b/documents/learn/index.md index 92c27f42..305c5d8a 100644 --- a/documents/learn/index.md +++ b/documents/learn/index.md @@ -6,12 +6,8 @@ _disableAffix: true --- diff --git a/documents/learn/samples.md b/documents/learn/samples.md index 9a5eca9b..c473525d 100644 --- a/documents/learn/samples.md +++ b/documents/learn/samples.md @@ -2,237 +2,78 @@ title: '@samples.title' --- -

    - -

    -

    - - - -

    -

    - -

    -

    - -

    -

    - - - -

    -

    - -

    -

    - -

    -

    - - @samples.triangle.title - -

    -

    - - HelloTriangleRenderer.cs - HelloTriangle.slang - - -

    -

    - -

    -

    - - D32FloatS8UInt - -

    -

    - - @samples.cube.title - -

    -

    - - SpinningCubeRenderer.cs - SpinningCube.slang - -

    -

    - -

    -

    - - Assets/Textures/shoko.png - -

    -

    - - @samples.computeShader.title - -

    -

    - - ComputeShaderRenderer.cs - ComputeShader.slang - -

    -

    - -

    -

    - -

    -

    - - @samples.indirectDrawing.title - -

    -

    - - IndirectDrawingRenderer.cs - IndirectDrawing.slang - -

    -

    - -

    -

    - - context.Capabilities.RayTracingSupported - -

    -

    - - @samples.rayTracing.title - -

    -

    - - RayTracingRenderer.cs - RayTracing.slang - -

    -

    - -

    -

    - - context.Capabilities.MeshShadingSupported - -

    -

    - - @samples.meshShading.title - -

    -

    - - MeshShadingRenderer.cs - MeshShading.slang - -

    -

    - -

    -

    - - App.cs - IRenderer.cs - -

    -

    - - TexturePresenter.cs - PresentTexture.slang - -

    -

    - -

    -

    - -

    -

    - - - -

    +

    +

    +

    +

    +

    +

    +

    +

    + @samples.triangle.title +

    +

    HelloTriangleRenderer.csHelloTriangle.slang

    +

    +

    D32FloatS8UInt

    +

    + @samples.cube.title +

    +

    SpinningCubeRenderer.csSpinningCube.slang

    +

    +

    Assets/Textures/shoko.png

    +

    + @samples.computeShader.title +

    +

    ComputeShaderRenderer.csComputeShader.slang

    +

    +

    +

    + @samples.indirectDrawing.title +

    +

    IndirectDrawingRenderer.csIndirectDrawing.slang

    +

    +

    context.Capabilities.RayTracingSupported

    +

    + @samples.rayTracing.title +

    +

    RayTracingRenderer.csRayTracing.slang

    +

    +

    context.Capabilities.MeshShadingSupported

    +

    + @samples.meshShading.title +

    +

    MeshShadingRenderer.csMeshShading.slang

    +

    +

    App.csIRenderer.cs

    +

    TexturePresenter.csPresentTexture.slang

    +

    +

    +

    - - + + - - + + - - + + - - + + - - + +
    - - - -
    - - - - - -
    - - - - - -
    - - - - - -
    - - - - - -
    -

    - - - -

    +

    diff --git a/documents/templates/ManagedReference.extension.js b/documents/templates/ManagedReference.extension.js index fa035230..ba8aea37 100644 --- a/documents/templates/ManagedReference.extension.js +++ b/documents/templates/ManagedReference.extension.js @@ -16,9 +16,7 @@ function prepareSignature(syntax, strings) { }; } syntax.apiParameterDescriptions = (syntax.parameters || []).filter(parameter => parameter.description?.trim()); - syntax.apiTypeParameterDescriptions = (syntax.typeParameters || []).filter(parameter => - parameter.description?.trim() - ); + syntax.apiTypeParameterDescriptions = (syntax.typeParameters || []).filter(parameter => parameter.description?.trim()); } function uidSuffix(uid) { @@ -34,22 +32,19 @@ exports.postTransform = function (model) { model.apiHasMemberFinder = !model.isNamespace; model.apiSeeAlsoId = 'seealso'; const hasRelationships = relationshipKeys.some(key => model[key]?.length > 0); - model.apiHasTypeDetails = - !model.isNamespace && (hasRelationships || !!model.namespace?.uid || !!model.assemblies?.length); + model.apiHasTypeDetails = !model.isNamespace && (hasRelationships || !!model.namespace?.uid || !!model.assemblies?.length); model.apiTypeDetailsKey = 'ui.reference.' + (hasRelationships ? 'relationships' : 'metadata'); model.apiTypeDetailsLabel = resources.get(strings, model.apiTypeDetailsKey); prepareSignature(model.syntax, strings); if (model.syntax) { model.syntax.apiBaseReferences = [...(model.inheritance || []), ...(model.implements || [])] - .map(type => ({ type: type.specName?.[0]?.value })) - .filter(reference => reference.type); + .map(type => ({ type: type.specName?.[0]?.value })).filter(reference => reference.type); } const anchors = new Set([model.id]); const overloads = new Set(); for (const group of model.children || []) { - group.apiTitleKey = - 'ui.reference.' + (model.isEnum ? 'values' : group.id === 'eii' ? 'implementations' : group.id); + group.apiTitleKey = 'ui.reference.' + (model.isEnum ? 'values' : group.id === 'eii' ? 'implementations' : group.id); group.apiTitle = resources.get(strings, group.apiTitleKey); for (const item of group.children || []) { item.apiName = item.name?.[0]?.value || item.uid; diff --git a/documents/templates/layout/_master.tmpl b/documents/templates/layout/_master.tmpl index 437114d7..138eef05 100644 --- a/documents/templates/layout/_master.tmpl +++ b/documents/templates/layout/_master.tmpl @@ -7,8 +7,7 @@ {{#title}}{{title}}{{/title}}{{^title}}{{>partials/title}}{{/title}} {{#_appTitle}}| {{_appTitle}} {{/_appTitle}} - + {{#description}} {{/description}} @@ -49,8 +48,7 @@ - + {{>partials/site.header}}
    @@ -59,9 +57,7 @@
    {{^_disableToc}} {{#apiHasMemberFinder}}
    {{/apiHasMemberFinder}} - diff --git a/documents/templates/partials/api.enum.tmpl.partial b/documents/templates/partials/api.enum.tmpl.partial index 242a1142..37a10c9f 100644 --- a/documents/templates/partials/api.enum.tmpl.partial +++ b/documents/templates/partials/api.enum.tmpl.partial @@ -7,8 +7,7 @@
    {{#children}}
    -

    {{syntax.content.0.value}} -

    +

    {{syntax.content.0.value}}

    {{#summary}}
    {{{summary}}}
    {{/summary}} diff --git a/documents/templates/partials/api.header.tmpl.partial b/documents/templates/partials/api.header.tmpl.partial index a21f1bac..25df996e 100644 --- a/documents/templates/partials/api.header.tmpl.partial +++ b/documents/templates/partials/api.header.tmpl.partial @@ -9,8 +9,7 @@ {{/conceptual}} {{#syntax.content.0.value}} -
    +
    {{>partials/api.source}} {{>partials/api.code}}
    diff --git a/documents/templates/partials/api.member-launcher.tmpl.partial b/documents/templates/partials/api.member-launcher.tmpl.partial index 5f644305..becaee2f 100644 --- a/documents/templates/partials/api.member-launcher.tmpl.partial +++ b/documents/templates/partials/api.member-launcher.tmpl.partial @@ -1,5 +1,4 @@ -
    {{#children}} -
    - {{name.0.value}} +
    {{name.0.value}} {{#summary}}
    {{{summary}}}
    {{/summary}} diff --git a/documents/templates/partials/api.signature.tmpl.partial b/documents/templates/partials/api.signature.tmpl.partial index ba2d3e57..c4151f76 100644 --- a/documents/templates/partials/api.signature.tmpl.partial +++ b/documents/templates/partials/api.signature.tmpl.partial @@ -5,8 +5,7 @@
    {{#apiTypeParameterDescriptions}}
    -
    {{id}} -
    +
    {{id}}
    {{{description}}}
    {{/apiTypeParameterDescriptions}} @@ -19,8 +18,7 @@
    {{#apiParameterDescriptions}}
    -
    {{id}} -
    +
    {{id}}
    {{{description}}}
    {{/apiParameterDescriptions}} diff --git a/documents/templates/partials/api.source.tmpl.partial b/documents/templates/partials/api.source.tmpl.partial index 965f7dad..ad10699b 100644 --- a/documents/templates/partials/api.source.tmpl.partial +++ b/documents/templates/partials/api.source.tmpl.partial @@ -1,7 +1,5 @@ {{#sourceurl}} - + {{/sourceurl}} diff --git a/documents/templates/partials/api.type.tmpl.partial b/documents/templates/partials/api.type.tmpl.partial index d51c094c..1cbda4fa 100644 --- a/documents/templates/partials/api.type.tmpl.partial +++ b/documents/templates/partials/api.type.tmpl.partial @@ -26,16 +26,12 @@ {{/syntax}} {{#remarks}}
    -

    - {{r.ui.reference.remarks}} -

    {{{remarks}}} +

    {{r.ui.reference.remarks}}

    {{{remarks}}}
    {{/remarks}} {{#example.0}}
    -

    - {{r.ui.reference.examples}} -

    +

    {{r.ui.reference.examples}}

    {{#example}} {{{.}}} {{/example}} diff --git a/documents/templates/partials/site.header.tmpl.partial b/documents/templates/partials/site.header.tmpl.partial index 1b59e538..136d7421 100644 --- a/documents/templates/partials/site.header.tmpl.partial +++ b/documents/templates/partials/site.header.tmpl.partial @@ -1,11 +1,7 @@  diff --git a/documents/templates/partials/site.language.tmpl.partial b/documents/templates/partials/site.language.tmpl.partial index 5b7550a1..0370d620 100644 --- a/documents/templates/partials/site.language.tmpl.partial +++ b/documents/templates/partials/site.language.tmpl.partial @@ -1,18 +1,12 @@ 
    - - - + diff --git a/documents/templates/partials/site.member-finder.tmpl.partial b/documents/templates/partials/site.member-finder.tmpl.partial index 63cf1ed8..d6b0dae3 100644 --- a/documents/templates/partials/site.member-finder.tmpl.partial +++ b/documents/templates/partials/site.member-finder.tmpl.partial @@ -1,40 +1,27 @@ {{#apiHasMemberFinder}} - +

    {{r.ui.members.title}}

    {{fullName.0.value}}

    - +
    - +
    diff --git a/documents/templates/partials/site.search.tmpl.partial b/documents/templates/partials/site.search.tmpl.partial index 71e66aa2..b6b92c87 100644 --- a/documents/templates/partials/site.search.tmpl.partial +++ b/documents/templates/partials/site.search.tmpl.partial @@ -3,44 +3,24 @@

    {{r.ui.search.title}}

    -
    {{/_enableSearch}} diff --git a/documents/templates/partials/site.sidebar.tmpl.partial b/documents/templates/partials/site.sidebar.tmpl.partial index 3dbec45c..47d40e23 100644 --- a/documents/templates/partials/site.sidebar.tmpl.partial +++ b/documents/templates/partials/site.sidebar.tmpl.partial @@ -1,53 +1,32 @@ {{^_disableToc}}
    -
    +
    -
    - {{r.ui.contents.title}} -
    - +
    {{r.ui.contents.title}}
    +
    {{#_apiReference}} -