Browse Source

Added Vulkan texture read/writeData implementations
More lenient texture error checking - don't crash on error

BearishSun 9 năm trước cách đây
mục cha
commit
95d48bf94c

+ 42 - 11
Source/BansheeCore/Source/BsTexture.cpp

@@ -136,7 +136,8 @@ namespace BansheeEngine
 		if (pixelData.getWidth() != mipWidth || pixelData.getHeight() != mipHeight ||
 			pixelData.getDepth() != mipDepth || pixelData.getFormat() != mProperties.getFormat())
 		{
-			BS_EXCEPT(RenderingAPIException, "Provided buffer is not of valid dimensions or format in order to read from this texture.");
+			LOGERR("Provided buffer is not of valid dimensions or format in order to read from this texture.");
+			return;
 		}
 
 		readData(pixelData, mip, face, deviceIdx, queueIdx);
@@ -147,10 +148,16 @@ namespace BansheeEngine
 		THROW_IF_NOT_CORE_THREAD;
 
 		if (mipLevel > mProperties.getNumMipmaps())
-			BS_EXCEPT(InvalidParametersException, "Invalid mip level: " + toString(mipLevel) + ". Min is 0, max is " + toString(mProperties.getNumMipmaps()));
+		{
+			LOGERR("Invalid mip level: " + toString(mipLevel) + ". Min is 0, max is " + toString(mProperties.getNumMipmaps()));
+			return PixelData(0, 0, 0, PF_UNKNOWN);
+		}
 
 		if (face >= mProperties.getNumFaces())
-			BS_EXCEPT(InvalidParametersException, "Invalid face index: " + toString(face) + ". Min is 0, max is " + toString(mProperties.getNumFaces()));
+		{
+			LOGERR("Invalid face index: " + toString(face) + ". Min is 0, max is " + toString(mProperties.getNumFaces()));
+			return PixelData(0, 0, 0, PF_UNKNOWN);
+		}
 
 		return lockImpl(options, mipLevel, face, deviceIdx, queueIdx);
 	}
@@ -168,13 +175,22 @@ namespace BansheeEngine
 		THROW_IF_NOT_CORE_THREAD;
 
 		if (target->mProperties.getTextureType() != mProperties.getTextureType())
-			BS_EXCEPT(InvalidParametersException, "Source and destination textures must be of same type and must have the same usage and type.");
+		{
+			LOGERR("Source and destination textures must be of same type and must have the same usage and type.");
+			return;
+		}
 
 		if (mProperties.getFormat() != target->mProperties.getFormat()) // Note: It might be okay to use different formats of the same size
-			BS_EXCEPT(InvalidParametersException, "Source and destination texture formats must match.");
+		{
+			LOGERR("Source and destination texture formats must match.");
+			return;
+		}
 
 		if (target->mProperties.getNumSamples() > 0 && mProperties.getNumSamples() != target->mProperties.getNumSamples())
-			BS_EXCEPT(InvalidParametersException, "When copying to a multisampled texture, source texture must have the same number of samples.");
+		{
+			LOGERR("When copying to a multisampled texture, source texture must have the same number of samples.");
+			return;
+		}
 
 		UINT32 srcFace = 0;
 		UINT32 srcMipLevel = 0;
@@ -186,16 +202,28 @@ namespace BansheeEngine
 		target->mProperties.mapFromSubresourceIdx(destSubresourceIdx, destFace, destMipLevel);
 
 		if (destFace >= mProperties.getNumFaces())
-			BS_EXCEPT(InvalidParametersException, "Invalid destination face index");
+		{
+			LOGERR("Invalid destination face index");
+			return;
+		}
 
 		if (srcFace >= target->mProperties.getNumFaces())
-			BS_EXCEPT(InvalidParametersException, "Invalid destination face index");
+		{
+			LOGERR("Invalid destination face index");
+			return;
+		}
 
 		if (srcMipLevel > mProperties.getNumMipmaps())
-			BS_EXCEPT(InvalidParametersException, "Source mip level out of range. Valid range is [0, " + toString(mProperties.getNumMipmaps()) + "]");
+		{
+			LOGERR("Source mip level out of range. Valid range is [0, " + toString(mProperties.getNumMipmaps()) + "]");
+			return;
+		}
 
 		if (destMipLevel > target->mProperties.getNumMipmaps())
-			BS_EXCEPT(InvalidParametersException, "Destination mip level out of range. Valid range is [0, " + toString(target->mProperties.getNumMipmaps()) + "]");
+		{
+			LOGERR("Destination mip level out of range. Valid range is [0, " + toString(target->mProperties.getNumMipmaps()) + "]");
+			return;
+		}
 
 		UINT32 srcMipWidth = mProperties.getWidth() >> srcMipLevel;
 		UINT32 srcMipHeight = mProperties.getHeight() >> srcMipLevel;
@@ -206,7 +234,10 @@ namespace BansheeEngine
 		UINT32 dstMipDepth = target->mProperties.getDepth() >> destMipLevel;
 
 		if (srcMipWidth != dstMipWidth || srcMipHeight != dstMipHeight || srcMipDepth != dstMipDepth)
