mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-21 10:49:14 +00:00
Support sampling depth and stencil of combined d/s formats
This CL adds sampling of depth-only and stencil-only texture views on all backends. However, Metal on macOS <= 10.11 will need a workaround to use separate depth/stencil textures for each aspect since it is impossible to sample the stencil aspect of a combined depth/stencil texture. Also fixes sampling of depth24plus on D3D12 which had an incomplete check for determining if a TYPELESS format is necessary. Bug: dawn:439, dawn:553 Change-Id: Id4991c565f822add200054296714e2dcd330119a Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/30725 Commit-Queue: Austin Eng <enga@chromium.org> Reviewed-by: Stephen White <senorblanco@chromium.org>
This commit is contained in:
committed by
Commit Bot service account
parent
9d6265bc07
commit
a0f1725c4f
@@ -150,7 +150,7 @@ namespace dawn_native {
|
||||
};
|
||||
|
||||
auto AddDepthStencilFormat = [&AddFormat](wgpu::TextureFormat format, Aspect aspects,
|
||||
uint32_t byteSize, bool isDepthSampleable) {
|
||||
uint32_t byteSize) {
|
||||
Format internalFormat;
|
||||
internalFormat.format = format;
|
||||
internalFormat.isRenderable = true;
|
||||
@@ -162,12 +162,8 @@ namespace dawn_native {
|
||||
internalFormat.firstAspect.block.width = 1;
|
||||
internalFormat.firstAspect.block.height = 1;
|
||||
internalFormat.firstAspect.baseType = wgpu::TextureComponentType::Float;
|
||||
if (isDepthSampleable) {
|
||||
internalFormat.firstAspect.supportedComponentTypes =
|
||||
ComponentTypeBit::Float | ComponentTypeBit::DepthComparison;
|
||||
} else {
|
||||
internalFormat.firstAspect.supportedComponentTypes = ComponentTypeBit::None;
|
||||
}
|
||||
internalFormat.firstAspect.supportedComponentTypes =
|
||||
ComponentTypeBit::Float | ComponentTypeBit::DepthComparison;
|
||||
AddFormat(internalFormat);
|
||||
};
|
||||
|
||||
@@ -238,12 +234,12 @@ namespace dawn_native {
|
||||
AddColorFormat(wgpu::TextureFormat::RGBA32Float, true, true, 16, Type::Float);
|
||||
|
||||
// Depth-stencil formats
|
||||
AddDepthStencilFormat(wgpu::TextureFormat::Depth32Float, Aspect::Depth, 4, true);
|
||||
AddDepthStencilFormat(wgpu::TextureFormat::Depth24Plus, Aspect::Depth, 4, false);
|
||||
AddDepthStencilFormat(wgpu::TextureFormat::Depth32Float, Aspect::Depth, 4);
|
||||
AddDepthStencilFormat(wgpu::TextureFormat::Depth24Plus, Aspect::Depth, 4);
|
||||
// TODO(cwallez@chromium.org): It isn't clear if this format should be copyable
|
||||
// because its size isn't well defined, is it 4, 5 or 8?
|
||||
AddDepthStencilFormat(wgpu::TextureFormat::Depth24PlusStencil8,
|
||||
Aspect::Depth | Aspect::Stencil, 4, false);
|
||||
Aspect::Depth | Aspect::Stencil, 4);
|
||||
|
||||
// BC compressed formats
|
||||
bool isBCFormatSupported = device->IsExtensionEnabled(Extension::TextureCompressionBC);
|
||||
|
||||
@@ -171,7 +171,7 @@ namespace dawn_native { namespace d3d12 {
|
||||
return DXGI_FORMAT_R32_TYPELESS;
|
||||
|
||||
case wgpu::TextureFormat::Depth24PlusStencil8:
|
||||
return DXGI_FORMAT_X32_TYPELESS_G8X24_UINT;
|
||||
return DXGI_FORMAT_R32G8X24_TYPELESS;
|
||||
|
||||
case wgpu::TextureFormat::BC1RGBAUnorm:
|
||||
case wgpu::TextureFormat::BC1RGBAUnormSrgb:
|
||||
@@ -451,8 +451,8 @@ namespace dawn_native { namespace d3d12 {
|
||||
|
||||
// This will need to be much more nuanced when WebGPU has
|
||||
// texture view compatibility rules.
|
||||
bool needsTypelessFormat = GetFormat().format == wgpu::TextureFormat::Depth32Float &&
|
||||
(GetUsage() & wgpu::TextureUsage::Sampled) != 0;
|
||||
const bool needsTypelessFormat =
|
||||
GetFormat().HasDepthOrStencil() && (GetUsage() & wgpu::TextureUsage::Sampled) != 0;
|
||||
|
||||
DXGI_FORMAT dxgiFormat = needsTypelessFormat
|
||||
? D3D12TypelessTextureFormat(GetFormat().format)
|
||||
@@ -1027,13 +1027,50 @@ namespace dawn_native { namespace d3d12 {
|
||||
TextureView::TextureView(TextureBase* texture, const TextureViewDescriptor* descriptor)
|
||||
: TextureViewBase(texture, descriptor) {
|
||||
mSrvDesc.Format = D3D12TextureFormat(descriptor->format);
|
||||
if (descriptor->format == wgpu::TextureFormat::Depth32Float) {
|
||||
// TODO(enga): This will need to be much more nuanced when WebGPU has
|
||||
// texture view compatibility rules.
|
||||
mSrvDesc.Format = DXGI_FORMAT_R32_FLOAT;
|
||||
}
|
||||
mSrvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||
|
||||
// TODO(enga): This will need to be much more nuanced when WebGPU has
|
||||
// texture view compatibility rules.
|
||||
UINT planeSlice = 0;
|
||||
if (GetFormat().HasDepthOrStencil()) {
|
||||
// Configure the SRV descriptor to reinterpret the texture allocated as
|
||||
// TYPELESS as a single-plane shader-accessible view.
|
||||
switch (descriptor->format) {
|
||||
case wgpu::TextureFormat::Depth32Float:
|
||||
case wgpu::TextureFormat::Depth24Plus:
|
||||
mSrvDesc.Format = DXGI_FORMAT_R32_FLOAT;
|
||||
break;
|
||||
case wgpu::TextureFormat::Depth24PlusStencil8:
|
||||
switch (descriptor->aspect) {
|
||||
case wgpu::TextureAspect::DepthOnly:
|
||||
planeSlice = 0;
|
||||
mSrvDesc.Format = DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
|
||||
break;
|
||||
case wgpu::TextureAspect::StencilOnly:
|
||||
planeSlice = 1;
|
||||
mSrvDesc.Format = DXGI_FORMAT_X32_TYPELESS_G8X24_UINT;
|
||||
// Stencil is accessed using the .g component in the shader.
|
||||
// Map it to the zeroth component to match other APIs.
|
||||
mSrvDesc.Shader4ComponentMapping =
|
||||
D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(
|
||||
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1,
|
||||
D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0,
|
||||
D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0,
|
||||
D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_1);
|
||||
break;
|
||||
case wgpu::TextureAspect::All:
|
||||
// A single aspect is not selected. The texture view must not be
|
||||
// sampled.
|
||||
mSrvDesc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Currently we always use D3D12_TEX2D_ARRAY_SRV because we cannot specify base array layer
|
||||
// and layer count in D3D12_TEX2D_SRV. For 2D texture views, we treat them as 1-layer 2D
|
||||
// array textures.
|
||||
@@ -1065,7 +1102,7 @@ namespace dawn_native { namespace d3d12 {
|
||||
mSrvDesc.Texture2DArray.FirstArraySlice = descriptor->baseArrayLayer;
|
||||
mSrvDesc.Texture2DArray.MipLevels = descriptor->mipLevelCount;
|
||||
mSrvDesc.Texture2DArray.MostDetailedMip = descriptor->baseMipLevel;
|
||||
mSrvDesc.Texture2DArray.PlaneSlice = 0;
|
||||
mSrvDesc.Texture2DArray.PlaneSlice = planeSlice;
|
||||
mSrvDesc.Texture2DArray.ResourceMinLODClamp = 0;
|
||||
break;
|
||||
case wgpu::TextureViewDimension::Cube:
|
||||
@@ -1093,6 +1130,7 @@ namespace dawn_native { namespace d3d12 {
|
||||
}
|
||||
|
||||
const D3D12_SHADER_RESOURCE_VIEW_DESC& TextureView::GetSRVDescriptor() const {
|
||||
ASSERT(mSrvDesc.Format != DXGI_FORMAT_UNKNOWN);
|
||||
return mSrvDesc;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace dawn_native { namespace metal {
|
||||
return usage & kUsageNeedsTextureView;
|
||||
}
|
||||
|
||||
MTLTextureUsage MetalTextureUsage(wgpu::TextureUsage usage) {
|
||||
MTLTextureUsage MetalTextureUsage(const Format& format, wgpu::TextureUsage usage) {
|
||||
MTLTextureUsage result = MTLTextureUsageUnknown; // This is 0
|
||||
|
||||
if (usage & (wgpu::TextureUsage::Storage)) {
|
||||
@@ -43,6 +43,14 @@ namespace dawn_native { namespace metal {
|
||||
|
||||
if (usage & (wgpu::TextureUsage::Sampled)) {
|
||||
result |= MTLTextureUsageShaderRead;
|
||||
|
||||
// For sampling stencil aspect of combined depth/stencil. See TextureView
|
||||
// constructor.
|
||||
if (@available(macOS 10.12, iOS 10.0, *)) {
|
||||
if (IsSubset(Aspect::Depth | Aspect::Stencil, format.aspects)) {
|
||||
result |= MTLTextureUsagePixelFormatView;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (usage & (wgpu::TextureUsage::RenderAttachment)) {
|
||||
@@ -85,6 +93,11 @@ namespace dawn_native { namespace metal {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (IsSubset(Aspect::Depth | Aspect::Stencil, texture->GetFormat().aspects) &&
|
||||
textureViewDescriptor->aspect == wgpu::TextureAspect::StencilOnly) {
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (textureViewDescriptor->dimension) {
|
||||
case wgpu::TextureViewDimension::Cube:
|
||||
case wgpu::TextureViewDimension::CubeArray:
|
||||
@@ -285,7 +298,8 @@ namespace dawn_native { namespace metal {
|
||||
return {};
|
||||
}
|
||||
|
||||
MTLTextureDescriptor* CreateMetalTextureDescriptor(const TextureDescriptor* descriptor) {
|
||||
MTLTextureDescriptor* CreateMetalTextureDescriptor(DeviceBase* device,
|
||||
const TextureDescriptor* descriptor) {
|
||||
MTLTextureDescriptor* mtlDesc = [MTLTextureDescriptor new];
|
||||
|
||||
mtlDesc.width = descriptor->size.width;
|
||||
@@ -293,7 +307,8 @@ namespace dawn_native { namespace metal {
|
||||
mtlDesc.sampleCount = descriptor->sampleCount;
|
||||
// TODO: add MTLTextureUsagePixelFormatView when needed when we support format
|
||||
// reinterpretation.
|
||||
mtlDesc.usage = MetalTextureUsage(descriptor->usage);
|
||||
mtlDesc.usage = MetalTextureUsage(device->GetValidInternalFormat(descriptor->format),
|
||||
descriptor->usage);
|
||||
mtlDesc.pixelFormat = MetalPixelFormat(descriptor->format);
|
||||
mtlDesc.mipmapLevelCount = descriptor->mipLevelCount;
|
||||
mtlDesc.storageMode = MTLStorageModePrivate;
|
||||
@@ -328,7 +343,7 @@ namespace dawn_native { namespace metal {
|
||||
|
||||
Texture::Texture(Device* device, const TextureDescriptor* descriptor)
|
||||
: TextureBase(device, descriptor, TextureState::OwnedInternal) {
|
||||
MTLTextureDescriptor* mtlDesc = CreateMetalTextureDescriptor(descriptor);
|
||||
MTLTextureDescriptor* mtlDesc = CreateMetalTextureDescriptor(device, descriptor);
|
||||
mMtlTexture = [device->GetMTLDevice() newTextureWithDescriptor:mtlDesc];
|
||||
[mtlDesc release];
|
||||
|
||||
@@ -351,7 +366,7 @@ namespace dawn_native { namespace metal {
|
||||
reinterpret_cast<const TextureDescriptor*>(descriptor->cTextureDescriptor),
|
||||
TextureState::OwnedInternal) {
|
||||
MTLTextureDescriptor* mtlDesc = CreateMetalTextureDescriptor(
|
||||
reinterpret_cast<const TextureDescriptor*>(descriptor->cTextureDescriptor));
|
||||
device, reinterpret_cast<const TextureDescriptor*>(descriptor->cTextureDescriptor));
|
||||
mtlDesc.storageMode = kIOSurfaceStorageMode;
|
||||
mMtlTexture = [device->GetMTLDevice() newTextureWithDescriptor:mtlDesc
|
||||
iosurface:ioSurface
|
||||
@@ -581,6 +596,20 @@ namespace dawn_native { namespace metal {
|
||||
mMtlTextureView = [mtlTexture retain];
|
||||
} else {
|
||||
MTLPixelFormat format = MetalPixelFormat(descriptor->format);
|
||||
if (descriptor->aspect == wgpu::TextureAspect::StencilOnly) {
|
||||
if (@available(macOS 10.12, iOS 10.0, *)) {
|
||||
ASSERT(format == MTLPixelFormatDepth32Float_Stencil8);
|
||||
format = MTLPixelFormatX32_Stencil8;
|
||||
} else {
|
||||
// TODO(enga): Add a workaround to back combined depth/stencil textures
|
||||
// with Sampled usage using two separate textures.
|
||||
// Or, consider always using the workaround for D32S8.
|
||||
GetDevice()->ConsumedError(
|
||||
DAWN_DEVICE_LOST_ERROR("Cannot create stencil-only texture view of "
|
||||
"combined depth/stencil format."));
|
||||
}
|
||||
}
|
||||
|
||||
MTLTextureType textureViewType =
|
||||
MetalTextureViewType(descriptor->dimension, texture->GetSampleCount());
|
||||
auto mipLevelRange = NSMakeRange(descriptor->baseMipLevel, descriptor->mipLevelCount);
|
||||
|
||||
@@ -306,6 +306,24 @@ namespace dawn_native { namespace opengl {
|
||||
for (auto unit : mPipeline->GetTextureUnitsForTextureView(viewIndex)) {
|
||||
gl.ActiveTexture(GL_TEXTURE0 + unit);
|
||||
gl.BindTexture(target, handle);
|
||||
if (ToBackend(view->GetTexture())->GetGLFormat().format ==
|
||||
GL_DEPTH_STENCIL) {
|
||||
Aspect aspect = view->GetAspects();
|
||||
ASSERT(HasOneBit(aspect));
|
||||
switch (aspect) {
|
||||
case Aspect::None:
|
||||
case Aspect::Color:
|
||||
UNREACHABLE();
|
||||
case Aspect::Depth:
|
||||
gl.TexParameteri(target, GL_DEPTH_STENCIL_TEXTURE_MODE,
|
||||
GL_DEPTH_COMPONENT);
|
||||
break;
|
||||
case Aspect::Stencil:
|
||||
gl.TexParameteri(target, GL_DEPTH_STENCIL_TEXTURE_MODE,
|
||||
GL_STENCIL_INDEX);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -96,6 +96,16 @@ namespace dawn_native { namespace opengl {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ToBackend(texture)->GetGLFormat().format == GL_DEPTH_STENCIL &&
|
||||
(texture->GetUsage() & wgpu::TextureUsage::Sampled) != 0 &&
|
||||
textureViewDescriptor->aspect == wgpu::TextureAspect::StencilOnly) {
|
||||
// We need a separate view for one of the depth or stencil planes
|
||||
// because each glTextureView needs it's own handle to set
|
||||
// GL_DEPTH_STENCIL_TEXTURE_MODE. Choose the stencil aspect for the
|
||||
// extra handle since it is likely sampled less often.
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (textureViewDescriptor->dimension) {
|
||||
case wgpu::TextureViewDimension::Cube:
|
||||
case wgpu::TextureViewDimension::CubeArray:
|
||||
|
||||
Reference in New Issue
Block a user