Implement texture subresource on Vulkan
This change implemented texture subresource on Vulkan. It added a new function to handle barriers for texture subresource for bind groups. It also simplified barriers which are set for texture clear and copy. Before this patch, all barriers are done upon all mip levels and all array layers. With this patch, barriers are done upon particular mip level(s) and array layer(s). We may need more texture subresource end2end tests for copy and clear opterations. I will visit that later. Bug: dawn:157 Change-Id: Ie2247c6315326494f2d3736334e84b2867a16c17 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/22024 Commit-Queue: Yunchao He <yunchao.he@intel.com> Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
parent
04701f9f1e
commit
0cd6533d1a
|
@ -150,10 +150,12 @@ namespace dawn_native { namespace vulkan {
|
||||||
|
|
||||||
case wgpu::BindingType::ReadonlyStorageTexture:
|
case wgpu::BindingType::ReadonlyStorageTexture:
|
||||||
case wgpu::BindingType::WriteonlyStorageTexture:
|
case wgpu::BindingType::WriteonlyStorageTexture:
|
||||||
|
// TODO (yunchao.he@intel.com): Do the transition for texture's
|
||||||
|
// subresource via its view.
|
||||||
ToBackend(
|
ToBackend(
|
||||||
static_cast<TextureViewBase*>(mBindings[index][bindingIndex])
|
static_cast<TextureViewBase*>(mBindings[index][bindingIndex])
|
||||||
->GetTexture())
|
->GetTexture())
|
||||||
->TransitionUsageNow(recordingContext,
|
->TransitionFullUsage(recordingContext,
|
||||||
wgpu::TextureUsage::Storage);
|
wgpu::TextureUsage::Storage);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -386,7 +388,8 @@ namespace dawn_native { namespace vulkan {
|
||||||
texture->GetNumMipLevels(), 0,
|
texture->GetNumMipLevels(), 0,
|
||||||
texture->GetArrayLayers());
|
texture->GetArrayLayers());
|
||||||
}
|
}
|
||||||
texture->TransitionUsageNow(recordingContext, usages.textureUsages[i].usage);
|
texture->TransitionUsageForPass(recordingContext,
|
||||||
|
usages.textureUsages[i].subresourceUsages);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const std::vector<PassResourceUsage>& passResourceUsages = GetResourceUsages().perPass;
|
const std::vector<PassResourceUsage>& passResourceUsages = GetResourceUsages().perPass;
|
||||||
|
@ -437,7 +440,9 @@ namespace dawn_native { namespace vulkan {
|
||||||
ToBackend(src.buffer)
|
ToBackend(src.buffer)
|
||||||
->TransitionUsageNow(recordingContext, wgpu::BufferUsage::CopySrc);
|
->TransitionUsageNow(recordingContext, wgpu::BufferUsage::CopySrc);
|
||||||
ToBackend(dst.texture)
|
ToBackend(dst.texture)
|
||||||
->TransitionUsageNow(recordingContext, wgpu::TextureUsage::CopyDst);
|
->TransitionUsageNow(recordingContext, wgpu::TextureUsage::CopyDst,
|
||||||
|
subresource.mipLevel, 1, subresource.baseArrayLayer,
|
||||||
|
1);
|
||||||
VkBuffer srcBuffer = ToBackend(src.buffer)->GetHandle();
|
VkBuffer srcBuffer = ToBackend(src.buffer)->GetHandle();
|
||||||
VkImage dstImage = ToBackend(dst.texture)->GetHandle();
|
VkImage dstImage = ToBackend(dst.texture)->GetHandle();
|
||||||
|
|
||||||
|
@ -464,7 +469,9 @@ namespace dawn_native { namespace vulkan {
|
||||||
subresource.baseArrayLayer, 1);
|
subresource.baseArrayLayer, 1);
|
||||||
|
|
||||||
ToBackend(src.texture)
|
ToBackend(src.texture)
|
||||||
->TransitionUsageNow(recordingContext, wgpu::TextureUsage::CopySrc);
|
->TransitionUsageNow(recordingContext, wgpu::TextureUsage::CopySrc,
|
||||||
|
subresource.mipLevel, 1, subresource.baseArrayLayer,
|
||||||
|
1);
|
||||||
ToBackend(dst.buffer)
|
ToBackend(dst.buffer)
|
||||||
->TransitionUsageNow(recordingContext, wgpu::BufferUsage::CopyDst);
|
->TransitionUsageNow(recordingContext, wgpu::BufferUsage::CopyDst);
|
||||||
|
|
||||||
|
@ -497,9 +504,11 @@ namespace dawn_native { namespace vulkan {
|
||||||
}
|
}
|
||||||
|
|
||||||
ToBackend(src.texture)
|
ToBackend(src.texture)
|
||||||
->TransitionUsageNow(recordingContext, wgpu::TextureUsage::CopySrc);
|
->TransitionUsageNow(recordingContext, wgpu::TextureUsage::CopySrc,
|
||||||
|
src.mipLevel, 1, src.arrayLayer, 1);
|
||||||
ToBackend(dst.texture)
|
ToBackend(dst.texture)
|
||||||
->TransitionUsageNow(recordingContext, wgpu::TextureUsage::CopyDst);
|
->TransitionUsageNow(recordingContext, wgpu::TextureUsage::CopyDst,
|
||||||
|
dst.mipLevel, 1, dst.arrayLayer, 1);
|
||||||
|
|
||||||
// In some situations we cannot do texture-to-texture copies with vkCmdCopyImage
|
// In some situations we cannot do texture-to-texture copies with vkCmdCopyImage
|
||||||
// because as Vulkan SPEC always validates image copies with the virtual size of
|
// because as Vulkan SPEC always validates image copies with the virtual size of
|
||||||
|
|
|
@ -59,7 +59,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
// Perform the necessary pipeline barriers for the texture to be used with the usage
|
// Perform the necessary pipeline barriers for the texture to be used with the usage
|
||||||
// requested by the implementation.
|
// requested by the implementation.
|
||||||
CommandRecordingContext* recordingContext = device->GetPendingRecordingContext();
|
CommandRecordingContext* recordingContext = device->GetPendingRecordingContext();
|
||||||
ToBackend(texture)->TransitionUsageNow(recordingContext, mTextureUsage);
|
ToBackend(texture)->TransitionFullUsage(recordingContext, mTextureUsage);
|
||||||
|
|
||||||
DAWN_TRY(device->SubmitPendingCommands());
|
DAWN_TRY(device->SubmitPendingCommands());
|
||||||
|
|
||||||
|
|
|
@ -225,6 +225,31 @@ namespace dawn_native { namespace vulkan {
|
||||||
return {extent.width, extent.height, extent.depth};
|
return {extent.width, extent.height, extent.depth};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VkImageMemoryBarrier BuildMemoryBarrier(const Format& format,
|
||||||
|
const VkImage& image,
|
||||||
|
wgpu::TextureUsage lastUsage,
|
||||||
|
wgpu::TextureUsage usage,
|
||||||
|
uint32_t mipLevel,
|
||||||
|
uint32_t arrayLayer) {
|
||||||
|
VkImageMemoryBarrier barrier;
|
||||||
|
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||||
|
barrier.pNext = nullptr;
|
||||||
|
barrier.srcAccessMask = VulkanAccessFlags(lastUsage, format);
|
||||||
|
barrier.dstAccessMask = VulkanAccessFlags(usage, format);
|
||||||
|
barrier.oldLayout = VulkanImageLayout(lastUsage, format);
|
||||||
|
barrier.newLayout = VulkanImageLayout(usage, format);
|
||||||
|
barrier.image = image;
|
||||||
|
barrier.subresourceRange.aspectMask = VulkanAspectMask(format);
|
||||||
|
barrier.subresourceRange.baseMipLevel = mipLevel;
|
||||||
|
barrier.subresourceRange.levelCount = 1;
|
||||||
|
barrier.subresourceRange.baseArrayLayer = arrayLayer;
|
||||||
|
barrier.subresourceRange.layerCount = 1;
|
||||||
|
|
||||||
|
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||||
|
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||||
|
return barrier;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// Converts Dawn texture format to Vulkan formats.
|
// Converts Dawn texture format to Vulkan formats.
|
||||||
|
@ -594,7 +619,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
|
|
||||||
// Release the texture
|
// Release the texture
|
||||||
mExternalState = ExternalState::PendingRelease;
|
mExternalState = ExternalState::PendingRelease;
|
||||||
TransitionUsageNow(device->GetPendingRecordingContext(), wgpu::TextureUsage::None);
|
TransitionFullUsage(device->GetPendingRecordingContext(), wgpu::TextureUsage::None);
|
||||||
|
|
||||||
// Queue submit to signal we are done with the texture
|
// Queue submit to signal we are done with the texture
|
||||||
device->GetPendingRecordingContext()->signalSemaphores.push_back(mSignalSemaphore);
|
device->GetPendingRecordingContext()->signalSemaphores.push_back(mSignalSemaphore);
|
||||||
|
@ -644,65 +669,141 @@ namespace dawn_native { namespace vulkan {
|
||||||
return VulkanAspectMask(GetFormat());
|
return VulkanAspectMask(GetFormat());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture::TransitionUsageNow(CommandRecordingContext* recordingContext,
|
void Texture::TweakTransitionForExternalUsage(CommandRecordingContext* recordingContext,
|
||||||
wgpu::TextureUsage usage) {
|
std::vector<VkImageMemoryBarrier>* barriers) {
|
||||||
// Avoid encoding barriers when it isn't needed.
|
ASSERT(GetNumMipLevels() == 1 && GetArrayLayers() == 1);
|
||||||
bool lastReadOnly = (mLastUsage & kReadOnlyTextureUsages) == mLastUsage;
|
ASSERT(barriers->size() <= 1);
|
||||||
if (lastReadOnly && mLastUsage == usage && mLastExternalState == mExternalState) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Format& format = GetFormat();
|
|
||||||
|
|
||||||
VkPipelineStageFlags srcStages = VulkanPipelineStage(mLastUsage, format);
|
|
||||||
VkPipelineStageFlags dstStages = VulkanPipelineStage(usage, format);
|
|
||||||
|
|
||||||
VkImageMemoryBarrier barrier;
|
|
||||||
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
|
||||||
barrier.pNext = nullptr;
|
|
||||||
barrier.srcAccessMask = VulkanAccessFlags(mLastUsage, format);
|
|
||||||
barrier.dstAccessMask = VulkanAccessFlags(usage, format);
|
|
||||||
barrier.oldLayout = VulkanImageLayout(mLastUsage, format);
|
|
||||||
barrier.newLayout = VulkanImageLayout(usage, format);
|
|
||||||
barrier.image = mHandle;
|
|
||||||
// This transitions the whole resource but assumes it is a 2D texture
|
|
||||||
ASSERT(GetDimension() == wgpu::TextureDimension::e2D);
|
|
||||||
barrier.subresourceRange.aspectMask = VulkanAspectMask(format);
|
|
||||||
barrier.subresourceRange.baseMipLevel = 0;
|
|
||||||
barrier.subresourceRange.levelCount = GetNumMipLevels();
|
|
||||||
barrier.subresourceRange.baseArrayLayer = 0;
|
|
||||||
barrier.subresourceRange.layerCount = GetArrayLayers();
|
|
||||||
|
|
||||||
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
||||||
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
||||||
|
|
||||||
if (mExternalState == ExternalState::PendingAcquire) {
|
if (mExternalState == ExternalState::PendingAcquire) {
|
||||||
|
if (!barriers->size()) {
|
||||||
|
barriers->push_back(BuildMemoryBarrier(GetFormat(), mHandle,
|
||||||
|
wgpu::TextureUsage::None,
|
||||||
|
wgpu::TextureUsage::None, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
// Transfer texture from external queue to graphics queue
|
// Transfer texture from external queue to graphics queue
|
||||||
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL_KHR;
|
(*barriers)[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL_KHR;
|
||||||
barrier.dstQueueFamilyIndex = ToBackend(GetDevice())->GetGraphicsQueueFamily();
|
(*barriers)[0].dstQueueFamilyIndex = ToBackend(GetDevice())->GetGraphicsQueueFamily();
|
||||||
// Don't override oldLayout to leave it as VK_IMAGE_LAYOUT_UNDEFINED
|
// Don't override oldLayout to leave it as VK_IMAGE_LAYOUT_UNDEFINED
|
||||||
// TODO(http://crbug.com/dawn/200)
|
// TODO(http://crbug.com/dawn/200)
|
||||||
mExternalState = ExternalState::Acquired;
|
mExternalState = ExternalState::Acquired;
|
||||||
|
|
||||||
} else if (mExternalState == ExternalState::PendingRelease) {
|
} else if (mExternalState == ExternalState::PendingRelease) {
|
||||||
|
if (!barriers->size()) {
|
||||||
|
barriers->push_back(BuildMemoryBarrier(GetFormat(), mHandle,
|
||||||
|
wgpu::TextureUsage::None,
|
||||||
|
wgpu::TextureUsage::None, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
// Transfer texture from graphics queue to external queue
|
// Transfer texture from graphics queue to external queue
|
||||||
barrier.srcQueueFamilyIndex = ToBackend(GetDevice())->GetGraphicsQueueFamily();
|
(*barriers)[0].srcQueueFamilyIndex = ToBackend(GetDevice())->GetGraphicsQueueFamily();
|
||||||
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL_KHR;
|
(*barriers)[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL_KHR;
|
||||||
barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
|
(*barriers)[0].newLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
mExternalState = ExternalState::Released;
|
mExternalState = ExternalState::Released;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move required semaphores into waitSemaphores
|
mLastExternalState = mExternalState;
|
||||||
|
|
||||||
recordingContext->waitSemaphores.insert(recordingContext->waitSemaphores.end(),
|
recordingContext->waitSemaphores.insert(recordingContext->waitSemaphores.end(),
|
||||||
mWaitRequirements.begin(), mWaitRequirements.end());
|
mWaitRequirements.begin(), mWaitRequirements.end());
|
||||||
mWaitRequirements.clear();
|
mWaitRequirements.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Texture::TransitionFullUsage(CommandRecordingContext* recordingContext,
|
||||||
|
wgpu::TextureUsage usage) {
|
||||||
|
TransitionUsageNow(recordingContext, usage, 0, GetNumMipLevels(), 0, GetArrayLayers());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Texture::TransitionUsageForPass(CommandRecordingContext* recordingContext,
|
||||||
|
const std::vector<wgpu::TextureUsage>& subresourceUsages) {
|
||||||
|
std::vector<VkImageMemoryBarrier> barriers;
|
||||||
|
const Format& format = GetFormat();
|
||||||
|
|
||||||
|
wgpu::TextureUsage allUsages = wgpu::TextureUsage::None;
|
||||||
|
wgpu::TextureUsage allLastUsages = wgpu::TextureUsage::None;
|
||||||
|
|
||||||
|
ASSERT(subresourceUsages.size() == GetSubresourceCount());
|
||||||
|
// This transitions assume it is a 2D texture
|
||||||
|
ASSERT(GetDimension() == wgpu::TextureDimension::e2D);
|
||||||
|
|
||||||
|
for (uint32_t arrayLayer = 0; arrayLayer < GetArrayLayers(); ++arrayLayer) {
|
||||||
|
for (uint32_t mipLevel = 0; mipLevel < GetNumMipLevels(); ++mipLevel) {
|
||||||
|
uint32_t index = GetSubresourceIndex(mipLevel, arrayLayer);
|
||||||
|
|
||||||
|
// Avoid encoding barriers when it isn't needed.
|
||||||
|
if (subresourceUsages[index] == wgpu::TextureUsage::None) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
bool lastReadOnly = (mLastSubresourceUsages[index] & kReadOnlyTextureUsages) ==
|
||||||
|
mLastSubresourceUsages[index];
|
||||||
|
if (lastReadOnly && mLastSubresourceUsages[index] == subresourceUsages[index] &&
|
||||||
|
mLastExternalState == mExternalState) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
barriers.push_back(
|
||||||
|
BuildMemoryBarrier(format, mHandle, mLastSubresourceUsages[index],
|
||||||
|
subresourceUsages[index], mipLevel, arrayLayer));
|
||||||
|
|
||||||
|
allUsages |= subresourceUsages[index];
|
||||||
|
allLastUsages |= mLastSubresourceUsages[index];
|
||||||
|
mLastSubresourceUsages[index] = subresourceUsages[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mExternalState != ExternalState::InternalOnly) {
|
||||||
|
TweakTransitionForExternalUsage(recordingContext, &barriers);
|
||||||
|
}
|
||||||
|
|
||||||
|
VkPipelineStageFlags srcStages = VulkanPipelineStage(allLastUsages, format);
|
||||||
|
VkPipelineStageFlags dstStages = VulkanPipelineStage(allUsages, format);
|
||||||
ToBackend(GetDevice())
|
ToBackend(GetDevice())
|
||||||
->fn.CmdPipelineBarrier(recordingContext->commandBuffer, srcStages, dstStages, 0, 0,
|
->fn.CmdPipelineBarrier(recordingContext->commandBuffer, srcStages, dstStages, 0, 0,
|
||||||
nullptr, 0, nullptr, 1, &barrier);
|
nullptr, 0, nullptr, barriers.size(), barriers.data());
|
||||||
|
}
|
||||||
|
|
||||||
mLastUsage = usage;
|
void Texture::TransitionUsageNow(CommandRecordingContext* recordingContext,
|
||||||
mLastExternalState = mExternalState;
|
wgpu::TextureUsage usage,
|
||||||
|
uint32_t baseMipLevel,
|
||||||
|
uint32_t levelCount,
|
||||||
|
uint32_t baseArrayLayer,
|
||||||
|
uint32_t layerCount) {
|
||||||
|
std::vector<VkImageMemoryBarrier> barriers;
|
||||||
|
const Format& format = GetFormat();
|
||||||
|
|
||||||
|
wgpu::TextureUsage allLastUsages = wgpu::TextureUsage::None;
|
||||||
|
|
||||||
|
// This transitions assume it is a 2D texture
|
||||||
|
ASSERT(GetDimension() == wgpu::TextureDimension::e2D);
|
||||||
|
|
||||||
|
for (uint32_t arrayLayer = 0; arrayLayer < layerCount; ++arrayLayer) {
|
||||||
|
for (uint32_t mipLevel = 0; mipLevel < levelCount; ++mipLevel) {
|
||||||
|
uint32_t index =
|
||||||
|
GetSubresourceIndex(baseMipLevel + mipLevel, baseArrayLayer + arrayLayer);
|
||||||
|
wgpu::TextureUsage lastUsage = mLastSubresourceUsages[index];
|
||||||
|
|
||||||
|
// Avoid encoding barriers when it isn't needed.
|
||||||
|
bool lastReadOnly = (lastUsage & kReadOnlyTextureUsages) == lastUsage;
|
||||||
|
if (lastReadOnly && lastUsage == usage && mLastExternalState == mExternalState) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
barriers.push_back(BuildMemoryBarrier(format, mHandle, lastUsage, usage,
|
||||||
|
baseMipLevel + mipLevel,
|
||||||
|
baseArrayLayer + arrayLayer));
|
||||||
|
allLastUsages |= lastUsage;
|
||||||
|
mLastSubresourceUsages[index] = usage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mExternalState != ExternalState::InternalOnly) {
|
||||||
|
TweakTransitionForExternalUsage(recordingContext, &barriers);
|
||||||
|
}
|
||||||
|
|
||||||
|
VkPipelineStageFlags srcStages = VulkanPipelineStage(allLastUsages, format);
|
||||||
|
VkPipelineStageFlags dstStages = VulkanPipelineStage(usage, format);
|
||||||
|
ToBackend(GetDevice())
|
||||||
|
->fn.CmdPipelineBarrier(recordingContext->commandBuffer, srcStages, dstStages, 0, 0,
|
||||||
|
nullptr, 0, nullptr, barriers.size(), barriers.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError Texture::ClearTexture(CommandRecordingContext* recordingContext,
|
MaybeError Texture::ClearTexture(CommandRecordingContext* recordingContext,
|
||||||
|
@ -716,7 +817,8 @@ namespace dawn_native { namespace vulkan {
|
||||||
uint8_t clearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0 : 1;
|
uint8_t clearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0 : 1;
|
||||||
float fClearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0.f : 1.f;
|
float fClearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0.f : 1.f;
|
||||||
|
|
||||||
TransitionUsageNow(recordingContext, wgpu::TextureUsage::CopyDst);
|
TransitionUsageNow(recordingContext, wgpu::TextureUsage::CopyDst, baseMipLevel, levelCount,
|
||||||
|
baseArrayLayer, layerCount);
|
||||||
if (GetFormat().isRenderable) {
|
if (GetFormat().isRenderable) {
|
||||||
VkImageSubresourceRange range = {};
|
VkImageSubresourceRange range = {};
|
||||||
range.aspectMask = GetVkAspectMask();
|
range.aspectMask = GetVkAspectMask();
|
||||||
|
|
|
@ -63,8 +63,18 @@ namespace dawn_native { namespace vulkan {
|
||||||
// Transitions the texture to be used as `usage`, recording any necessary barrier in
|
// Transitions the texture to be used as `usage`, recording any necessary barrier in
|
||||||
// `commands`.
|
// `commands`.
|
||||||
// TODO(cwallez@chromium.org): coalesce barriers and do them early when possible.
|
// TODO(cwallez@chromium.org): coalesce barriers and do them early when possible.
|
||||||
void TransitionUsageNow(CommandRecordingContext* recordingContext,
|
void TransitionFullUsage(CommandRecordingContext* recordingContext,
|
||||||
wgpu::TextureUsage usage);
|
wgpu::TextureUsage usage);
|
||||||
|
|
||||||
|
void TransitionUsageNow(CommandRecordingContext* recordingContext,
|
||||||
|
wgpu::TextureUsage usage,
|
||||||
|
uint32_t baseMipLevel,
|
||||||
|
uint32_t levelCount,
|
||||||
|
uint32_t baseArrayLayer,
|
||||||
|
uint32_t layerCount);
|
||||||
|
void TransitionUsageForPass(CommandRecordingContext* recordingContext,
|
||||||
|
const std::vector<wgpu::TextureUsage>& subresourceUsages);
|
||||||
|
|
||||||
void EnsureSubresourceContentInitialized(CommandRecordingContext* recordingContext,
|
void EnsureSubresourceContentInitialized(CommandRecordingContext* recordingContext,
|
||||||
uint32_t baseMipLevel,
|
uint32_t baseMipLevel,
|
||||||
uint32_t levelCount,
|
uint32_t levelCount,
|
||||||
|
@ -96,6 +106,9 @@ namespace dawn_native { namespace vulkan {
|
||||||
uint32_t layerCount,
|
uint32_t layerCount,
|
||||||
TextureBase::ClearValue);
|
TextureBase::ClearValue);
|
||||||
|
|
||||||
|
void TweakTransitionForExternalUsage(CommandRecordingContext* recordingContext,
|
||||||
|
std::vector<VkImageMemoryBarrier>* barriers);
|
||||||
|
|
||||||
VkImage mHandle = VK_NULL_HANDLE;
|
VkImage mHandle = VK_NULL_HANDLE;
|
||||||
ResourceMemoryAllocation mMemoryAllocation;
|
ResourceMemoryAllocation mMemoryAllocation;
|
||||||
VkDeviceMemory mExternalAllocation = VK_NULL_HANDLE;
|
VkDeviceMemory mExternalAllocation = VK_NULL_HANDLE;
|
||||||
|
@ -115,7 +128,8 @@ namespace dawn_native { namespace vulkan {
|
||||||
|
|
||||||
// A usage of none will make sure the texture is transitioned before its first use as
|
// A usage of none will make sure the texture is transitioned before its first use as
|
||||||
// required by the Vulkan spec.
|
// required by the Vulkan spec.
|
||||||
wgpu::TextureUsage mLastUsage = wgpu::TextureUsage::None;
|
std::vector<wgpu::TextureUsage> mLastSubresourceUsages =
|
||||||
|
std::vector<wgpu::TextureUsage>(GetSubresourceCount(), wgpu::TextureUsage::None);
|
||||||
};
|
};
|
||||||
|
|
||||||
class TextureView final : public TextureViewBase {
|
class TextureView final : public TextureViewBase {
|
||||||
|
|
|
@ -188,7 +188,12 @@ TEST_P(TextureSubresourceTest, ArrayLayersTest) {
|
||||||
EXPECT_TEXTURE_RGBA8_EQ(&bottomLeft, texture, 0, kSize - 1, 1, 1, 0, 1);
|
EXPECT_TEXTURE_RGBA8_EQ(&bottomLeft, texture, 0, kSize - 1, 1, 1, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO (yunchao.he@intel.com): add tests for storage texture and sampler across miplevel or
|
// TODO (yunchao.he@intel.com):
|
||||||
|
// * add tests for storage texture and sampler across miplevel or
|
||||||
// arraylayer dimensions in the same texture
|
// arraylayer dimensions in the same texture
|
||||||
|
//
|
||||||
|
// * add tests for copy operation upon texture subresource if needed
|
||||||
|
//
|
||||||
|
// * add tests for clear operation upon texture subresource if needed
|
||||||
|
|
||||||
DAWN_INSTANTIATE_TEST(TextureSubresourceTest, MetalBackend(), OpenGLBackend());
|
DAWN_INSTANTIATE_TEST(TextureSubresourceTest, MetalBackend(), OpenGLBackend(), VulkanBackend());
|
||||||
|
|
Loading…
Reference in New Issue