| # Dawn partial Load Resolve Texture |
| |
| The `dawn-partial-load-resolve-texture` feature is an extension to `dawn-load-resolve-texture`, which in addition allows to specify a rect sub-region of texture, where load and resolve will take effect only. The feature can't be available unless `dawn-load-resolve-texture` is available. |
| |
| Additional functionalities: |
| - Adds `wgpu::RenderPassDescriptorExpandResolveRect` as chained struct for `wgpu::RenderPassDescriptor`. It defines a rect of {`x`, `y`, `width`, `height`} to indicate that expanding and resolving are only performed partially on the texels within this rect region of texture. The texels outside of the rect are not impacted. |
| |
| Example Usage: |
| ``` |
| // Create MSAA texture |
| wgpu::TextureDescriptor desc = ...; |
| desc.usage = wgpu::TextureUsage::RenderAttachment; |
| desc.sampleCount = 4; |
| |
| auto msaaTexture = device.CreateTexture(&desc); |
| |
| |
| // Create resolve texture with TextureBinding usage. |
| wgpu::TextureDescriptor desc = ...; |
| desc.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding; |
| |
| auto resolveTexture = device.CreateTexture(&desc); |
| |
| // Create a render pass which will discard the MSAA texture. |
| wgpu::RenderPassDescriptor renderPassDesc = ...; |
| renderPassDesc.colorAttachments[0].view = msaaTexture.CreateView(); |
| renderPassDesc.colorAttachments[0].resolveTarget |
| = resolveTexture.CreateView(); |
| renderPassDesc.colorAttachments[0].storeOp |
| = wgpu::StoreOp::Discard; |
| |
| auto renderPassEncoder = encoder.BeginRenderPass(&renderPassDesc); |
| renderPassEncoder.Draw(3); |
| renderPassEncoder.End(); |
| |
| // Create a render pipeline with wgpu::ColorTargetStateExpandResolveTextureDawn. |
| wgpu::ColorTargetStateExpandResolveTextureDawn pipelineExpandResolveTextureState; |
| pipelineExpandResolveTextureState.enabled = true; |
| |
| wgpu::RenderPipelineDescriptor pipelineDesc = ...; |
| pipelineDesc.multisample.count = 4; |
| |
| pipelineDesc->fragment->targets[0].nextInChain = &pipelineExpandResolveTextureState; |
| |
| auto pipeline = device.CreateRenderPipeline(&pipelineDesc); |
| |
| // Create another render pass with "ExpandResolveTexture" LoadOp. |
| // Even though we discard the previous content of the MSAA texture, |
| // the old pixels of the resolve texture will be reserved across |
| // render passes. |
| wgpu::RenderPassDescriptor renderPassDesc2 = ...; |
| renderPassDesc2.colorAttachments[0].view = msaaTexture.CreateView(); |
| renderPassDesc2.colorAttachments[0].resolveTarget |
| = resolveTexture.CreateView(); |
| renderPassDesc2.colorAttachments[0].loadOp |
| = wgpu::LoadOp::ExpandResolveTexture; |
| |
| // If there is no need to expand and resolve the whole texture, |
| // RenderPassDescriptorExpandResolveRect can be used to specify a |
| // subregion of texture to be updated only. |
| wgpu::RenderPassDescriptorExpandResolveRect rect{}; |
| rect.x = rect.y = 0; |
| rect.width = rect.height = 32; |
| renderPassDesc2.nextInChain = ▭ |
| |
| auto renderPassEncoder2 = encoder.BeginRenderPass(&renderPassDesc2); |
| renderPassEncoder2.SetPipeline(pipeline); |
| renderPassEncoder2.Draw(3); |
| renderPassEncoder2.End(); |
| |
| ``` |
| |
| Notes: |
| - In case that the target size of a render pass is very large, the cost of using `wgpu::LoadOp::ExpandResolveTexture` can be rather expensive, as it always assumes full-size expand and resolve. More commonly in reality, each frame we only need to re-draw a small damage region, of which UI frameworks usually have the knowledge, instead of the full window, or webpage. This feature aims to eliminate the waste by doing partial expand and resolve with the hint of `wgpu::RenderPassDescriptorExpandResolveRect`, the actual damage region. |
| - The feature currently is only available on dawn d3d11 backend. Internally, both expand and resolve are implemented with a dedicated `wgpu::RenderPipeline`. `wgpu::RenderPassEncoder::APISetScissorRect` is used to set the scissor rect to `wgpu::RenderPassDescriptorExpandResolveRect`, when using the pipeline. The major difference is that expand lives in the original render pass, while resolve requires a separate one. |