Cogs.Core
RenderTargetsWebGPU.cpp
1#include "RenderTargetsWebGPU.h"
2
3#include "GraphicsDeviceWebGPU.h"
4#include "Foundation/Logging/Logger.h"
5
6#include <cassert>
7
8namespace{
9 Cogs::Logging::Log logger = Cogs::Logging::getLogger("RenderTargetsWebGPU");
10
11 void render_targets_error_callback(WGPUPopErrorScopeStatus status, WGPUErrorType type, WGPUStringView message, void* userdata1, void* userdata2)
12 {
13 Cogs::RenderTargetsWebGPU *render_targets = (Cogs::RenderTargetsWebGPU*)userdata1;
14 (void)render_targets;
16 (void)ptr;
17 if(status == WGPUPopErrorScopeStatus_CallbackCancelled){
18 LOG_ERROR(logger, "WebGPU render targets err status: Cancelled");
19 }
20 if(status == WGPUPopErrorScopeStatus_Error){
21 LOG_ERROR(logger, "WebGPU render targets err status: Error");
22 }
23 if(message.data && message.length){
24 LOG_ERROR(logger, "WebGPU render targets err (%d) %.*s", type, WGPUStringViewFormat(message));
25 }
26 }
27}
28
29namespace Cogs{
30
31 void RenderTargetsWebGPU::initialize(GraphicsDeviceWebGPU *graphicsDeviceIn)
32 {
33 graphicsDevice = graphicsDeviceIn;
34 }
35
37 {
38 ResourceCountersWebGPU &counters = graphicsDevice->counters;
39 RenderTargetWebGPU render_target = {};
40
41 if(graphicsDevice->use_error_scope){
42 wgpuDevicePushErrorScope(graphicsDevice->device, graphicsDevice->filter);
43 }
44
45 for(size_t i=0; i<numViews; i++){
46 const RenderTargetViewDescription &set = renderTargetViews[i];
47 assert(HandleIsValid(set.texture));
48 const TextureWebGPU &texture = graphicsDevice->textures.textures[set.texture];
49
50 WGPUTextureViewDescriptor desc = WGPU_TEXTURE_VIEW_DESCRIPTOR_INIT;
51 desc.format = texture.view_format;
52 desc.dimension = texture.view_dimension;
53 if(set.numLayers == 1){
54 switch(desc.dimension){
55 case WGPUTextureViewDimension_2DArray:
56 case WGPUTextureViewDimension_Cube:
57 case WGPUTextureViewDimension_CubeArray:
58 desc.dimension = WGPUTextureViewDimension_2D;
59 break;
60 default:
61 break;
62 }
63 }
64 desc.baseMipLevel = set.levelIndex;
65 desc.mipLevelCount = 1;
66 desc.baseArrayLayer = set.layerIndex;
67 desc.arrayLayerCount = set.numLayers;
68 desc.aspect = WGPUTextureAspect_All;
69 render_target.view[i] = wgpuTextureCreateView(texture.texture, &desc);
70 counters.texture_view++;
71 render_target.textureHandle[i] = set.texture;
72 render_target.format[i] = texture.view_format;
73 }
74 render_target.count = (uint32_t)numViews;
75
76 if(numViews){
77 const RenderTargetViewDescription &set = renderTargetViews[0];
78 const TextureWebGPU &texture = graphicsDevice->textures.textures[set.texture];
79 render_target.width = texture.width;
80 render_target.height = texture.height;
81 render_target.samples = texture.samples;
82 }
83
84 if(graphicsDevice->use_error_scope){
85 WGPUPopErrorScopeCallbackInfo info = WGPU_POP_ERROR_SCOPE_CALLBACK_INFO_INIT;
86 info.mode = WGPUCallbackMode_AllowSpontaneous;
87 info.callback = render_targets_error_callback;
88 info.userdata1 = this;
89 info.userdata2 = graphicsDevice;
90 WGPUFuture future = wgpuDevicePopErrorScope(graphicsDevice->device, info);
91 // WGPUWaitStatus wgpuInstanceWaitAny(WGPUInstance instance, size_t futureCount, WGPUFutureWaitInfo * futures, uint64_t timeoutNS);
92 }
93
94 return render_targets.addResource(std::move(render_target));
95 }
96
98 {
99 if(!HandleIsValid(handle)) return;
100 ResourceCountersWebGPU &counters = graphicsDevice->counters;
101 RenderTargetWebGPU &target = render_targets[handle];
102 for(size_t i=0; i<target.count; i++){
103 wgpuTextureViewRelease(target.view[i]);
104 counters.texture_view--;
105 }
106 render_targets.removeResource(handle);
107 }
108
110 {
111 RenderTargetWebGPU &target = render_targets[handle];
112 assert(target.width);
113 assert(target.height);
114 assert(target.samples);
115 TextureDescription tex_desc = {};
116 tex_desc.target = ResourceDimensions::Texture2D;
117 tex_desc.width = target.width;
118 tex_desc.height = target.height;
119 tex_desc.depth = 1;
120 tex_desc.layers = 1;
121 tex_desc.faces = 1;
122 tex_desc.levels = 1;
123 tex_desc.samples = target.samples;
124 tex_desc.format = TextureFormat::D32_FLOAT;
125 tex_desc.flags = TextureFlags::DepthBuffer;
126 TextureHandle textureHandle = graphicsDevice->textures.loadTexture(tex_desc, nullptr);
127 DepthStencilViewDescription view_desc = {};
128 view_desc.texture = textureHandle;
129 view_desc.layerIndex = 0;
130 view_desc.numLayers = 1;
131 view_desc.levelIndex = 0;
132 DepthStencilHandle ret = createDepthStencilTarget(handle, view_desc);
133 DepthStencilTargetWebGPU &ds = depth_stencil_targets[ret];
134 ds.textureHandle = textureHandle;
135 ds.freeTextureHandle = true;
136 return ret;
137 }
138
140 {
141 DepthStencilViewDescription view_desc = {};
142 view_desc.texture = textureHandle;
143 view_desc.layerIndex = 0;
144 view_desc.numLayers = 1;
145 view_desc.levelIndex = 0;
146 return createDepthStencilTarget(handle, view_desc);
147 }
148
150 {
151 DepthStencilTargetWebGPU depth_stencil_target;
152
153 if(graphicsDevice->use_error_scope){
154 wgpuDevicePushErrorScope(graphicsDevice->device, graphicsDevice->filter);
155 }
156
157 {
158 ResourceCountersWebGPU &counters = graphicsDevice->counters;
159 const DepthStencilViewDescription &set = depthStencilView;
160 const TextureWebGPU &texture = graphicsDevice->textures.textures[set.texture];
161
162 WGPUTextureViewDescriptor desc = WGPU_TEXTURE_VIEW_DESCRIPTOR_INIT;
163 desc.format = texture.view_format;
164 desc.dimension = texture.view_dimension;
165 if(set.numLayers == 1){
166 switch(desc.dimension){
167 case WGPUTextureViewDimension_2DArray:
168 case WGPUTextureViewDimension_CubeArray:
169 case WGPUTextureViewDimension_Cube:
170 desc.dimension = WGPUTextureViewDimension_2D;
171 break;
172 default:
173 break;
174 }
175 }
176 desc.baseMipLevel = set.levelIndex;
177 desc.mipLevelCount = 1;
178 desc.baseArrayLayer = set.layerIndex;
179 desc.arrayLayerCount = set.numLayers;
180 desc.aspect = WGPUTextureAspect_All;
181 depth_stencil_target.view = wgpuTextureCreateView(texture.texture, &desc);
182 counters.texture_view++;
183 depth_stencil_target.format = texture.view_format;
184 depth_stencil_target.samples = texture.samples;
185 }
186
187 if(graphicsDevice->use_error_scope){
188 WGPUPopErrorScopeCallbackInfo info = WGPU_POP_ERROR_SCOPE_CALLBACK_INFO_INIT;
189 info.mode = WGPUCallbackMode_AllowSpontaneous;
190 info.callback = render_targets_error_callback;
191 info.userdata1 = this;
192 info.userdata2 = graphicsDevice;
193 WGPUFuture future = wgpuDevicePopErrorScope(graphicsDevice->device, info);
194 // WGPUWaitStatus wgpuInstanceWaitAny(WGPUInstance instance, size_t futureCount, WGPUFutureWaitInfo * futures, uint64_t timeoutNS);
195 }
196
197 return depth_stencil_targets.addResource(std::move(depth_stencil_target));
198 }
199
201 {
202 if(!HandleIsValid(handle)) return;
203 ResourceCountersWebGPU &counters = graphicsDevice->counters;
204 DepthStencilTargetWebGPU &target = depth_stencil_targets[handle];
205 wgpuTextureViewRelease(target.view);
206 counters.texture_view--;
207 if(target.freeTextureHandle){
208 graphicsDevice->textures.releaseTexture(target.textureHandle);
209 }
210 depth_stencil_targets.removeResource(handle);
211 }
212
214 {
215 RenderTargetLayout layout;
216
217 if(HandleIsValid(renderTargetHandle)){
218 const RenderTargetWebGPU &target = render_targets[renderTargetHandle];
219 layout.numColorTargets = static_cast<uint8_t>(target.count);
220 layout.samples = static_cast<uint8_t>(target.samples);
221
222 for(size_t i=0; i<target.count; i++){
223 layout.colorFormats[i] = graphicsDevice->textures.textures[target.textureHandle[i]].format;
224 }
225 } else {
226 layout.numColorTargets = 1;
227 layout.colorFormats[0] = TextureFormat::B8G8R8A8_UNORM_SRGB;
228 layout.samples = static_cast<uint8_t>(graphicsDevice->defaultSwapChain.samples);
229 }
230
231 if(HandleIsValid(depthStencilHandle)){
232 const DepthStencilTargetWebGPU &target = depth_stencil_targets[depthStencilHandle];
233 layout.depthStencilFormat = graphicsDevice->textures.textures[target.textureHandle].format;
234 } else if(!HandleIsValid(renderTargetHandle)){
235 layout.depthStencilFormat = TextureFormat::D32_FLOAT;
236 }
237
238 return layout;
239 }
240
242 {
243 {
244 std::vector<RenderTargetHandle> handles;
245 for (auto& resource : render_targets) {
246 handles.push_back(render_targets.getHandle(resource));
247 }
248 for (auto& handle : handles) {
249 releaseRenderTarget(handle);
250 }
251 }
252 {
253 std::vector<DepthStencilHandle> handles;
254 for (auto& resource : depth_stencil_targets) {
255 handles.push_back(depth_stencil_targets.getHandle(resource));
256 }
257 for (auto& handle : handles) {
259 }
260 }
261 }
262
263}
Log implementation class.
Definition: LogManager.h:140
virtual void releaseRenderTarget(RenderTargetHandle handle) override
Release the render target with the given renderTargetHandle.
virtual DepthStencilHandle createDepthStencilTarget(const RenderTargetHandle handle) override
Creates a depth/stencil target to back the render target with the given handle.
virtual void releaseResources() override
Release all allocated render target resources.
virtual RenderTargetLayout getLayout(const RenderTargetHandle renderTargetHandle, const DepthStencilHandle depthStencilHandle) override
Get the view layout for the given render target / depth stencil target pair.
virtual void releaseDepthStencilTarget(DepthStencilHandle handle) override
Release the depth target with the given depthStencilHandle.
virtual RenderTargetHandle createRenderTarget(const RenderTargetViewDescription *renderTargetViews, const size_t numViews) override
Create a render target using the given view descriptions.
virtual void releaseTexture(TextureHandle textureHandle) override
Release the texture with the given textureHandle.
virtual TextureHandle loadTexture(const TextureDescription &desc, const TextureData *data) override
Load a texture from the given description.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Definition: LogManager.h:181
Contains all Cogs related functionality.
Definition: FieldSetter.h:23
Describes a single depth stencil view and which resources to use from the underlying texture.
TextureHandle texture
Texture handle.
uint16_t numLayers
Number of available layers to write to.
uint8_t levelIndex
Index of the mipmap level to render to.
uint16_t layerIndex
Index of the first layer (if array) to write depth to.
Describes the formats and sample count of a render target's attachments.
TextureFormat colorFormats[8]
Formats of the color targets, only the first numColorTargets entries are valid.
TextureFormat depthStencilFormat
Format of the depth stencil target, TextureFormat::Unknown if there is none.
uint8_t samples
Number of samples, 1 implies no multisampling.
uint8_t numColorTargets
Number of valid entries in colorFormats.
Describes a single render target view and which resources to use from the underlying texture.
uint16_t layerIndex
Index of the first layer (if array) to render to.
uint16_t numLayers
Number of available layers to render to.
TextureHandle texture
Texture handle.
uint8_t levelIndex
Index of the mipmap level to render to.
@ DepthBuffer
The texture can be used as a depth target and have depth buffer values written into.
Definition: Flags.h:122