blob: 8a5ec77eeb3ae11dd4bd7f80107691494069658a [file] [log] [blame] [edit]
// Copyright 2023 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "dawn/native/d3d12/SharedTextureMemoryD3D12.h"
#include <utility>
#include "dawn/native/ChainUtils.h"
#include "dawn/native/d3d/D3DError.h"
#include "dawn/native/d3d/KeyedMutex.h"
#include "dawn/native/d3d/UtilsD3D.h"
#include "dawn/native/d3d12/DeviceD3D12.h"
#include "dawn/native/d3d12/TextureD3D12.h"
namespace dawn::native::d3d12 {
// static
ResultOrError<Ref<SharedTextureMemory>> SharedTextureMemory::Create(
Device* device,
StringView label,
const SharedTextureMemoryDXGISharedHandleDescriptor* descriptor) {
DAWN_INVALID_IF(descriptor->handle == nullptr, "shared HANDLE is missing.");
ComPtr<ID3D12Resource> d3d12Resource;
Ref<d3d::KeyedMutex> keyedMutex;
DAWN_TRY(device->ImportSharedHandleResource(descriptor->handle, descriptor->useKeyedMutex,
d3d12Resource, keyedMutex));
D3D12_RESOURCE_DESC desc = d3d12Resource->GetDesc();
DAWN_INVALID_IF(desc.Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE2D,
"Resource dimension (%d) was not Texture2D", desc.Dimension);
DAWN_INVALID_IF(desc.DepthOrArraySize != 1, "Resource DepthOrArraySize (%d) was not 1",
desc.DepthOrArraySize);
DAWN_INVALID_IF(desc.MipLevels != 1, "Resource MipLevels (%d) was not 1", desc.MipLevels);
DAWN_INVALID_IF(desc.SampleDesc.Count != 1, "Resource SampleDesc.Count (%d) was not 1",
desc.SampleDesc.Count);
const CombinedLimits& limits = device->GetLimits();
DAWN_INVALID_IF(desc.Width > limits.v1.maxTextureDimension2D,
"Resource Width (%u) exceeds maxTextureDimension2D (%u).", desc.Width,
limits.v1.maxTextureDimension2D);
DAWN_INVALID_IF(desc.Height > limits.v1.maxTextureDimension2D,
"Resource Height (%u) exceeds maxTextureDimension2D (%u).", desc.Height,
limits.v1.maxTextureDimension2D);
DAWN_INVALID_IF(!(desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS),
"Resource did not have D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS flag");
SharedTextureMemoryProperties properties;
properties.size = {static_cast<uint32_t>(desc.Width), static_cast<uint32_t>(desc.Height), 1};
DAWN_TRY_ASSIGN(properties.format, d3d::FromUncompressedColorDXGITextureFormat(desc.Format));
// The usages that the underlying D3D12 texture supports are partially
// dependent on its creation flags. Note that the SharedTextureMemory
// frontend takes care of stripping out any usages that are not supported
// for `format`.
wgpu::TextureUsage storageBindingUsage =
(desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS)
? wgpu::TextureUsage::StorageBinding
: wgpu::TextureUsage::None;
wgpu::TextureUsage renderAttachmentUsage =
(desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET)
? wgpu::TextureUsage::RenderAttachment
: wgpu::TextureUsage::None;
properties.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst |
wgpu::TextureUsage::TextureBinding | storageBindingUsage |
renderAttachmentUsage;
auto result = AcquireRef(new SharedTextureMemory(
device, label, properties, std::move(d3d12Resource), std::move(keyedMutex)));
result->Initialize();
return result;
}
SharedTextureMemory::SharedTextureMemory(Device* device,
StringView label,
SharedTextureMemoryProperties properties,
ComPtr<ID3D12Resource> resource,
Ref<d3d::KeyedMutex> keyedMutex)
: d3d::SharedTextureMemory(device, label, properties),
mResource(std::move(resource)),
mKeyedMutex(std::move(keyedMutex)) {}
void SharedTextureMemory::DestroyImpl() {
ToBackend(GetDevice())->ReferenceUntilUnused(std::move(mResource));
mKeyedMutex = nullptr;
}
ID3D12Resource* SharedTextureMemory::GetD3DResource() const {
return mResource.Get();
}
d3d::KeyedMutex* SharedTextureMemory::GetKeyedMutex() const {
return mKeyedMutex.Get();
}
ResultOrError<Ref<TextureBase>> SharedTextureMemory::CreateTextureImpl(
const UnpackedPtr<TextureDescriptor>& descriptor) {
return Texture::CreateFromSharedTextureMemory(this, descriptor);
}
MaybeError SharedTextureMemory::BeginAccessImpl(
TextureBase* texture,
const UnpackedPtr<BeginAccessDescriptor>& descriptor) {
DAWN_TRY(d3d::SharedTextureMemory::BeginAccessImpl(texture, descriptor));
if (auto* beginState = descriptor.Get<SharedTextureMemoryD3DSwapchainBeginState>()) {
ToBackend(texture)->SetIsSwapchainTexture(beginState->isSwapchain);
}
// Reset state to COMMON. BeginAccess contains a list of fences to wait on after
// which the texture's usage will complete on the GPU.
// All textures created from SharedTextureMemory must have
// flag D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS. All textures with that flag are eligible
// to decay to COMMON.
// https://learn.microsoft.com/en-us/windows/win32/direct3d12/using-resource-barriers-to-synchronize-resource-states-in-direct3d-12#state-decay-to-common
ToBackend(texture)->ResetSubresourceStateAndDecayToCommon();
return {};
}
ResultOrError<FenceAndSignalValue> SharedTextureMemory::EndAccessImpl(
TextureBase* texture,
ExecutionSerial lastUsageSerial,
UnpackedPtr<EndAccessState>& state) {
ToBackend(texture)->NotifySwapChainPresentToPIX();
return d3d::SharedTextureMemory::EndAccessImpl(texture, lastUsageSerial, state);
}
} // namespace dawn::native::d3d12