blob: a47cfdd955b90bd0d373a7427afba746ecaabd11 [file] [log] [blame]
/*
* Copyright 2021 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/gpu/graphite/BackendTexture.h"
#include "include/gpu/MutableTextureState.h"
#ifdef SK_DAWN
#include "include/private/gpu/graphite/DawnTypesPriv.h"
#endif
#ifdef SK_VULKAN
#include "include/gpu/vk/VulkanMutableTextureState.h"
#endif
namespace skgpu::graphite {
BackendTexture::BackendTexture() = default;
BackendTexture::~BackendTexture() = default;
BackendTexture::BackendTexture(const BackendTexture& that) {
*this = that;
}
BackendTexture& BackendTexture::operator=(const BackendTexture& that) {
if (!that.isValid()) {
fInfo = {};
return *this;
}
// We shouldn't be mixing backends.
SkASSERT(!this->isValid() || this->backend() == that.backend());
fDimensions = that.fDimensions;
fInfo = that.fInfo;
switch (that.backend()) {
#ifdef SK_DAWN
case BackendApi::kDawn:
fDawnTexture = that.fDawnTexture;
fDawnTextureView = that.fDawnTextureView;
break;
#endif
#ifdef SK_METAL
case BackendApi::kMetal:
fMtlTexture = that.fMtlTexture;
break;
#endif
#ifdef SK_VULKAN
case BackendApi::kVulkan:
fVkImage = that.fVkImage;
fMutableState = that.fMutableState;
fMemoryAlloc = that.fMemoryAlloc;
break;
#endif
default:
SK_ABORT("Unsupported Backend");
}
return *this;
}
bool BackendTexture::operator==(const BackendTexture& that) const {
if (!this->isValid() || !that.isValid()) {
return false;
}
if (fDimensions != that.fDimensions || fInfo != that.fInfo) {
return false;
}
switch (that.backend()) {
#ifdef SK_DAWN
case BackendApi::kDawn:
if (fDawnTexture != that.fDawnTexture) {
return false;
}
if (fDawnTextureView != that.fDawnTextureView) {
return false;
}
break;
#endif
#ifdef SK_METAL
case BackendApi::kMetal:
if (fMtlTexture != that.fMtlTexture) {
return false;
}
break;
#endif
#ifdef SK_VULKAN
case BackendApi::kVulkan:
if (fVkImage != that.fVkImage) {
return false;
}
break;
#endif
default:
SK_ABORT("Unsupported Backend");
}
return true;
}
void BackendTexture::setMutableState(const skgpu::MutableTextureState& newState) {
fMutableState->set(newState);
}
sk_sp<MutableTextureState> BackendTexture::getMutableState() const {
return fMutableState;
}
#ifdef SK_DAWN
BackendTexture::BackendTexture(WGPUTexture texture)
: fDimensions{static_cast<int32_t>(wgpuTextureGetWidth(texture)),
static_cast<int32_t>(wgpuTextureGetHeight(texture))}
, fInfo(DawnTextureInfoFromWGPUTexture(texture))
, fDawnTexture(texture)
, fDawnTextureView(nullptr) {}
BackendTexture::BackendTexture(SkISize planeDimensions,
const DawnTextureInfo& info,
WGPUTexture texture)
: fDimensions(planeDimensions)
, fInfo(info)
, fDawnTexture(texture)
, fDawnTextureView(nullptr) {
#if defined(__EMSCRIPTEN__)
SkASSERT(info.fAspect == wgpu::TextureAspect::All);
#else
SkASSERT(info.fAspect == wgpu::TextureAspect::All ||
info.fAspect == wgpu::TextureAspect::Plane0Only ||
info.fAspect == wgpu::TextureAspect::Plane1Only ||
info.fAspect == wgpu::TextureAspect::Plane2Only);
#endif
}
// When we only have a WGPUTextureView we can't actually take advantage of these TextureUsage bits
// because they require having the WGPUTexture.
static DawnTextureInfo strip_copy_usage(const DawnTextureInfo& info) {
DawnTextureInfo result = info;
result.fUsage &= ~(wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::CopySrc);
return result;
}
BackendTexture::BackendTexture(SkISize dimensions,
const DawnTextureInfo& info,
WGPUTextureView textureView)
: fDimensions(dimensions)
, fInfo(strip_copy_usage(info))
, fDawnTexture(nullptr)
, fDawnTextureView(textureView) {}
WGPUTexture BackendTexture::getDawnTexturePtr() const {
if (this->isValid() && this->backend() == BackendApi::kDawn) {
return fDawnTexture;
}
return {};
}
WGPUTextureView BackendTexture::getDawnTextureViewPtr() const {
if (this->isValid() && this->backend() == BackendApi::kDawn) {
return fDawnTextureView;
}
return {};
}
#endif
#ifdef SK_METAL
BackendTexture::BackendTexture(SkISize dimensions, CFTypeRef mtlTexture)
: fDimensions(dimensions)
, fInfo(MtlTextureInfo(mtlTexture))
, fMtlTexture(mtlTexture) {}
CFTypeRef BackendTexture::getMtlTexture() const {
if (this->isValid() && this->backend() == BackendApi::kMetal) {
return fMtlTexture;
}
return nullptr;
}
#endif // SK_METAL
#ifdef SK_VULKAN
BackendTexture::BackendTexture(SkISize dimensions,
const VulkanTextureInfo& info,
VkImageLayout layout,
uint32_t queueFamilyIndex,
VkImage image,
VulkanAlloc vulkanMemoryAllocation)
: fDimensions(dimensions)
, fInfo(info)
, fMutableState(sk_make_sp<skgpu::MutableTextureState>(
skgpu::MutableTextureStates::MakeVulkan(layout, queueFamilyIndex)))
, fMemoryAlloc(vulkanMemoryAllocation)
, fVkImage(image) {}
VkImage BackendTexture::getVkImage() const {
if (this->isValid() && this->backend() == BackendApi::kVulkan) {
return fVkImage;
}
return VK_NULL_HANDLE;
}
VkImageLayout BackendTexture::getVkImageLayout() const {
if (this->isValid() && this->backend() == BackendApi::kVulkan) {
SkASSERT(fMutableState);
return skgpu::MutableTextureStates::GetVkImageLayout(fMutableState.get());
}
return VK_IMAGE_LAYOUT_UNDEFINED;
}
uint32_t BackendTexture::getVkQueueFamilyIndex() const {
if (this->isValid() && this->backend() == BackendApi::kVulkan) {
SkASSERT(fMutableState);
return skgpu::MutableTextureStates::GetVkQueueFamilyIndex(fMutableState.get());
}
return 0;
}
const VulkanAlloc* BackendTexture::getMemoryAlloc() const {
if (this->isValid() && this->backend() == BackendApi::kVulkan) {
return &fMemoryAlloc;
}
return {};
}
#endif // SK_VULKAN
} // namespace skgpu::graphite