-			BS_EXCEPT(InvalidParametersException, "Source and destination sizes must match");
+		{
+			LOGERR("Source and destination sizes must match");
+			return;
+		}
 
 		copyImpl(srcFace, srcMipLevel, destFace, destMipLevel, target, queueIdx);
 	}

+ 14 - 5
Source/BansheeD3D11RenderAPI/Source/BsD3D11Texture.cpp

@@ -158,9 +158,12 @@ namespace BansheeEngine
 	void D3D11TextureCore::readData(PixelData& dest, UINT32 mipLevel, UINT32 face, UINT32 deviceIdx, UINT32 queueIdx)
 	{
 		if (mProperties.getNumSamples() > 1)
-			BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
+		{
+			LOGERR("Multisampled textures cannot be accessed from the CPU directly.");
+			return;
+		}
 
-		PixelData myData = lock(GBL_READ_ONLY, mipLevel, face);
+		PixelData myData = lock(GBL_READ_ONLY, mipLevel, face, deviceIdx, queueIdx);
 
 #if BS_DEBUG_MODE
 		if(dest.getConsecutiveSize() != myData.getConsecutiveSize())
@@ -181,17 +184,23 @@ namespace BansheeEngine
 		PixelFormat format = mProperties.getFormat();
 
 		if (mProperties.getNumSamples() > 1)
-			BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
+		{
+			LOGERR("Multisampled textures cannot be accessed from the CPU directly.");
+			return;
+		}
 
 		mipLevel = Math::clamp(mipLevel, (UINT32)mipLevel, mProperties.getNumMipmaps());
 		face = Math::clamp(face, (UINT32)0, mProperties.getNumFaces() - 1);
 
 		if (face > 0 && mProperties.getTextureType() == TEX_TYPE_3D)
-			BS_EXCEPT(InvalidStateException, "3D texture arrays are not supported.");
+		{
+			LOGERR("3D texture arrays are not supported.");
+			return;
+		}
 
 		if ((mProperties.getUsage() & TU_DYNAMIC) != 0)
 		{
-			PixelData myData = lock(discardWholeBuffer ? GBL_WRITE_ONLY_DISCARD : GBL_WRITE_ONLY, mipLevel, face);
+			PixelData myData = lock(discardWholeBuffer ? GBL_WRITE_ONLY_DISCARD : GBL_WRITE_ONLY, mipLevel, face, 0, queueIdx);
 			PixelUtil::bulkPixelConversion(src, myData);
 			unlock();
 		}

+ 50 - 0
Source/BansheeVulkanRenderAPI/Source/BsVulkanTexture.cpp

@@ -6,6 +6,7 @@
 #include "BsVulkanUtility.h"
 #include "BsCoreThread.h"
 #include "BsRenderStats.h"
+#include "BsMath.h"
 
 namespace BansheeEngine
 {
@@ -288,12 +289,61 @@ namespace BansheeEngine
 
 	void VulkanTextureCore::readData(PixelData& dest, UINT32 mipLevel, UINT32 face, UINT32 deviceIdx, UINT32 queueIdx)
 	{
+		if (mProperties.getNumSamples() > 1)
+		{
+			LOGERR("Multisampled textures cannot be accessed from the CPU directly.");
+			return;
+		}
+
+		PixelData myData = lock(GBL_READ_ONLY, mipLevel, face, deviceIdx, queueIdx);
+
+#if BS_DEBUG_MODE
+		if (dest.getConsecutiveSize() != myData.getConsecutiveSize())
+		{
+			unlock();
+			BS_EXCEPT(InternalErrorException, "Buffer sizes don't match");
+		}
+#endif
+
+		PixelUtil::bulkPixelConversion(myData, dest);
+
+		unlock();
+
 		BS_INC_RENDER_STAT_CAT(ResRead, RenderStatObject_Texture);
 	}
 
 	void VulkanTextureCore::writeData(const PixelData& src, UINT32 mipLevel, UINT32 face, bool discardWholeBuffer,
 									  UINT32 queueIdx)
 	{
+		if (mProperties.getNumSamples() > 1)
+		{
+			LOGERR("Multisampled textures cannot be accessed from the CPU directly.");
+			return;
+		}
+
+		PixelFormat format = mProperties.getFormat();
+
+		mipLevel = Math::clamp(mipLevel, (UINT32)mipLevel, mProperties.getNumMipmaps());
+		face = Math::clamp(face, (UINT32)0, mProperties.getNumFaces() - 1);
+
+		if (face > 0 && mProperties.getTextureType() == TEX_TYPE_3D)
+		{
+			LOGERR("3D texture arrays are not supported.");
+			return;
+		}
+
+		// Write to every device
+		for (UINT32 i = 0; i < BS_MAX_DEVICES; i++)
+		{
+			if (mImages[i] == nullptr)
+				continue;
+
+			PixelData myData = lock(discardWholeBuffer ? GBL_WRITE_ONLY_DISCARD : GBL_WRITE_ONLY, mipLevel, face, i,
+									queueIdx);
+			PixelUtil::bulkPixelConversion(src, myData);
+			unlock();
+		}
+
 		BS_INC_RENDER_STAT_CAT(ResWrite, RenderStatObject_Texture);
 	}
 }