From fd359caf0cbdefd759d1c788d72faba3f65a6386 Mon Sep 17 00:00:00 2001 From: jvanverth Date: Fri, 18 Mar 2016 11:57:24 -0700 Subject: Implement Vulkan GrBackendObject for textures. BUG=skia:5043 GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1808263002 Review URL: https://codereview.chromium.org/1808263002 --- src/gpu/vk/GrVkGpu.cpp | 121 ++++++++++++++++++++------------- src/gpu/vk/GrVkRenderTarget.cpp | 29 ++++++-- src/gpu/vk/GrVkRenderTarget.h | 4 +- src/gpu/vk/GrVkTexture.cpp | 29 ++++++-- src/gpu/vk/GrVkTexture.h | 4 +- src/gpu/vk/GrVkTextureRenderTarget.cpp | 31 +++++++-- src/gpu/vk/GrVkTextureRenderTarget.h | 3 +- 7 files changed, 156 insertions(+), 65 deletions(-) (limited to 'src/gpu') diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp index 180ba3be66..16526f6613 100644 --- a/src/gpu/vk/GrVkGpu.cpp +++ b/src/gpu/vk/GrVkGpu.cpp @@ -34,6 +34,7 @@ #include "SkConfig8888.h" #include "vk/GrVkInterface.h" +#include "vk/GrVkTypes.h" #define VK_CALL(X) GR_VK_CALL(this->vkInterface(), X) #define VK_CALL_RET(RET, X) GR_VK_CALL_RET(this->vkInterface(), RET, X) @@ -195,7 +196,8 @@ GrVkGpu::~GrVkGpu() { fCurrentCmdBuffer->unref(this); // wait for all commands to finish - VK_CALL(QueueWaitIdle(fQueue)); + VkResult res = VK_CALL(QueueWaitIdle(fQueue)); + SkASSERT(res == VK_SUCCESS); // must call this just before we destroy the VkDevice fResourceProvider.destroyResources(); @@ -582,8 +584,10 @@ GrTexture* GrVkGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc, return nullptr; } - // TODO: determine what format Chrome will actually send us and turn it into a Resource - GrVkImage::Resource* imageRsrc = reinterpret_cast(desc.fTextureHandle); + const GrVkTextureInfo* info = reinterpret_cast(desc.fTextureHandle); + if (VK_NULL_HANDLE == info->fImage || VK_NULL_HANDLE == info->fAlloc) { + return nullptr; + } GrGpuResource::LifeCycle lifeCycle = (kAdopt_GrWrapOwnership == ownership) ? GrGpuResource::kAdopted_LifeCycle @@ -605,9 +609,10 @@ GrTexture* GrVkGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc, if (renderTarget) { texture = GrVkTextureRenderTarget::CreateWrappedTextureRenderTarget(this, surfDesc, lifeCycle, format, - imageRsrc); + info); } else { - texture = GrVkTexture::CreateWrappedTexture(this, surfDesc, lifeCycle, format, imageRsrc); + texture = GrVkTexture::CreateWrappedTexture(this, surfDesc, lifeCycle, format, + info); } if (!texture) { return nullptr; @@ -619,9 +624,12 @@ GrTexture* GrVkGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc, GrRenderTarget* GrVkGpu::onWrapBackendRenderTarget(const GrBackendRenderTargetDesc& wrapDesc, GrWrapOwnership ownership) { - // TODO: determine what format Chrome will actually send us and turn it into a Resource - GrVkImage::Resource* imageRsrc = - reinterpret_cast(wrapDesc.fRenderTargetHandle); + const GrVkTextureInfo* info = + reinterpret_cast(wrapDesc.fRenderTargetHandle); + if (VK_NULL_HANDLE == info->fImage || + (VK_NULL_HANDLE == info->fAlloc && kAdopt_GrWrapOwnership == ownership)) { + return nullptr; + } GrGpuResource::LifeCycle lifeCycle = (kAdopt_GrWrapOwnership == ownership) ? GrGpuResource::kAdopted_LifeCycle @@ -637,7 +645,8 @@ GrRenderTarget* GrVkGpu::onWrapBackendRenderTarget(const GrBackendRenderTargetDe desc.fOrigin = resolve_origin(wrapDesc.fOrigin); GrVkRenderTarget* tgt = GrVkRenderTarget::CreateWrappedRenderTarget(this, desc, - lifeCycle, imageRsrc); + lifeCycle, + info); if (tgt && wrapDesc.fStencilBits) { if (!createStencilAttachmentForRenderTarget(tgt, desc.fWidth, desc.fHeight)) { tgt->unref(); @@ -736,22 +745,42 @@ GrBackendObject GrVkGpu::createTestingOnlyBackendTexture(void* srcData, int w, i VkFlags memProps = (srcData && linearTiling) ? VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT : VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; - // This ImageDesc refers to the texture that will be read by the client. Thus even if msaa is - // requested, this ImageDesc describes the resolved texutre. Therefore we always have samples set - // to 1. - GrVkImage::ImageDesc imageDesc; - imageDesc.fImageType = VK_IMAGE_TYPE_2D; - imageDesc.fFormat = pixelFormat; - imageDesc.fWidth = w; - imageDesc.fHeight = h; - imageDesc.fLevels = 1; - imageDesc.fSamples = 1; - imageDesc.fImageTiling = linearTiling ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL; - imageDesc.fUsageFlags = usageFlags; - imageDesc.fMemProps = memProps; + VkImage image = VK_NULL_HANDLE; + VkDeviceMemory alloc = VK_NULL_HANDLE; - const GrVkImage::Resource* imageRsrc = GrVkImage::CreateResource(this, imageDesc); - if (!imageRsrc) { + VkImageTiling imageTiling = linearTiling ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL; + VkImageLayout initialLayout = (VK_IMAGE_TILING_LINEAR == imageTiling) + ? VK_IMAGE_LAYOUT_PREINITIALIZED + : VK_IMAGE_LAYOUT_UNDEFINED; + + // Create Image + VkSampleCountFlagBits vkSamples; + if (!GrSampleCountToVkSampleCount(1, &vkSamples)) { + return 0; + } + + const VkImageCreateInfo imageCreateInfo = { + VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // sType + NULL, // pNext + 0, // VkImageCreateFlags + VK_IMAGE_TYPE_2D, // VkImageType + pixelFormat, // VkFormat + { w, h, 1 }, // VkExtent3D + 1, // mipLevels + 1, // arrayLayers + vkSamples, // samples + imageTiling, // VkImageTiling + usageFlags, // VkImageUsageFlags + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode + 0, // queueFamilyCount + 0, // pQueueFamilyIndices + initialLayout // initialLayout + }; + + GR_VK_CALL_ERRCHECK(this->vkInterface(), CreateImage(this->device(), &imageCreateInfo, nullptr, &image)); + + if (!GrVkMemory::AllocAndBindImageMemory(this, image, memProps, &alloc)) { + VK_CALL(DestroyImage(this->device(), image, nullptr)); return 0; } @@ -765,22 +794,13 @@ GrBackendObject GrVkGpu::createTestingOnlyBackendTexture(void* srcData, int w, i VkSubresourceLayout layout; VkResult err; - const GrVkInterface* interface = this->vkInterface(); - - GR_VK_CALL(interface, GetImageSubresourceLayout(fDevice, - imageRsrc->fImage, - &subres, - &layout)); + VK_CALL(GetImageSubresourceLayout(fDevice, image, &subres, &layout)); void* mapPtr; - err = GR_VK_CALL(interface, MapMemory(fDevice, - imageRsrc->fAlloc, - 0, - layout.rowPitch * h, - 0, - &mapPtr)); + err = VK_CALL(MapMemory(fDevice, alloc, 0, layout.rowPitch * h, 0, &mapPtr)); if (err) { - imageRsrc->unref(this); + VK_CALL(FreeMemory(this->device(), alloc, nullptr)); + VK_CALL(DestroyImage(this->device(), image, nullptr)); return 0; } @@ -791,21 +811,27 @@ GrBackendObject GrVkGpu::createTestingOnlyBackendTexture(void* srcData, int w, i if (rowCopyBytes == layout.rowPitch) { memcpy(mapPtr, srcData, rowCopyBytes * h); } else { - SkRectMemcpy(mapPtr, static_cast(layout.rowPitch), srcData, w, rowCopyBytes, - h); + SkRectMemcpy(mapPtr, static_cast(layout.rowPitch), srcData, rowCopyBytes, + rowCopyBytes, h); } - GR_VK_CALL(interface, UnmapMemory(fDevice, imageRsrc->fAlloc)); + VK_CALL(UnmapMemory(fDevice, alloc)); } else { // TODO: Add support for copying to optimal tiling SkASSERT(false); } } - return (GrBackendObject)imageRsrc; + GrVkTextureInfo* info = new GrVkTextureInfo; + info->fImage = image; + info->fAlloc = alloc; + info->fImageTiling = imageTiling; + info->fImageLayout = initialLayout; + + return (GrBackendObject)info; } bool GrVkGpu::isTestingOnlyBackendTexture(GrBackendObject id) const { - GrVkImage::Resource* backend = reinterpret_cast(id); + const GrVkTextureInfo* backend = reinterpret_cast(id); if (backend && backend->fImage && backend->fAlloc) { VkMemoryRequirements req; @@ -822,14 +848,17 @@ bool GrVkGpu::isTestingOnlyBackendTexture(GrBackendObject id) const { } void GrVkGpu::deleteTestingOnlyBackendTexture(GrBackendObject id, bool abandon) { - GrVkImage::Resource* backend = reinterpret_cast(id); + const GrVkTextureInfo* backend = reinterpret_cast(id); if (backend) { if (!abandon) { - backend->unref(this); - } else { - backend->unrefAndAbandon(); + // something in the command buffer may still be using this, so force submit + this->submitCommandBuffer(kForce_SyncQueue); + + VK_CALL(FreeMemory(this->device(), backend->fAlloc, nullptr)); + VK_CALL(DestroyImage(this->device(), backend->fImage, nullptr)); } + delete backend; } } diff --git a/src/gpu/vk/GrVkRenderTarget.cpp b/src/gpu/vk/GrVkRenderTarget.cpp index ee45aa30e8..7ff7f26d42 100644 --- a/src/gpu/vk/GrVkRenderTarget.cpp +++ b/src/gpu/vk/GrVkRenderTarget.cpp @@ -15,6 +15,8 @@ #include "GrVkResourceProvider.h" #include "GrVkUtil.h" +#include "vk/GrVkTypes.h" + #define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X) // We're virtually derived from GrSurface (via GrRenderTarget) so its @@ -203,12 +205,29 @@ GrVkRenderTarget* GrVkRenderTarget::CreateWrappedRenderTarget(GrVkGpu* gpu, const GrSurfaceDesc& desc, GrGpuResource::LifeCycle lifeCycle, - const GrVkImage::Resource* imageResource) { - SkASSERT(imageResource); + const GrVkTextureInfo* info) { + SkASSERT(info); + // We can wrap a rendertarget without its allocation, as long as we don't take ownership + SkASSERT(VK_NULL_HANDLE != info->fImage); + SkASSERT(VK_NULL_HANDLE != info->fAlloc || kAdopted_LifeCycle != lifeCycle); + + GrVkImage::Resource::Flags flags = (VK_IMAGE_TILING_LINEAR == info->fImageTiling) + ? Resource::kLinearTiling_Flag : Resource::kNo_Flags; + + const GrVkImage::Resource* imageResource = new GrVkImage::Resource(info->fImage, + info->fAlloc, + flags); + if (!imageResource) { + return nullptr; + } - // Note: we assume the caller will unref the imageResource - // Create() will increment the refCount, and we'll unref when we're done with it - return GrVkRenderTarget::Create(gpu, desc, lifeCycle, imageResource); + GrVkRenderTarget* rt = GrVkRenderTarget::Create(gpu, desc, lifeCycle, imageResource); + if (rt) { + rt->fCurrentLayout = info->fImageLayout; + } + // Create() will increment the refCount of the image resource if it succeeds + imageResource->unref(gpu); + return rt; } bool GrVkRenderTarget::completeStencilAttachment() { diff --git a/src/gpu/vk/GrVkRenderTarget.h b/src/gpu/vk/GrVkRenderTarget.h index b4d72eac73..21c5788aa1 100644 --- a/src/gpu/vk/GrVkRenderTarget.h +++ b/src/gpu/vk/GrVkRenderTarget.h @@ -20,6 +20,8 @@ class GrVkGpu; class GrVkImageView; class GrVkStencilAttachment; +struct GrVkTextureInfo; + #ifdef SK_BUILD_FOR_WIN // Windows gives bogus warnings about inheriting asTexture/asRenderTarget via dominance. #pragma warning(push) @@ -34,7 +36,7 @@ public: static GrVkRenderTarget* CreateWrappedRenderTarget(GrVkGpu*, const GrSurfaceDesc&, GrGpuResource::LifeCycle, - const GrVkImage::Resource* resource); + const GrVkTextureInfo*); ~GrVkRenderTarget() override; diff --git a/src/gpu/vk/GrVkTexture.cpp b/src/gpu/vk/GrVkTexture.cpp index 5c4c3bd6c7..a6a89df37a 100644 --- a/src/gpu/vk/GrVkTexture.cpp +++ b/src/gpu/vk/GrVkTexture.cpp @@ -10,6 +10,8 @@ #include "GrVkImageView.h" #include "GrVkUtil.h" +#include "vk/GrVkTypes.h" + #define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X) // Because this class is virtually derived from GrSurface we must explicitly call its constructor. @@ -75,12 +77,29 @@ GrVkTexture* GrVkTexture::CreateNewTexture(GrVkGpu* gpu, const GrSurfaceDesc& de GrVkTexture* GrVkTexture::CreateWrappedTexture(GrVkGpu* gpu, const GrSurfaceDesc& desc, GrGpuResource::LifeCycle lifeCycle, VkFormat format, - const GrVkImage::Resource* imageResource) { - SkASSERT(imageResource); + const GrVkTextureInfo* info) { + SkASSERT(info); + // Wrapped textures require both image and allocation (because they can be mapped) + SkASSERT(VK_NULL_HANDLE != info->fImage && VK_NULL_HANDLE != info->fAlloc); + + GrVkImage::Resource::Flags flags = (VK_IMAGE_TILING_LINEAR == info->fImageTiling) + ? Resource::kLinearTiling_Flag : Resource::kNo_Flags; + + const GrVkImage::Resource* imageResource = new GrVkImage::Resource(info->fImage, + info->fAlloc, + flags); + if (!imageResource) { + return nullptr; + } - // Note: we assume the caller will unref the imageResource - // Create() will increment the refCount, and we'll unref when we're done with it - return Create(gpu, desc, lifeCycle, format, imageResource); + GrVkTexture* texture = Create(gpu, desc, lifeCycle, format, imageResource); + if (texture) { + texture->fCurrentLayout = info->fImageLayout; + } + // Create() will increment the refCount of the image resource if it succeeds + imageResource->unref(gpu); + + return texture; } GrVkTexture::~GrVkTexture() { diff --git a/src/gpu/vk/GrVkTexture.h b/src/gpu/vk/GrVkTexture.h index 5e31c9da4b..48ec7305e4 100644 --- a/src/gpu/vk/GrVkTexture.h +++ b/src/gpu/vk/GrVkTexture.h @@ -14,6 +14,7 @@ class GrVkGpu; class GrVkImageView; +struct GrVkTextureInfo; class GrVkTexture : public GrTexture, public virtual GrVkImage { public: @@ -21,10 +22,9 @@ public: GrGpuResource::LifeCycle, const GrVkImage::ImageDesc&); - static GrVkTexture* CreateWrappedTexture(GrVkGpu*, const GrSurfaceDesc&, GrGpuResource::LifeCycle, - VkFormat, const GrVkImage::Resource*); + VkFormat, const GrVkTextureInfo*); ~GrVkTexture() override; diff --git a/src/gpu/vk/GrVkTextureRenderTarget.cpp b/src/gpu/vk/GrVkTextureRenderTarget.cpp index 79ba90481e..fa9327c788 100644 --- a/src/gpu/vk/GrVkTextureRenderTarget.cpp +++ b/src/gpu/vk/GrVkTextureRenderTarget.cpp @@ -12,6 +12,8 @@ #include "GrVkImageView.h" #include "GrVkUtil.h" +#include "vk/GrVkTypes.h" + #define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X) GrVkTextureRenderTarget* @@ -140,11 +142,30 @@ GrVkTextureRenderTarget::CreateWrappedTextureRenderTarget(GrVkGpu* gpu, const GrSurfaceDesc& desc, GrGpuResource::LifeCycle lifeCycle, VkFormat format, - GrVkImage::Resource* imageRsrc) { - SkASSERT(imageRsrc); + const GrVkTextureInfo* info) { + SkASSERT(info); + // Wrapped textures require both image and allocation (because they can be mapped) + SkASSERT(VK_NULL_HANDLE != info->fImage && VK_NULL_HANDLE != info->fAlloc); + + GrVkImage::Resource::Flags flags = (VK_IMAGE_TILING_LINEAR == info->fImageTiling) + ? Resource::kLinearTiling_Flag : Resource::kNo_Flags; + + const GrVkImage::Resource* imageResource = new GrVkImage::Resource(info->fImage, + info->fAlloc, + flags); + if (!imageResource) { + return nullptr; + } + + GrVkTextureRenderTarget* trt = GrVkTextureRenderTarget::Create(gpu, desc, lifeCycle, + format, imageResource); + if (trt) { + trt->fCurrentLayout = info->fImageLayout; + } + // Create() will increment the refCount of the image resource if it succeeds + imageResource->unref(gpu); + + return trt; - // Note: we assume the caller will unref the imageResource - // Create() will increment the refCount, and we'll unref when we're done with it - return GrVkTextureRenderTarget::Create(gpu, desc, lifeCycle, format, imageRsrc); } diff --git a/src/gpu/vk/GrVkTextureRenderTarget.h b/src/gpu/vk/GrVkTextureRenderTarget.h index 6e0d89968f..a7aff009d3 100644 --- a/src/gpu/vk/GrVkTextureRenderTarget.h +++ b/src/gpu/vk/GrVkTextureRenderTarget.h @@ -20,6 +20,7 @@ #endif class GrVkImageView; +struct GrVkTextureInfo; class GrVkTextureRenderTarget: public GrVkTexture, public GrVkRenderTarget { public: @@ -31,7 +32,7 @@ public: const GrSurfaceDesc&, GrGpuResource::LifeCycle, VkFormat, - GrVkImage::Resource*); + const GrVkTextureInfo*); protected: void onAbandon() override { -- cgit v1.2.3