mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-20 10:25:28 +00:00
Implement initialization of multisampled textures
Metal needs RenderTarget usage to be added to the texture allocation so the clear can be done using a render pass. Already working for GL which does not have usage flags on creation. Also working on Vulkan which does not need a render pass. We use vkCmdClearColorImage. D3D12 also needs a render pass to clear multisampled textures, but it already requires multisampled textures to be created with RenderTarget flags. To test the behavior, NonzeroTextureCreation tests are expanded, and the ExpectSampledDepthData helper is factored into a more general ExpectSampledFloatData helper. Fixes: dawn:794 Change-Id: If0f9f26f3c58b4292c85265aa7ff330e9931ddae Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/55604 Commit-Queue: Austin Eng <enga@chromium.org> Reviewed-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
@@ -471,6 +471,9 @@ namespace dawn_native { namespace d3d12 {
|
||||
mDxgiKeyedMutex = std::move(dxgiKeyedMutex);
|
||||
mSwapChainTexture = isSwapChainTexture;
|
||||
|
||||
D3D12_RESOURCE_DESC desc = d3d12Texture->GetDesc();
|
||||
mD3D12ResourceFlags = desc.Flags;
|
||||
|
||||
AllocationInfo info;
|
||||
info.mMethod = AllocationMethod::kExternal;
|
||||
// When creating the ResourceHeapAllocation, the resource heap is set to nullptr because the
|
||||
@@ -507,6 +510,7 @@ namespace dawn_native { namespace d3d12 {
|
||||
resourceDescriptor.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
|
||||
resourceDescriptor.Flags =
|
||||
D3D12ResourceFlags(GetUsage(), GetFormat(), IsMultisampledTexture());
|
||||
mD3D12ResourceFlags = resourceDescriptor.Flags;
|
||||
|
||||
DAWN_TRY_ASSIGN(mResourceAllocation,
|
||||
ToBackend(GetDevice())
|
||||
@@ -879,82 +883,80 @@ namespace dawn_native { namespace d3d12 {
|
||||
uint8_t clearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0 : 1;
|
||||
float fClearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0.f : 1.f;
|
||||
|
||||
if ((GetUsage() & wgpu::TextureUsage::RenderAttachment) != 0) {
|
||||
if (GetFormat().HasDepthOrStencil()) {
|
||||
TrackUsageAndTransitionNow(commandContext, D3D12_RESOURCE_STATE_DEPTH_WRITE, range);
|
||||
if ((mD3D12ResourceFlags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL) != 0) {
|
||||
TrackUsageAndTransitionNow(commandContext, D3D12_RESOURCE_STATE_DEPTH_WRITE, range);
|
||||
|
||||
for (uint32_t level = range.baseMipLevel;
|
||||
level < range.baseMipLevel + range.levelCount; ++level) {
|
||||
for (uint32_t layer = range.baseArrayLayer;
|
||||
layer < range.baseArrayLayer + range.layerCount; ++layer) {
|
||||
// Iterate the aspects individually to determine which clear flags to use.
|
||||
D3D12_CLEAR_FLAGS clearFlags = {};
|
||||
for (Aspect aspect : IterateEnumMask(range.aspects)) {
|
||||
if (clearValue == TextureBase::ClearValue::Zero &&
|
||||
IsSubresourceContentInitialized(
|
||||
SubresourceRange::SingleMipAndLayer(level, layer, aspect))) {
|
||||
// Skip lazy clears if already initialized.
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (aspect) {
|
||||
case Aspect::Depth:
|
||||
clearFlags |= D3D12_CLEAR_FLAG_DEPTH;
|
||||
break;
|
||||
case Aspect::Stencil:
|
||||
clearFlags |= D3D12_CLEAR_FLAG_STENCIL;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
if (clearFlags == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CPUDescriptorHeapAllocation dsvHandle;
|
||||
DAWN_TRY_ASSIGN(dsvHandle, device->GetDepthStencilViewAllocator()
|
||||
->AllocateTransientCPUDescriptors());
|
||||
const D3D12_CPU_DESCRIPTOR_HANDLE baseDescriptor =
|
||||
dsvHandle.GetBaseDescriptor();
|
||||
D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = GetDSVDescriptor(level, layer, 1);
|
||||
device->GetD3D12Device()->CreateDepthStencilView(GetD3D12Resource(),
|
||||
&dsvDesc, baseDescriptor);
|
||||
|
||||
commandList->ClearDepthStencilView(baseDescriptor, clearFlags, fClearColor,
|
||||
clearColor, 0, nullptr);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
TrackUsageAndTransitionNow(commandContext, D3D12_RESOURCE_STATE_RENDER_TARGET,
|
||||
range);
|
||||
|
||||
const float clearColorRGBA[4] = {fClearColor, fClearColor, fClearColor,
|
||||
fClearColor};
|
||||
|
||||
ASSERT(range.aspects == Aspect::Color);
|
||||
for (uint32_t level = range.baseMipLevel;
|
||||
level < range.baseMipLevel + range.levelCount; ++level) {
|
||||
for (uint32_t layer = range.baseArrayLayer;
|
||||
layer < range.baseArrayLayer + range.layerCount; ++layer) {
|
||||
for (uint32_t level = range.baseMipLevel; level < range.baseMipLevel + range.levelCount;
|
||||
++level) {
|
||||
for (uint32_t layer = range.baseArrayLayer;
|
||||
layer < range.baseArrayLayer + range.layerCount; ++layer) {
|
||||
// Iterate the aspects individually to determine which clear flags to use.
|
||||
D3D12_CLEAR_FLAGS clearFlags = {};
|
||||
for (Aspect aspect : IterateEnumMask(range.aspects)) {
|
||||
if (clearValue == TextureBase::ClearValue::Zero &&
|
||||
IsSubresourceContentInitialized(
|
||||
SubresourceRange::SingleMipAndLayer(level, layer, Aspect::Color))) {
|
||||
SubresourceRange::SingleMipAndLayer(level, layer, aspect))) {
|
||||
// Skip lazy clears if already initialized.
|
||||
continue;
|
||||
}
|
||||
|
||||
CPUDescriptorHeapAllocation rtvHeap;
|
||||
DAWN_TRY_ASSIGN(rtvHeap, device->GetRenderTargetViewAllocator()
|
||||
->AllocateTransientCPUDescriptors());
|
||||
const D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = rtvHeap.GetBaseDescriptor();
|
||||
|
||||
D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = GetRTVDescriptor(level, layer, 1);
|
||||
device->GetD3D12Device()->CreateRenderTargetView(GetD3D12Resource(),
|
||||
&rtvDesc, rtvHandle);
|
||||
commandList->ClearRenderTargetView(rtvHandle, clearColorRGBA, 0, nullptr);
|
||||
switch (aspect) {
|
||||
case Aspect::Depth:
|
||||
clearFlags |= D3D12_CLEAR_FLAG_DEPTH;
|
||||
break;
|
||||
case Aspect::Stencil:
|
||||
clearFlags |= D3D12_CLEAR_FLAG_STENCIL;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
if (clearFlags == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CPUDescriptorHeapAllocation dsvHandle;
|
||||
DAWN_TRY_ASSIGN(
|
||||
dsvHandle,
|
||||
device->GetDepthStencilViewAllocator()->AllocateTransientCPUDescriptors());
|
||||
const D3D12_CPU_DESCRIPTOR_HANDLE baseDescriptor =
|
||||
dsvHandle.GetBaseDescriptor();
|
||||
D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = GetDSVDescriptor(level, layer, 1);
|
||||
device->GetD3D12Device()->CreateDepthStencilView(GetD3D12Resource(), &dsvDesc,
|
||||
baseDescriptor);
|
||||
|
||||
commandList->ClearDepthStencilView(baseDescriptor, clearFlags, fClearColor,
|
||||
clearColor, 0, nullptr);
|
||||
}
|
||||
}
|
||||
} else if ((mD3D12ResourceFlags & D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET) != 0) {
|
||||
TrackUsageAndTransitionNow(commandContext, D3D12_RESOURCE_STATE_RENDER_TARGET, range);
|
||||
|
||||
const float clearColorRGBA[4] = {fClearColor, fClearColor, fClearColor, fClearColor};
|
||||
|
||||
ASSERT(range.aspects == Aspect::Color);
|
||||
for (uint32_t level = range.baseMipLevel; level < range.baseMipLevel + range.levelCount;
|
||||
++level) {
|
||||
for (uint32_t layer = range.baseArrayLayer;
|
||||
layer < range.baseArrayLayer + range.layerCount; ++layer) {
|
||||
if (clearValue == TextureBase::ClearValue::Zero &&
|
||||
IsSubresourceContentInitialized(
|
||||
SubresourceRange::SingleMipAndLayer(level, layer, Aspect::Color))) {
|
||||
// Skip lazy clears if already initialized.
|
||||
continue;
|
||||
}
|
||||
|
||||
CPUDescriptorHeapAllocation rtvHeap;
|
||||
DAWN_TRY_ASSIGN(
|
||||
rtvHeap,
|
||||
device->GetRenderTargetViewAllocator()->AllocateTransientCPUDescriptors());
|
||||
const D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = rtvHeap.GetBaseDescriptor();
|
||||
|
||||
D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = GetRTVDescriptor(level, layer, 1);
|
||||
device->GetD3D12Device()->CreateRenderTargetView(GetD3D12Resource(), &rtvDesc,
|
||||
rtvHandle);
|
||||
commandList->ClearRenderTargetView(rtvHandle, clearColorRGBA, 0, nullptr);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -123,6 +123,7 @@ namespace dawn_native { namespace d3d12 {
|
||||
|
||||
ResourceHeapAllocation mResourceAllocation;
|
||||
bool mSwapChainTexture = false;
|
||||
D3D12_RESOURCE_FLAGS mD3D12ResourceFlags;
|
||||
|
||||
ExternalMutexSerial mAcquireMutexKey = ExternalMutexSerial(0);
|
||||
ExternalMutexSerial mReleaseMutexKey = ExternalMutexSerial(0);
|
||||
|
||||
@@ -63,6 +63,7 @@ namespace dawn_native { namespace metal {
|
||||
TextureBase::ClearValue clearValue);
|
||||
|
||||
NSPRef<id<MTLTexture>> mMtlTexture;
|
||||
MTLTextureUsage mMtlUsage;
|
||||
};
|
||||
|
||||
class TextureView final : public TextureViewBase {
|
||||
|
||||
@@ -34,7 +34,9 @@ namespace dawn_native { namespace metal {
|
||||
return usage & kUsageNeedsTextureView;
|
||||
}
|
||||
|
||||
MTLTextureUsage MetalTextureUsage(const Format& format, wgpu::TextureUsage usage) {
|
||||
MTLTextureUsage MetalTextureUsage(const Format& format,
|
||||
wgpu::TextureUsage usage,
|
||||
uint32_t sampleCount) {
|
||||
MTLTextureUsage result = MTLTextureUsageUnknown; // This is 0
|
||||
|
||||
if (usage & (wgpu::TextureUsage::Storage)) {
|
||||
@@ -53,7 +55,8 @@ namespace dawn_native { namespace metal {
|
||||
}
|
||||
}
|
||||
|
||||
if (usage & (wgpu::TextureUsage::RenderAttachment)) {
|
||||
// MTLTextureUsageRenderTarget is needed to clear multisample textures.
|
||||
if (usage & (wgpu::TextureUsage::RenderAttachment) || sampleCount > 1) {
|
||||
result |= MTLTextureUsageRenderTarget;
|
||||
}
|
||||
|
||||
@@ -310,7 +313,7 @@ namespace dawn_native { namespace metal {
|
||||
// TODO: add MTLTextureUsagePixelFormatView when needed when we support format
|
||||
// reinterpretation.
|
||||
mtlDesc.usage = MetalTextureUsage(device->GetValidInternalFormat(descriptor->format),
|
||||
descriptor->usage);
|
||||
descriptor->usage, descriptor->sampleCount);
|
||||
mtlDesc.pixelFormat = MetalPixelFormat(descriptor->format);
|
||||
mtlDesc.mipmapLevelCount = descriptor->mipLevelCount;
|
||||
mtlDesc.storageMode = MTLStorageModePrivate;
|
||||
@@ -357,6 +360,7 @@ namespace dawn_native { namespace metal {
|
||||
NSRef<MTLTextureDescriptor> mtlDesc = CreateMetalTextureDescriptor(device, descriptor);
|
||||
mMtlTexture =
|
||||
AcquireNSPRef([device->GetMTLDevice() newTextureWithDescriptor:mtlDesc.Get()]);
|
||||
mMtlUsage = [*mtlDesc usage];
|
||||
|
||||
if (device->IsToggleEnabled(Toggle::NonzeroClearResourcesOnCreationForTesting)) {
|
||||
device->ConsumedError(ClearTexture(device->GetPendingCommandContext(),
|
||||
@@ -370,6 +374,8 @@ namespace dawn_native { namespace metal {
|
||||
NSPRef<id<MTLTexture>> mtlTexture)
|
||||
: TextureBase(device, descriptor, TextureState::OwnedInternal),
|
||||
mMtlTexture(std::move(mtlTexture)) {
|
||||
NSRef<MTLTextureDescriptor> mtlDesc = CreateMetalTextureDescriptor(device, descriptor);
|
||||
mMtlUsage = [*mtlDesc usage];
|
||||
}
|
||||
|
||||
Texture::Texture(Device* device,
|
||||
@@ -386,6 +392,7 @@ namespace dawn_native { namespace metal {
|
||||
mMtlTexture = AcquireNSPRef([device->GetMTLDevice() newTextureWithDescriptor:mtlDesc.Get()
|
||||
iosurface:ioSurface
|
||||
plane:plane]);
|
||||
mMtlUsage = [*mtlDesc usage];
|
||||
|
||||
SetIsSubresourceContentInitialized(descriptor->isInitialized, GetAllSubresources());
|
||||
}
|
||||
@@ -410,7 +417,7 @@ namespace dawn_native { namespace metal {
|
||||
const uint8_t clearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0 : 1;
|
||||
const double dClearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0.0 : 1.0;
|
||||
|
||||
if ((GetUsage() & wgpu::TextureUsage::RenderAttachment) != 0) {
|
||||
if ((mMtlUsage & MTLTextureUsageRenderTarget) != 0) {
|
||||
ASSERT(GetFormat().isRenderable);
|
||||
|
||||
// End the blit encoder if it is open.
|
||||
|
||||
Reference in New Issue
Block a user