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:
wgpu::RenderPassDescriptorResolveRect as chained struct for wgpu::RenderPassDescriptor. It defines an expanding rect of {colorOffsetX, colorOffsetY, width, height} and a resolving rect {resolveOffsetX, resolveOffsetY, 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 1, ExpandResolveTexture and RenderPassDescriptorResolveRect:
When the load operation is set to wgpu::LoadOp::ExpandResolveTexture:
// 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,
// RenderPassDescriptorResolveRect can be used to specify a
// subregion of texture to be updated only.
wgpu::RenderPassDescriptorResolveRect rect{};
rect.colorOffsetX = rect.colorOffsetY = 1;
rect.resolveOffsetX = rect.resolveOffsetY = 1;
rect.width = rect.height = 32;
renderPassDesc2.nextInChain = ▭
auto renderPassEncoder2 = encoder.BeginRenderPass(&renderPassDesc2);
renderPassEncoder2.SetPipeline(pipeline);
renderPassEncoder2.Draw(3);
renderPassEncoder2.End();
Example Usage 2, Clear and RenderPassDescriptorResolveRect:
Similar to the above example, but using wgpu::LoadOp::Clear:
// Create another render pass with "Clear" LoadOp.
wgpu::RenderPassDescriptor renderPassDesc2 = ...;
renderPassDesc2.colorAttachments[0].view = msaaTexture.CreateView();
renderPassDesc2.colorAttachments[0].resolveTarget
= resolveTexture.CreateView();
renderPassDesc2.colorAttachments[0].loadOp = wgpu::LoadOp::Clear;
renderPassDesc2.colorAttachments[0].clearValue = clearValue;
wgpu::RenderPassDescriptorResolveRect rect{};
rect.colorOffsetX = rect.colorOffsetY = 1;
rect.resolveOffsetX = rect.resolveOffsetY = 1;
rect.width = rect.height = 32;
renderPassDesc2.nextInChain = ▭
Example Usage 3, Load and RenderPassDescriptorResolveRect:
Similar to the first example, but using wgpu::LoadOp::Load:
// Create another render pass with "Load" LoadOp.
wgpu::RenderPassDescriptor renderPassDesc2 = ...;
renderPassDesc2.colorAttachments[0].view = msaaTexture.CreateView();
renderPassDesc2.colorAttachments[0].resolveTarget
= resolveTexture.CreateView();
renderPassDesc2.colorAttachments[0].loadOp = wgpu::LoadOp::Load;
wgpu::RenderPassDescriptorResolveRect rect{};
rect.colorOffsetX = rect.colorOffsetY = 1;
rect.resolveOffsetX = rect.resolveOffsetY = 1;
rect.width = rect.height = 32;
renderPassDesc2.nextInChain = ▭
Notes:
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::RenderPassDescriptorResolveRect, the actual damage region.wgpu::RenderPipeline. wgpu::RenderPassEncoder::APISetScissorRect is used to set the scissor rect to wgpu::RenderPassDescriptorResolveRect, when using the pipeline. The major difference is that expand lives in the original render pass, while resolve requires a separate one.