diff --git a/.gitignore b/.gitignore index c4f30e7b..4eb399ba 100644 --- a/.gitignore +++ b/.gitignore @@ -433,5 +433,5 @@ FodyWeavers.xsd ## macOS generated files .DS_Store -## DocFx generated files -_site/ \ No newline at end of file +## DocFX generated files +_site/ diff --git a/README.md b/README.md index 667734c0..59b05e5e 100644 --- a/README.md +++ b/README.md @@ -1,86 +1,91 @@ 

- Zenith.NET Logo + Zenith.NET icon

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 + Learn · + Samples · + 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 is a rendering hardware interface (RHI) that 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 a backend supported by your platform and graphics driver. 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; using Zenith.NET.Vulkan; using GraphicsContext context = GraphicsContext.CreateVulkan(useValidationLayer: true); + +context.ValidationMessage += static (_, args) => Console.WriteLine($"[{args.Severity}] {args.Message}"); ``` -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 [First Triangle](https://qian-o.github.io/Zenith.NET/learn/first-triangle.html) to build a .NET console application with NuGet packages, from an empty window to the first rendered frame. -## 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 [Platform Integration](https://qian-o.github.io/Zenith.NET/learn/concepts/platform-integration.html) for native surfaces, frame ownership and UI integration choices. -### 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) +- [Learn](https://qian-o.github.io/Zenith.NET/learn/) — a complete triangle tutorial and guides to the programming model. +- [Samples](https://qian-o.github.io/Zenith.NET/learn/samples.html) — focused examples with C# and Slang source links. +- [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). diff --git a/documents/api/.gitignore b/documents/api/.gitignore index 0b116cf8..dc922561 100644 --- a/documents/api/.gitignore +++ b/documents/api/.gitignore @@ -1,5 +1,3 @@ -############### -# temp file # -############### +# Generated DocFX API metadata *.yml -.manifest \ No newline at end of file +.manifest diff --git a/documents/api/index.md b/documents/api/index.md index a92e1ecc..d686959c 100644 --- a/documents/api/index.md +++ b/documents/api/index.md @@ -1,32 +1,50 @@ -# API Reference +--- +title: '@reference.title' +description: '@reference.meta.description' +--- -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. +
+
+

+ +

+

+ +

+
+
+ + + + + GraphicsContext +

+ +

+
+ + + + + CommandBuffer +

+ +

+
+
+
+
+

+ +

+
+
+ +
+
diff --git a/documents/docfx.json b/documents/docfx.json index 56d86754..ddd8b2c3 100644 --- a/documents/docfx.json +++ b/documents/docfx.json @@ -5,12 +5,8 @@ "src": [ { "src": "../sources", - "files": [ - "**/*.csproj" - ], - "exclude": [ - "Experiments/**" - ] + "files": "**/*.csproj", + "exclude": "Experiments/**" } ], "output": "api", @@ -20,37 +16,83 @@ "build": { "content": [ { - "files": [ - "api/**/*.{md,yml}", - "docs/**/*.{md,yml}", - "tutorials/**/*.{md,yml}", - "index.md", - "toc.yml" - ] + "files": ["api/**/*.{md,yml}", "learn/**/*.md", "index.md", "toc.yml", "locales/*/strings.yml"] } ], - "resource": [ - { - "files": [ - "images/**" - ] + "resource": { + "files": "images/**" + }, + "template": ["default", "modern", "templates"], + "fileMetadata": { + "_section": { + "learn/**": "learn", + "api/**": "api" + }, + "_apiReference": { + "api/**": true + }, + "_disableAffix": { + "api/**": true, + "learn/index.md": true + }, + "_disableToc": { + "learn/**": false, + "api/**": false } - ], - "template": [ - "default", - "modern", - "templates" - ], + }, "globalMetadata": { "_appTitle": "Zenith.NET", "_appLogoPath": "images/Zenith.NET-Logo.svg", "_appFaviconPath": "images/Zenith.NET.svg", "_enableSearch": true, - "_appFooter": "Zenith.NET is a modern rendering hardware interface for .NET.", "_gitContribute": { "repo": "https://github.com/qian-o/Zenith.NET", "branch": "master" - } + }, + "_languages": [ + { + "code": "de-DE", + "label": "Deutsch" + }, + { + "code": "en-US", + "label": "English" + }, + { + "code": "es-ES", + "label": "Español" + }, + { + "code": "fr-FR", + "label": "Français" + }, + { + "code": "ja-JP", + "label": "日本語" + }, + { + "code": "ko-KR", + "label": "한국어" + }, + { + "code": "pt-BR", + "label": "Português (Brasil)" + }, + { + "code": "ru-RU", + "label": "Русский" + }, + { + "code": "zh-CN", + "label": "简体中文" + }, + { + "code": "zh-TW", + "label": "繁體中文" + } + ], + "_lang": "en-US", + "_sourceLanguage": "en-US" }, "output": "_site", "sitemap": { 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 bd96a940..090eb8a7 100644 Binary files a/documents/images/Zenith.NET-Logo.png and b/documents/images/Zenith.NET-Logo.png differ diff --git a/documents/images/Zenith.NET-Logo.svg b/documents/images/Zenith.NET-Logo.svg index 71a8ceba..bcff91ea 100644 --- a/documents/images/Zenith.NET-Logo.svg +++ b/documents/images/Zenith.NET-Logo.svg @@ -1,37 +1,38 @@ - - Zenith.NET - - - - - - - - - - - - - - - - - - - - - + + Zenith.NET + A graphite Z icon with a fine top-lit edge reflection, paired with a silver-white Zenith.NET wordmark for dark backgrounds. + - - - + + +