Vulkan: Add proper error handling for all regular object creation.

This makes all the regular WebGPU object creation handle errors properly
in the Vulkan backend instead of ASSERTing no Vulkan error is raised.

Static Create functions are added to all these types so that the details
of how the initialization is done is private, and it isn't possible to
construct an object but forget to initialize it.

BUG=dawn:19

Change-Id: I362b2d66b74dd7799ffbf69d732bc58caa97950b
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/11861
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
This commit is contained in:
Corentin Wallez 2019-10-08 08:16:11 +00:00 committed by Commit Bot service account
parent bc8e7ea286
commit e986cb9254
25 changed files with 260 additions and 117 deletions

View File

@ -16,6 +16,7 @@
#include "common/BitSetIterator.h"
#include "dawn_native/vulkan/DeviceVk.h"
#include "dawn_native/vulkan/VulkanError.h"
namespace dawn_native { namespace vulkan {
@ -60,8 +61,17 @@ namespace dawn_native { namespace vulkan {
}
}
BindGroupLayout::BindGroupLayout(Device* device, const BindGroupLayoutDescriptor* descriptor)
: BindGroupLayoutBase(device, descriptor) {
// static
ResultOrError<BindGroupLayout*> BindGroupLayout::Create(
Device* device,
const BindGroupLayoutDescriptor* descriptor) {
std::unique_ptr<BindGroupLayout> bgl =
std::make_unique<BindGroupLayout>(device, descriptor);
DAWN_TRY(bgl->Initialize());
return bgl.release();
}
MaybeError BindGroupLayout::Initialize() {
const auto& info = GetBindingInfo();
// Compute the bindings that will be chained in the DescriptorSetLayout create info. We add
@ -88,10 +98,10 @@ namespace dawn_native { namespace vulkan {
createInfo.bindingCount = numBindings;
createInfo.pBindings = bindings.data();
if (device->fn.CreateDescriptorSetLayout(device->GetVkDevice(), &createInfo, nullptr,
&mHandle) != VK_SUCCESS) {
ASSERT(false);
}
Device* device = ToBackend(GetDevice());
return CheckVkSuccess(device->fn.CreateDescriptorSetLayout(device->GetVkDevice(),
&createInfo, nullptr, &mHandle),
"CreateDescriptorSetLayout");
}
BindGroupLayout::~BindGroupLayout() {

View File

@ -27,7 +27,8 @@ namespace dawn_native { namespace vulkan {
class BindGroupLayout : public BindGroupLayoutBase {
public:
BindGroupLayout(Device* device, const BindGroupLayoutDescriptor* descriptor);
static ResultOrError<BindGroupLayout*> Create(Device* device,
const BindGroupLayoutDescriptor* descriptor);
~BindGroupLayout();
VkDescriptorSetLayout GetHandle() const;
@ -37,6 +38,9 @@ namespace dawn_native { namespace vulkan {
PoolSizeSpec ComputePoolSizes(uint32_t* numPoolSizes) const;
private:
using BindGroupLayoutBase::BindGroupLayoutBase;
MaybeError Initialize();
VkDescriptorSetLayout mHandle = VK_NULL_HANDLE;
};

View File

@ -14,19 +14,28 @@
#include "dawn_native/vulkan/BindGroupVk.h"
#include "common/BitSetIterator.h"
#include "dawn_native/vulkan/BindGroupLayoutVk.h"
#include "dawn_native/vulkan/BufferVk.h"
#include "dawn_native/vulkan/DeviceVk.h"
#include "dawn_native/vulkan/FencedDeleter.h"
#include "dawn_native/vulkan/SamplerVk.h"
#include "dawn_native/vulkan/TextureVk.h"
#include "common/BitSetIterator.h"
#include "dawn_native/vulkan/VulkanError.h"
namespace dawn_native { namespace vulkan {
BindGroup::BindGroup(Device* device, const BindGroupDescriptor* descriptor)
: BindGroupBase(device, descriptor) {
// static
ResultOrError<BindGroup*> BindGroup::Create(Device* device,
const BindGroupDescriptor* descriptor) {
std::unique_ptr<BindGroup> group = std::make_unique<BindGroup>(device, descriptor);
DAWN_TRY(group->Initialize());
return group.release();
}
MaybeError BindGroup::Initialize() {
Device* device = ToBackend(GetDevice());
// Create a pool to hold our descriptor set.
// TODO(cwallez@chromium.org): This horribly inefficient, find a way to be better, for
// example by having one pool per bind group layout instead.
@ -41,10 +50,9 @@ namespace dawn_native { namespace vulkan {
createInfo.poolSizeCount = numPoolSizes;
createInfo.pPoolSizes = poolSizes.data();
if (device->fn.CreateDescriptorPool(device->GetVkDevice(), &createInfo, nullptr, &mPool) !=
VK_SUCCESS) {
ASSERT(false);
}
DAWN_TRY(CheckVkSuccess(
device->fn.CreateDescriptorPool(device->GetVkDevice(), &createInfo, nullptr, &mPool),
"CreateDescriptorPool"));
// Now do the allocation of one descriptor set, this is very suboptimal too.
VkDescriptorSetLayout vkLayout = ToBackend(GetLayout())->GetHandle();
@ -56,10 +64,9 @@ namespace dawn_native { namespace vulkan {
allocateInfo.descriptorSetCount = 1;
allocateInfo.pSetLayouts = &vkLayout;
if (device->fn.AllocateDescriptorSets(device->GetVkDevice(), &allocateInfo, &mHandle) !=
VK_SUCCESS) {
ASSERT(false);
}
DAWN_TRY(CheckVkSuccess(
device->fn.AllocateDescriptorSets(device->GetVkDevice(), &allocateInfo, &mHandle),
"AllocateDescriptorSets"));
// Now do a write of a single descriptor set with all possible chained data allocated on the
// stack.
@ -118,6 +125,8 @@ namespace dawn_native { namespace vulkan {
device->fn.UpdateDescriptorSets(device->GetVkDevice(), numWrites, writes.data(), 0,
nullptr);
return {};
}
BindGroup::~BindGroup() {

View File

@ -25,12 +25,16 @@ namespace dawn_native { namespace vulkan {
class BindGroup : public BindGroupBase {
public:
BindGroup(Device* device, const BindGroupDescriptor* descriptor);
static ResultOrError<BindGroup*> Create(Device* device,
const BindGroupDescriptor* descriptor);
~BindGroup();
VkDescriptorSet GetHandle() const;
private:
using BindGroupBase::BindGroupBase;
MaybeError Initialize();
VkDescriptorPool mPool = VK_NULL_HANDLE;
VkDescriptorSet mHandle = VK_NULL_HANDLE;
};

View File

@ -114,8 +114,11 @@ namespace dawn_native { namespace vulkan {
} // namespace
Buffer::Buffer(Device* device, const BufferDescriptor* descriptor)
: BufferBase(device, descriptor) {
// static
ResultOrError<Buffer*> Buffer::Create(Device* device, const BufferDescriptor* descriptor) {
std::unique_ptr<Buffer> buffer = std::make_unique<Buffer>(device, descriptor);
DAWN_TRY(buffer->Initialize());
return buffer.release();
}
MaybeError Buffer::Initialize() {

View File

@ -29,11 +29,9 @@ namespace dawn_native { namespace vulkan {
class Buffer : public BufferBase {
public:
Buffer(Device* device, const BufferDescriptor* descriptor);
static ResultOrError<Buffer*> Create(Device* device, const BufferDescriptor* descriptor);
~Buffer();
MaybeError Initialize();
void OnMapReadCommandSerialFinished(uint32_t mapSerial, const void* data);
void OnMapWriteCommandSerialFinished(uint32_t mapSerial, void* data);
@ -45,6 +43,9 @@ namespace dawn_native { namespace vulkan {
void TransitionUsageNow(CommandRecordingContext* recordingContext, dawn::BufferUsage usage);
private:
using BufferBase::BufferBase;
MaybeError Initialize();
// Dawn API
MaybeError MapReadAsyncImpl(uint32_t serial) override;
MaybeError MapWriteAsyncImpl(uint32_t serial) override;

View File

@ -286,6 +286,12 @@ namespace dawn_native { namespace vulkan {
}
} // anonymous namespace
// static
CommandBuffer* CommandBuffer::Create(CommandEncoderBase* encoder,
const CommandBufferDescriptor* descriptor) {
return new CommandBuffer(encoder, descriptor);
}
CommandBuffer::CommandBuffer(CommandEncoderBase* encoder,
const CommandBufferDescriptor* descriptor)
: CommandBufferBase(encoder, descriptor), mCommands(encoder->AcquireCommands()) {

View File

@ -17,6 +17,7 @@
#include "dawn_native/CommandAllocator.h"
#include "dawn_native/CommandBuffer.h"
#include "dawn_native/Error.h"
#include "common/vulkan_platform.h"
@ -32,12 +33,15 @@ namespace dawn_native { namespace vulkan {
class CommandBuffer : public CommandBufferBase {
public:
CommandBuffer(CommandEncoderBase* encoder, const CommandBufferDescriptor* descriptor);
static CommandBuffer* Create(CommandEncoderBase* encoder,
const CommandBufferDescriptor* descriptor);
~CommandBuffer();
void RecordCommands(CommandRecordingContext* recordingContext);
private:
CommandBuffer(CommandEncoderBase* encoder, const CommandBufferDescriptor* descriptor);
void RecordComputePass(CommandRecordingContext* recordingContext);
void RecordRenderPass(CommandRecordingContext* recordingContext,
BeginRenderPassCmd* renderPass);

View File

@ -18,11 +18,21 @@
#include "dawn_native/vulkan/FencedDeleter.h"
#include "dawn_native/vulkan/PipelineLayoutVk.h"
#include "dawn_native/vulkan/ShaderModuleVk.h"
#include "dawn_native/vulkan/VulkanError.h"
namespace dawn_native { namespace vulkan {
ComputePipeline::ComputePipeline(Device* device, const ComputePipelineDescriptor* descriptor)
: ComputePipelineBase(device, descriptor) {
// static
ResultOrError<ComputePipeline*> ComputePipeline::Create(
Device* device,
const ComputePipelineDescriptor* descriptor) {
std::unique_ptr<ComputePipeline> pipeline =
std::make_unique<ComputePipeline>(device, descriptor);
DAWN_TRY(pipeline->Initialize(descriptor));
return pipeline.release();
}
MaybeError ComputePipeline::Initialize(const ComputePipelineDescriptor* descriptor) {
VkComputePipelineCreateInfo createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
createInfo.pNext = nullptr;
@ -39,10 +49,11 @@ namespace dawn_native { namespace vulkan {
createInfo.stage.pName = descriptor->computeStage.entryPoint;
createInfo.stage.pSpecializationInfo = nullptr;
if (device->fn.CreateComputePipelines(device->GetVkDevice(), VK_NULL_HANDLE, 1, &createInfo,
nullptr, &mHandle) != VK_SUCCESS) {
ASSERT(false);
}
Device* device = ToBackend(GetDevice());
return CheckVkSuccess(
device->fn.CreateComputePipelines(device->GetVkDevice(), VK_NULL_HANDLE, 1, &createInfo,
nullptr, &mHandle),
"CreateComputePipeline");
}
ComputePipeline::~ComputePipeline() {

View File

@ -18,6 +18,7 @@
#include "dawn_native/ComputePipeline.h"
#include "common/vulkan_platform.h"
#include "dawn_native/Error.h"
namespace dawn_native { namespace vulkan {
@ -25,12 +26,16 @@ namespace dawn_native { namespace vulkan {
class ComputePipeline : public ComputePipelineBase {
public:
ComputePipeline(Device* device, const ComputePipelineDescriptor* descriptor);
static ResultOrError<ComputePipeline*> Create(Device* device,
const ComputePipelineDescriptor* descriptor);
~ComputePipeline();
VkPipeline GetHandle() const;
private:
using ComputePipelineBase::ComputePipelineBase;
MaybeError Initialize(const ComputePipelineDescriptor* descriptor);
VkPipeline mHandle = VK_NULL_HANDLE;
};

View File

@ -147,54 +147,52 @@ namespace dawn_native { namespace vulkan {
ResultOrError<BindGroupBase*> Device::CreateBindGroupImpl(
const BindGroupDescriptor* descriptor) {
return new BindGroup(this, descriptor);
return BindGroup::Create(this, descriptor);
}
ResultOrError<BindGroupLayoutBase*> Device::CreateBindGroupLayoutImpl(
const BindGroupLayoutDescriptor* descriptor) {
return new BindGroupLayout(this, descriptor);
return BindGroupLayout::Create(this, descriptor);
}
ResultOrError<BufferBase*> Device::CreateBufferImpl(const BufferDescriptor* descriptor) {
std::unique_ptr<Buffer> buffer = std::make_unique<Buffer>(this, descriptor);
DAWN_TRY(buffer->Initialize());
return buffer.release();
return Buffer::Create(this, descriptor);
}
CommandBufferBase* Device::CreateCommandBuffer(CommandEncoderBase* encoder,
const CommandBufferDescriptor* descriptor) {
return new CommandBuffer(encoder, descriptor);
return CommandBuffer::Create(encoder, descriptor);
}
ResultOrError<ComputePipelineBase*> Device::CreateComputePipelineImpl(
const ComputePipelineDescriptor* descriptor) {
return new ComputePipeline(this, descriptor);
return ComputePipeline::Create(this, descriptor);
}
ResultOrError<PipelineLayoutBase*> Device::CreatePipelineLayoutImpl(
const PipelineLayoutDescriptor* descriptor) {
return new PipelineLayout(this, descriptor);
return PipelineLayout::Create(this, descriptor);
}
ResultOrError<QueueBase*> Device::CreateQueueImpl() {
return new Queue(this);
return Queue::Create(this);
}
ResultOrError<RenderPipelineBase*> Device::CreateRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) {
return new RenderPipeline(this, descriptor);
return RenderPipeline::Create(this, descriptor);
}
ResultOrError<SamplerBase*> Device::CreateSamplerImpl(const SamplerDescriptor* descriptor) {
return new Sampler(this, descriptor);
return Sampler::Create(this, descriptor);
}
ResultOrError<ShaderModuleBase*> Device::CreateShaderModuleImpl(
const ShaderModuleDescriptor* descriptor) {
return new ShaderModule(this, descriptor);
return ShaderModule::Create(this, descriptor);
}
ResultOrError<SwapChainBase*> Device::CreateSwapChainImpl(
const SwapChainDescriptor* descriptor) {
return new SwapChain(this, descriptor);
return SwapChain::Create(this, descriptor);
}
ResultOrError<TextureBase*> Device::CreateTextureImpl(const TextureDescriptor* descriptor) {
return new Texture(this, descriptor);
return Texture::Create(this, descriptor);
}
ResultOrError<TextureViewBase*> Device::CreateTextureViewImpl(
TextureBase* texture,
const TextureViewDescriptor* descriptor) {
return new TextureView(texture, descriptor);
return TextureView::Create(texture, descriptor);
}
Serial Device::GetCompletedCommandSerial() const {

View File

@ -14,16 +14,25 @@
#include "dawn_native/vulkan/PipelineLayoutVk.h"
#include "common/BitSetIterator.h"
#include "dawn_native/vulkan/BindGroupLayoutVk.h"
#include "dawn_native/vulkan/DeviceVk.h"
#include "dawn_native/vulkan/FencedDeleter.h"
#include "common/BitSetIterator.h"
#include "dawn_native/vulkan/VulkanError.h"
namespace dawn_native { namespace vulkan {
PipelineLayout::PipelineLayout(Device* device, const PipelineLayoutDescriptor* descriptor)
: PipelineLayoutBase(device, descriptor) {
// static
ResultOrError<PipelineLayout*> PipelineLayout::Create(
Device* device,
const PipelineLayoutDescriptor* descriptor) {
std::unique_ptr<PipelineLayout> layout =
std::make_unique<PipelineLayout>(device, descriptor);
DAWN_TRY(layout->Initialize());
return layout.release();
}
MaybeError PipelineLayout::Initialize() {
// Compute the array of VkDescriptorSetLayouts that will be chained in the create info.
// TODO(cwallez@chromium.org) Vulkan doesn't allow holes in this array, should we expose
// this constraints at the Dawn level?
@ -43,10 +52,10 @@ namespace dawn_native { namespace vulkan {
createInfo.pushConstantRangeCount = 0;
createInfo.pPushConstantRanges = nullptr;
if (device->fn.CreatePipelineLayout(device->GetVkDevice(), &createInfo, nullptr,
&mHandle) != VK_SUCCESS) {
ASSERT(false);
}
Device* device = ToBackend(GetDevice());
return CheckVkSuccess(
device->fn.CreatePipelineLayout(device->GetVkDevice(), &createInfo, nullptr, &mHandle),
"CreatePipelineLayout");
}
PipelineLayout::~PipelineLayout() {

View File

@ -18,6 +18,7 @@
#include "dawn_native/PipelineLayout.h"
#include "common/vulkan_platform.h"
#include "dawn_native/Error.h"
namespace dawn_native { namespace vulkan {
@ -25,12 +26,16 @@ namespace dawn_native { namespace vulkan {
class PipelineLayout : public PipelineLayoutBase {
public:
PipelineLayout(Device* device, const PipelineLayoutDescriptor* descriptor);
static ResultOrError<PipelineLayout*> Create(Device* device,
const PipelineLayoutDescriptor* descriptor);
~PipelineLayout();
VkPipelineLayout GetHandle() const;
private:
using PipelineLayoutBase::PipelineLayoutBase;
MaybeError Initialize();
VkPipelineLayout mHandle = VK_NULL_HANDLE;
};

View File

@ -20,7 +20,9 @@
namespace dawn_native { namespace vulkan {
Queue::Queue(Device* device) : QueueBase(device) {
// static
Queue* Queue::Create(Device* device) {
return new Queue(device);
}
Queue::~Queue() {

View File

@ -24,10 +24,12 @@ namespace dawn_native { namespace vulkan {
class Queue : public QueueBase {
public:
Queue(Device* device);
static Queue* Create(Device* device);
~Queue();
private:
using QueueBase::QueueBase;
MaybeError SubmitImpl(uint32_t commandCount, CommandBufferBase* const* commands) override;
};

View File

@ -21,6 +21,7 @@
#include "dawn_native/vulkan/ShaderModuleVk.h"
#include "dawn_native/vulkan/TextureVk.h"
#include "dawn_native/vulkan/UtilsVulkan.h"
#include "dawn_native/vulkan/VulkanError.h"
namespace dawn_native { namespace vulkan {
@ -318,8 +319,19 @@ namespace dawn_native { namespace vulkan {
} // anonymous namespace
RenderPipeline::RenderPipeline(Device* device, const RenderPipelineDescriptor* descriptor)
: RenderPipelineBase(device, descriptor) {
// static
ResultOrError<RenderPipeline*> RenderPipeline::Create(
Device* device,
const RenderPipelineDescriptor* descriptor) {
std::unique_ptr<RenderPipeline> pipeline =
std::make_unique<RenderPipeline>(device, descriptor);
DAWN_TRY(pipeline->Initialize(descriptor));
return pipeline.release();
}
MaybeError RenderPipeline::Initialize(const RenderPipelineDescriptor* descriptor) {
Device* device = ToBackend(GetDevice());
VkPipelineShaderStageCreateInfo shaderStages[2];
{
shaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
@ -488,10 +500,10 @@ namespace dawn_native { namespace vulkan {
createInfo.basePipelineHandle = VK_NULL_HANDLE;
createInfo.basePipelineIndex = -1;
if (device->fn.CreateGraphicsPipelines(device->GetVkDevice(), VK_NULL_HANDLE, 1,
&createInfo, nullptr, &mHandle) != VK_SUCCESS) {
ASSERT(false);
}
return CheckVkSuccess(
device->fn.CreateGraphicsPipelines(device->GetVkDevice(), VK_NULL_HANDLE, 1,
&createInfo, nullptr, &mHandle),
"CreateGraphicsPipeline");
}
VkPipelineVertexInputStateCreateInfo RenderPipeline::ComputeVertexInputDesc(

View File

@ -18,6 +18,7 @@
#include "dawn_native/RenderPipeline.h"
#include "common/vulkan_platform.h"
#include "dawn_native/Error.h"
namespace dawn_native { namespace vulkan {
@ -25,12 +26,16 @@ namespace dawn_native { namespace vulkan {
class RenderPipeline : public RenderPipelineBase {
public:
RenderPipeline(Device* device, const RenderPipelineDescriptor* descriptor);
static ResultOrError<RenderPipeline*> Create(Device* device,
const RenderPipelineDescriptor* descriptor);
~RenderPipeline();
VkPipeline GetHandle() const;
private:
using RenderPipelineBase::RenderPipelineBase;
MaybeError Initialize(const RenderPipelineDescriptor* descriptor);
VkPipelineVertexInputStateCreateInfo ComputeVertexInputDesc(
const VertexInputDescriptor* vertexInput,
std::array<VkVertexInputBindingDescription, kMaxVertexBuffers>* mBindings,

View File

@ -17,6 +17,7 @@
#include "dawn_native/vulkan/DeviceVk.h"
#include "dawn_native/vulkan/FencedDeleter.h"
#include "dawn_native/vulkan/UtilsVulkan.h"
#include "dawn_native/vulkan/VulkanError.h"
namespace dawn_native { namespace vulkan {
@ -57,8 +58,14 @@ namespace dawn_native { namespace vulkan {
}
} // anonymous namespace
Sampler::Sampler(Device* device, const SamplerDescriptor* descriptor)
: SamplerBase(device, descriptor), mDevice(device) {
// static
ResultOrError<Sampler*> Sampler::Create(Device* device, const SamplerDescriptor* descriptor) {
std::unique_ptr<Sampler> sampler = std::make_unique<Sampler>(device, descriptor);
DAWN_TRY(sampler->Initialize(descriptor));
return sampler.release();
}
MaybeError Sampler::Initialize(const SamplerDescriptor* descriptor) {
VkSamplerCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
createInfo.pNext = nullptr;
@ -78,15 +85,15 @@ namespace dawn_native { namespace vulkan {
createInfo.maxLod = descriptor->lodMaxClamp;
createInfo.unnormalizedCoordinates = VK_FALSE;
if (device->fn.CreateSampler(device->GetVkDevice(), &createInfo, nullptr, &mHandle) !=
VK_SUCCESS) {
ASSERT(false);
}
Device* device = ToBackend(GetDevice());
return CheckVkSuccess(
device->fn.CreateSampler(device->GetVkDevice(), &createInfo, nullptr, &mHandle),
"CreateSampler");
}
Sampler::~Sampler() {
if (mHandle != VK_NULL_HANDLE) {
mDevice->GetFencedDeleter()->DeleteWhenUnused(mHandle);
ToBackend(GetDevice())->GetFencedDeleter()->DeleteWhenUnused(mHandle);
mHandle = VK_NULL_HANDLE;
}
}

View File

@ -18,20 +18,23 @@
#include "dawn_native/Sampler.h"
#include "common/vulkan_platform.h"
#include "dawn_native/Error.h"
#include "dawn_native/vulkan/MemoryAllocator.h"
namespace dawn_native { namespace vulkan {
class Sampler : public SamplerBase {
public:
Sampler(Device* device, const SamplerDescriptor* descriptor);
static ResultOrError<Sampler*> Create(Device* device, const SamplerDescriptor* descriptor);
~Sampler();
VkSampler GetHandle() const;
private:
using SamplerBase::SamplerBase;
MaybeError Initialize(const SamplerDescriptor* descriptor);
VkSampler mHandle = VK_NULL_HANDLE;
Device* mDevice = nullptr;
};
}} // namespace dawn_native::vulkan

View File

@ -16,13 +16,21 @@
#include "dawn_native/vulkan/DeviceVk.h"
#include "dawn_native/vulkan/FencedDeleter.h"
#include "dawn_native/vulkan/VulkanError.h"
#include <spirv_cross.hpp>
namespace dawn_native { namespace vulkan {
ShaderModule::ShaderModule(Device* device, const ShaderModuleDescriptor* descriptor)
: ShaderModuleBase(device, descriptor) {
// static
ResultOrError<ShaderModule*> ShaderModule::Create(Device* device,
const ShaderModuleDescriptor* descriptor) {
std::unique_ptr<ShaderModule> module = std::make_unique<ShaderModule>(device, descriptor);
DAWN_TRY(module->Initialize(descriptor));
return module.release();
}
MaybeError ShaderModule::Initialize(const ShaderModuleDescriptor* descriptor) {
// Use SPIRV-Cross to extract info from the SPIRV even if Vulkan consumes SPIRV. We want to
// have a translation step eventually anyway.
spirv_cross::Compiler compiler(descriptor->code, descriptor->codeSize);
@ -35,10 +43,10 @@ namespace dawn_native { namespace vulkan {
createInfo.codeSize = descriptor->codeSize * sizeof(uint32_t);
createInfo.pCode = descriptor->code;
if (device->fn.CreateShaderModule(device->GetVkDevice(), &createInfo, nullptr, &mHandle) !=
VK_SUCCESS) {
ASSERT(false);
}
Device* device = ToBackend(GetDevice());
return CheckVkSuccess(
device->fn.CreateShaderModule(device->GetVkDevice(), &createInfo, nullptr, &mHandle),
"CreateShaderModule");
}
ShaderModule::~ShaderModule() {

View File

@ -18,6 +18,7 @@
#include "dawn_native/ShaderModule.h"
#include "common/vulkan_platform.h"
#include "dawn_native/Error.h"
namespace dawn_native { namespace vulkan {
@ -25,12 +26,16 @@ namespace dawn_native { namespace vulkan {
class ShaderModule : public ShaderModuleBase {
public:
ShaderModule(Device* device, const ShaderModuleDescriptor* descriptor);
static ResultOrError<ShaderModule*> Create(Device* device,
const ShaderModuleDescriptor* descriptor);
~ShaderModule();
VkShaderModule GetHandle() const;
private:
using ShaderModuleBase::ShaderModuleBase;
MaybeError Initialize(const ShaderModuleDescriptor* descriptor);
VkShaderModule mHandle = VK_NULL_HANDLE;
};

View File

@ -19,6 +19,11 @@
namespace dawn_native { namespace vulkan {
// static
SwapChain* SwapChain::Create(Device* device, const SwapChainDescriptor* descriptor) {
return new SwapChain(device, descriptor);
}
SwapChain::SwapChain(Device* device, const SwapChainDescriptor* descriptor)
: SwapChainBase(device, descriptor) {
const auto& im = GetImplementation();

View File

@ -25,10 +25,12 @@ namespace dawn_native { namespace vulkan {
class SwapChain : public SwapChainBase {
public:
SwapChain(Device* device, const SwapChainDescriptor* descriptor);
static SwapChain* Create(Device* device, const SwapChainDescriptor* descriptor);
~SwapChain();
protected:
SwapChain(Device* device, const SwapChainDescriptor* descriptor);
TextureBase* GetNextTextureImpl(const TextureDescriptor* descriptor) override;
MaybeError OnBeforePresent(TextureBase* texture) override;

View File

@ -26,6 +26,7 @@
#include "dawn_native/vulkan/FencedDeleter.h"
#include "dawn_native/vulkan/StagingBufferVk.h"
#include "dawn_native/vulkan/UtilsVulkan.h"
#include "dawn_native/vulkan/VulkanError.h"
namespace dawn_native { namespace vulkan {
@ -395,8 +396,17 @@ namespace dawn_native { namespace vulkan {
return {};
}
Texture::Texture(Device* device, const TextureDescriptor* descriptor)
: TextureBase(device, descriptor, TextureState::OwnedInternal) {
// static
ResultOrError<Texture*> Texture::Create(Device* device, const TextureDescriptor* descriptor) {
std::unique_ptr<Texture> texture =
std::make_unique<Texture>(device, descriptor, TextureState::OwnedInternal);
DAWN_TRY(texture->InitializeAsInternalTexture());
return texture.release();
}
MaybeError Texture::InitializeAsInternalTexture() {
Device* device = ToBackend(GetDevice());
// Create the Vulkan image "container". We don't need to check that the format supports the
// combination of sample, usage etc. because validation should have been done in the Dawn
// frontend already based on the minimum supported formats in the Vulkan spec
@ -428,29 +438,30 @@ namespace dawn_native { namespace vulkan {
// also required for the implementation of robust resource initialization.
createInfo.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
if (device->fn.CreateImage(device->GetVkDevice(), &createInfo, nullptr, &mHandle) !=
VK_SUCCESS) {
ASSERT(false);
}
DAWN_TRY(CheckVkSuccess(
device->fn.CreateImage(device->GetVkDevice(), &createInfo, nullptr, &mHandle),
"CreateImage"));
// Create the image memory and associate it with the container
VkMemoryRequirements requirements;
device->fn.GetImageMemoryRequirements(device->GetVkDevice(), mHandle, &requirements);
if (!device->GetMemoryAllocator()->Allocate(requirements, false, &mMemoryAllocation)) {
ASSERT(false);
return DAWN_OUT_OF_MEMORY_ERROR("Failed to allocate texture");
}
if (device->fn.BindImageMemory(device->GetVkDevice(), mHandle,
mMemoryAllocation.GetMemory(),
mMemoryAllocation.GetMemoryOffset()) != VK_SUCCESS) {
ASSERT(false);
}
DAWN_TRY(CheckVkSuccess(device->fn.BindImageMemory(device->GetVkDevice(), mHandle,
mMemoryAllocation.GetMemory(),
mMemoryAllocation.GetMemoryOffset()),
"BindImageMemory"));
if (device->IsToggleEnabled(Toggle::NonzeroClearResourcesOnCreationForTesting)) {
device->ConsumedError(ClearTexture(ToBackend(GetDevice())->GetPendingRecordingContext(),
0, GetNumMipLevels(), 0, GetArrayLayers(),
TextureBase::ClearValue::NonZero));
DAWN_TRY(ClearTexture(ToBackend(GetDevice())->GetPendingRecordingContext(), 0,
GetNumMipLevels(), 0, GetArrayLayers(),
TextureBase::ClearValue::NonZero));
}
return {};
}
// With this constructor, the lifetime of the resource is externally managed.
@ -756,10 +767,16 @@ namespace dawn_native { namespace vulkan {
}
}
// TODO(jiawei.shao@intel.com): create texture view by TextureViewDescriptor
TextureView::TextureView(TextureBase* texture, const TextureViewDescriptor* descriptor)
: TextureViewBase(texture, descriptor) {
Device* device = ToBackend(texture->GetDevice());
// static
ResultOrError<TextureView*> TextureView::Create(TextureBase* texture,
const TextureViewDescriptor* descriptor) {
std::unique_ptr<TextureView> view = std::make_unique<TextureView>(texture, descriptor);
DAWN_TRY(view->Initialize(descriptor));
return view.release();
}
MaybeError TextureView::Initialize(const TextureViewDescriptor* descriptor) {
Device* device = ToBackend(GetTexture()->GetDevice());
VkImageViewCreateInfo createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
@ -776,10 +793,9 @@ namespace dawn_native { namespace vulkan {
createInfo.subresourceRange.baseArrayLayer = descriptor->baseArrayLayer;
createInfo.subresourceRange.layerCount = descriptor->arrayLayerCount;
if (device->fn.CreateImageView(device->GetVkDevice(), &createInfo, nullptr, &mHandle) !=
VK_SUCCESS) {
ASSERT(false);
}
return CheckVkSuccess(
device->fn.CreateImageView(device->GetVkDevice(), &createInfo, nullptr, &mHandle),
"CreateImageView");
}
TextureView::~TextureView() {

View File

@ -35,15 +35,7 @@ namespace dawn_native { namespace vulkan {
class Texture : public TextureBase {
public:
enum class ExternalState {
InternalOnly,
PendingAcquire,
Acquired,
PendingRelease,
Released
};
Texture(Device* device, const TextureDescriptor* descriptor);
static ResultOrError<Texture*> Create(Device* device, const TextureDescriptor* descriptor);
Texture(Device* device, const TextureDescriptor* descriptor, VkImage nativeImage);
Texture(Device* device,
const ExternalImageDescriptor* descriptor,
@ -70,6 +62,9 @@ namespace dawn_native { namespace vulkan {
MaybeError SignalAndDestroy(VkSemaphore* outSignalSemaphore);
private:
using TextureBase::TextureBase;
MaybeError InitializeAsInternalTexture();
void DestroyImpl() override;
MaybeError ClearTexture(CommandRecordingContext* recordingContext,
uint32_t baseMipLevel,
@ -82,24 +77,36 @@ namespace dawn_native { namespace vulkan {
DeviceMemoryAllocation mMemoryAllocation;
VkDeviceMemory mExternalAllocation = VK_NULL_HANDLE;
enum class ExternalState {
InternalOnly,
PendingAcquire,
Acquired,
PendingRelease,
Released
};
ExternalState mExternalState = ExternalState::InternalOnly;
ExternalState mLastExternalState = ExternalState::InternalOnly;
VkSemaphore mSignalSemaphore = VK_NULL_HANDLE;
std::vector<VkSemaphore> mWaitRequirements;
// A usage of none will make sure the texture is transitioned before its first use as
// required by the spec.
// required by the Vulkan spec.
dawn::TextureUsage mLastUsage = dawn::TextureUsage::None;
};
class TextureView : public TextureViewBase {
public:
TextureView(TextureBase* texture, const TextureViewDescriptor* descriptor);
static ResultOrError<TextureView*> Create(TextureBase* texture,
const TextureViewDescriptor* descriptor);
~TextureView();
VkImageView GetHandle() const;
private:
using TextureViewBase::TextureViewBase;
MaybeError Initialize(const TextureViewDescriptor* descriptor);
VkImageView mHandle = VK_NULL_HANDLE;
};