From 17275ed17099bdd6619034b717290b0574fdd33f Mon Sep 17 00:00:00 2001 From: Yun Hsiao Wu Date: Thu, 20 Aug 2020 16:30:30 +0800 Subject: [PATCH] GFX Descriptor Set: Vulkan --- cocos/renderer/core/gfx/GFXBuffer.h | 11 +- cocos/renderer/core/gfx/GFXCommandBuffer.h | 2 +- cocos/renderer/core/gfx/GFXDef.h | 1 - cocos/renderer/core/gfx/GFXTexture.h | 2 + cocos/renderer/gfx-gles2/GLES2Buffer.cc | 8 +- .../renderer/gfx-gles2/GLES2CommandBuffer.cc | 4 +- cocos/renderer/gfx-gles2/GLES2CommandBuffer.h | 2 +- cocos/renderer/gfx-gles2/GLES2Commands.cc | 2 + .../renderer/gfx-gles2/GLES2DescriptorSet.cc | 34 +-- cocos/renderer/gfx-gles2/GLES2DescriptorSet.h | 4 +- cocos/renderer/gfx-gles2/GLES2Texture.cc | 2 +- cocos/renderer/gfx-gles3/GLES3Buffer.h | 2 - .../renderer/gfx-gles3/GLES3CommandBuffer.cc | 2 +- cocos/renderer/gfx-gles3/GLES3CommandBuffer.h | 2 +- cocos/renderer/gfx-gles3/GLES3Texture.cc | 3 +- cocos/renderer/gfx-vulkan/CMakeLists.txt | 6 - cocos/renderer/gfx-vulkan/VKBindingLayout.cc | 198 --------------- cocos/renderer/gfx-vulkan/VKBindingLayout.h | 28 --- cocos/renderer/gfx-vulkan/VKBuffer.cc | 61 ++++- cocos/renderer/gfx-vulkan/VKBuffer.h | 6 + cocos/renderer/gfx-vulkan/VKCommandBuffer.cc | 67 +++-- cocos/renderer/gfx-vulkan/VKCommandBuffer.h | 47 ++-- cocos/renderer/gfx-vulkan/VKCommands.cc | 228 +++++++++--------- cocos/renderer/gfx-vulkan/VKCommands.h | 4 + cocos/renderer/gfx-vulkan/VKDescriptorSet.cc | 170 +++++++++++++ cocos/renderer/gfx-vulkan/VKDescriptorSet.h | 28 +++ .../gfx-vulkan/VKDescriptorSetLayout.cc | 44 ++++ .../gfx-vulkan/VKDescriptorSetLayout.h | 27 +++ cocos/renderer/gfx-vulkan/VKDevice.cc | 44 +++- cocos/renderer/gfx-vulkan/VKDevice.h | 6 +- cocos/renderer/gfx-vulkan/VKGPUObjects.h | 161 ++++++------- cocos/renderer/gfx-vulkan/VKPipelineLayout.cc | 47 ++++ cocos/renderer/gfx-vulkan/VKPipelineLayout.h | 27 +++ cocos/renderer/gfx-vulkan/VKPipelineState.cc | 3 + cocos/renderer/gfx-vulkan/VKSPIRV.h | 18 +- cocos/renderer/gfx-vulkan/VKTexture.cc | 12 +- cocos/renderer/gfx-vulkan/VKUtils.h | 42 ++-- 37 files changed, 783 insertions(+), 572 deletions(-) delete mode 100644 cocos/renderer/gfx-vulkan/VKBindingLayout.cc delete mode 100644 cocos/renderer/gfx-vulkan/VKBindingLayout.h create mode 100644 cocos/renderer/gfx-vulkan/VKDescriptorSet.cc create mode 100644 cocos/renderer/gfx-vulkan/VKDescriptorSet.h create mode 100644 cocos/renderer/gfx-vulkan/VKDescriptorSetLayout.cc create mode 100644 cocos/renderer/gfx-vulkan/VKDescriptorSetLayout.h create mode 100644 cocos/renderer/gfx-vulkan/VKPipelineLayout.cc create mode 100644 cocos/renderer/gfx-vulkan/VKPipelineLayout.h diff --git a/cocos/renderer/core/gfx/GFXBuffer.h b/cocos/renderer/core/gfx/GFXBuffer.h index b0bc3b2aa77..bcd943f5a8c 100755 --- a/cocos/renderer/core/gfx/GFXBuffer.h +++ b/cocos/renderer/core/gfx/GFXBuffer.h @@ -25,17 +25,20 @@ class CC_DLL Buffer : public GFXObject { CC_INLINE uint getCount() const { return _count; } CC_INLINE uint getSize() const { return _size; } CC_INLINE BufferFlags getFlags() const { return _flags; } - CC_INLINE uint8_t *getBufferView() const { return _buffer; } + CC_INLINE uint8_t *getBackupBuffer() const { return _buffer; } + CC_INLINE bool isBufferView() const { return _isBufferView; } protected: Device *_device = nullptr; BufferUsage _usage = BufferUsageBit::NONE; MemoryUsage _memUsage = MemoryUsageBit::NONE; - uint _stride = 0; - uint _count = 0; - uint _size = 0; + uint _stride = 0u; + uint _count = 0u; + uint _size = 0u; + uint _offset = 0u; BufferFlags _flags = BufferFlagBit::NONE; uint8_t *_buffer = nullptr; + bool _isBufferView = false; }; } // namespace gfx diff --git a/cocos/renderer/core/gfx/GFXCommandBuffer.h b/cocos/renderer/core/gfx/GFXCommandBuffer.h index 120ac56d76a..847c93f333c 100755 --- a/cocos/renderer/core/gfx/GFXCommandBuffer.h +++ b/cocos/renderer/core/gfx/GFXCommandBuffer.h @@ -19,7 +19,7 @@ class CC_DLL CommandBuffer : public GFXObject { virtual void beginRenderPass(RenderPass *renderPass, Framebuffer *fbo, const Rect &renderArea, const vector &colors, float depth, int stencil) = 0; virtual void endRenderPass() = 0; virtual void bindPipelineState(PipelineState *pso) = 0; - virtual void bindDescriptorSet(uint set, DescriptorSet *descriptorSet, uint dynamicOffsetCount, uint *dynamicOffsets) = 0; + virtual void bindDescriptorSet(uint set, DescriptorSet *descriptorSet, uint dynamicOffsetCount, const uint *dynamicOffsets) = 0; virtual void bindInputAssembler(InputAssembler *ia) = 0; virtual void setViewport(const Viewport &vp) = 0; virtual void setScissor(const Rect &rect) = 0; diff --git a/cocos/renderer/core/gfx/GFXDef.h b/cocos/renderer/core/gfx/GFXDef.h index d5f178bd41d..ae39eddf79e 100755 --- a/cocos/renderer/core/gfx/GFXDef.h +++ b/cocos/renderer/core/gfx/GFXDef.h @@ -34,7 +34,6 @@ enum class ObjectType : uint8_t { UNKNOWN, BUFFER, TEXTURE, - TEXTURE_VIEW, RENDER_PASS, FRAMEBUFFER, SAMPLER, diff --git a/cocos/renderer/core/gfx/GFXTexture.h b/cocos/renderer/core/gfx/GFXTexture.h index 31fa9fc72ad..eec972cbbe4 100755 --- a/cocos/renderer/core/gfx/GFXTexture.h +++ b/cocos/renderer/core/gfx/GFXTexture.h @@ -29,6 +29,7 @@ class CC_DLL Texture : public GFXObject { CC_INLINE SampleCount getSamples() const { return _samples; } CC_INLINE TextureFlags getFlags() const { return _flags; } CC_INLINE uint8_t *getBuffer() const { return _buffer; } + CC_INLINE bool isTextureView() const { return _isTextureView; } protected: Device *_device = nullptr; @@ -46,6 +47,7 @@ class CC_DLL Texture : public GFXObject { SampleCount _samples = SampleCount::X1; TextureFlags _flags = TextureFlagBit::NONE; uint8_t *_buffer = nullptr; + bool _isTextureView = false; }; } // namespace gfx diff --git a/cocos/renderer/gfx-gles2/GLES2Buffer.cc b/cocos/renderer/gfx-gles2/GLES2Buffer.cc index 5af8a86c2bf..52ff4d8f71e 100644 --- a/cocos/renderer/gfx-gles2/GLES2Buffer.cc +++ b/cocos/renderer/gfx-gles2/GLES2Buffer.cc @@ -18,7 +18,7 @@ bool GLES2Buffer::initialize(const BufferInfo &info) { _usage = info.usage; _memUsage = info.memUsage; _size = info.size; - _stride = std::max(info.stride, 1U); + _stride = std::max(info.stride, 1u); _count = _size / _stride; _flags = info.flags; @@ -60,6 +60,8 @@ bool GLES2Buffer::initialize(const BufferInfo &info) { bool GLES2Buffer::initialize(const BufferViewInfo &info) { + _isBufferView = true; + GLES2Buffer *buffer = (GLES2Buffer *)info.buffer; _usage = buffer->_usage; @@ -96,7 +98,7 @@ void GLES2Buffer::destroy() { } void GLES2Buffer::resize(uint size) { - CCASSERT(!_gpuBufferView, "Cannot resize buffer views"); + CCASSERT(!_isBufferView, "Cannot resize buffer views"); if (_size != size) { const uint oldSize = _size; @@ -129,7 +131,7 @@ void GLES2Buffer::resize(uint size) { } void GLES2Buffer::update(void *buffer, uint offset, uint size) { - CCASSERT(!_gpuBufferView, "Cannot update through buffer views"); + CCASSERT(!_isBufferView, "Cannot update through buffer views"); CCASSERT(size != 0, "Should not update buffer with 0 bytes of data"); CCASSERT(buffer, "Buffer should not be nullptr"); diff --git a/cocos/renderer/gfx-gles2/GLES2CommandBuffer.cc b/cocos/renderer/gfx-gles2/GLES2CommandBuffer.cc index 9a58c046519..e36dbd5ea00 100644 --- a/cocos/renderer/gfx-gles2/GLES2CommandBuffer.cc +++ b/cocos/renderer/gfx-gles2/GLES2CommandBuffer.cc @@ -98,12 +98,12 @@ void GLES2CommandBuffer::bindPipelineState(PipelineState *pso) { } } -void GLES2CommandBuffer::bindDescriptorSet(uint set, DescriptorSet *descriptorSet, uint dynamicOffsetCount, uint *dynamicOffsets) { +void GLES2CommandBuffer::bindDescriptorSet(uint set, DescriptorSet *descriptorSet, uint dynamicOffsetCount, const uint *dynamicOffsets) { // these will break if using more sets than what's declared in DeviceInfo.bindingMappingInfo CCASSERT(_curGPUDescriptorSets.size() > set, ""); CCASSERT(_curDynamicOffsets.size() > set, ""); - GLES2GPUDescriptorSet *gpuDescriptorSet = ((GLES2DescriptorSet *)descriptorSet)->gpuBindingLayout(); + GLES2GPUDescriptorSet *gpuDescriptorSet = ((GLES2DescriptorSet *)descriptorSet)->gpuDescriptorSet(); if (_curGPUDescriptorSets[set] != gpuDescriptorSet) { _curGPUDescriptorSets[set] = gpuDescriptorSet; _isStateInvalid = true; diff --git a/cocos/renderer/gfx-gles2/GLES2CommandBuffer.h b/cocos/renderer/gfx-gles2/GLES2CommandBuffer.h index 8a9805cd086..de4e2f2e16c 100644 --- a/cocos/renderer/gfx-gles2/GLES2CommandBuffer.h +++ b/cocos/renderer/gfx-gles2/GLES2CommandBuffer.h @@ -24,7 +24,7 @@ class CC_GLES2_API GLES2CommandBuffer : public CommandBuffer { virtual void beginRenderPass(RenderPass *renderPass, Framebuffer *fbo, const Rect &renderArea, const vector &colors, float depth, int stencil) override; virtual void endRenderPass() override; virtual void bindPipelineState(PipelineState *pso) override; - virtual void bindDescriptorSet(uint set, DescriptorSet *descriptorSet, uint dynamicOffsetCount, uint *dynamicOffsets) override; + virtual void bindDescriptorSet(uint set, DescriptorSet *descriptorSet, uint dynamicOffsetCount, const uint *dynamicOffsets) override; virtual void bindInputAssembler(InputAssembler *ia) override; virtual void setViewport(const Viewport &vp) override; virtual void setScissor(const Rect &rect) override; diff --git a/cocos/renderer/gfx-gles2/GLES2Commands.cc b/cocos/renderer/gfx-gles2/GLES2Commands.cc index a3d80233e26..7000dd6749f 100644 --- a/cocos/renderer/gfx-gles2/GLES2Commands.cc +++ b/cocos/renderer/gfx-gles2/GLES2Commands.cc @@ -1668,6 +1668,8 @@ void GLES2CmdFuncExecuteCmds(GLES2Device *device, GLES2CmdPackage *cmdPackage) { gpuDescriptor.gpuBufferView->offset + offset; } else if (gpuDescriptor.gpuBuffer) { uniformBuffBase = gpuDescriptor.gpuBuffer->buffer + offset; + } else { + continue; } for (size_t u = 0; u < glBlock.glActiveUniforms.size(); ++u) { diff --git a/cocos/renderer/gfx-gles2/GLES2DescriptorSet.cc b/cocos/renderer/gfx-gles2/GLES2DescriptorSet.cc index 30989da3e52..d5eba117620 100644 --- a/cocos/renderer/gfx-gles2/GLES2DescriptorSet.cc +++ b/cocos/renderer/gfx-gles2/GLES2DescriptorSet.cc @@ -27,10 +27,10 @@ bool GLES2DescriptorSet::initialize(const DescriptorSetInfo &info) { _textures.resize(descriptorCount); _samplers.resize(descriptorCount); - _gpuBindingLayout = CC_NEW(GLES2GPUDescriptorSet); - _gpuBindingLayout->gpuDescriptors.resize(descriptorCount); + _gpuDescriptorSet = CC_NEW(GLES2GPUDescriptorSet); + _gpuDescriptorSet->gpuDescriptors.resize(descriptorCount); for (size_t i = 0u; i < descriptorCount; i++) { - _gpuBindingLayout->gpuDescriptors[i].type = bindings[i].descriptorType; + _gpuDescriptorSet->gpuDescriptors[i].type = bindings[i].descriptorType; } _status = Status::SUCCESS; @@ -41,33 +41,37 @@ bool GLES2DescriptorSet::initialize(const DescriptorSetInfo &info) { void GLES2DescriptorSet::destroy() { _layout = nullptr; - if (_gpuBindingLayout) { - CC_DELETE(_gpuBindingLayout); - _gpuBindingLayout = nullptr; + if (_gpuDescriptorSet) { + CC_DELETE(_gpuDescriptorSet); + _gpuDescriptorSet = nullptr; } _status = Status::UNREADY; } void GLES2DescriptorSet::update() { - if (_isDirty && _gpuBindingLayout) { - const DescriptorSetLayoutBindingList &bindings = _layout->getBindings(); - for (size_t i = 0; i < bindings.size(); i++) { - if ((uint)bindings[i].descriptorType & DESCRIPTOR_BUFFER_TYPE) { + if (_isDirty && _gpuDescriptorSet) { + uint bindingCount = _gpuDescriptorSet->gpuDescriptors.size(); + + for (size_t i = 0; i < bindingCount; i++) { + GLES2GPUDescriptor &binding = _gpuDescriptorSet->gpuDescriptors[i]; + + if ((uint)binding.type & DESCRIPTOR_BUFFER_TYPE) { GLES2Buffer *buffer = (GLES2Buffer *)_buffers[i]; if (buffer) { if (buffer->gpuBuffer()) { - _gpuBindingLayout->gpuDescriptors[i].gpuBuffer = buffer->gpuBuffer(); + binding.gpuBuffer = buffer->gpuBuffer(); } else if (buffer->gpuBufferView()) { - _gpuBindingLayout->gpuDescriptors[i].gpuBufferView = buffer->gpuBufferView(); + binding.gpuBufferView = buffer->gpuBufferView(); } } - } else if ((uint)bindings[i].descriptorType & DESCRIPTOR_SAMPLER_TYPE) { + } + else if ((uint)binding.type & DESCRIPTOR_SAMPLER_TYPE) { if (_textures[i]) { - _gpuBindingLayout->gpuDescriptors[i].gpuTexture = ((GLES2Texture *)_textures[i])->gpuTexture(); + binding.gpuTexture = ((GLES2Texture *)_textures[i])->gpuTexture(); } if (_samplers[i]) { - _gpuBindingLayout->gpuDescriptors[i].gpuSampler = ((GLES2Sampler *)_samplers[i])->gpuSampler(); + binding.gpuSampler = ((GLES2Sampler *)_samplers[i])->gpuSampler(); } } } diff --git a/cocos/renderer/gfx-gles2/GLES2DescriptorSet.h b/cocos/renderer/gfx-gles2/GLES2DescriptorSet.h index f79f32d5407..42b5d5adec1 100644 --- a/cocos/renderer/gfx-gles2/GLES2DescriptorSet.h +++ b/cocos/renderer/gfx-gles2/GLES2DescriptorSet.h @@ -16,10 +16,10 @@ class CC_GLES2_API GLES2DescriptorSet : public DescriptorSet { virtual void destroy() override; virtual void update() override; - CC_INLINE GLES2GPUDescriptorSet *gpuBindingLayout() const { return _gpuBindingLayout; } + CC_INLINE GLES2GPUDescriptorSet *gpuDescriptorSet() const { return _gpuDescriptorSet; } private: - GLES2GPUDescriptorSet *_gpuBindingLayout = nullptr; + GLES2GPUDescriptorSet *_gpuDescriptorSet = nullptr; }; } // namespace gfx diff --git a/cocos/renderer/gfx-gles2/GLES2Texture.cc b/cocos/renderer/gfx-gles2/GLES2Texture.cc index 6f06da40b01..84520ba37d8 100644 --- a/cocos/renderer/gfx-gles2/GLES2Texture.cc +++ b/cocos/renderer/gfx-gles2/GLES2Texture.cc @@ -96,7 +96,7 @@ bool GLES2Texture::initialize(const TextureInfo &info) { } bool GLES2Texture::initialize(const TextureViewInfo &info) { - _Type = ObjectType::TEXTURE_VIEW; + _isTextureView = true; CC_LOG_ERROR("GLES2 doesn't support texture view"); _status = Status::FAILED; diff --git a/cocos/renderer/gfx-gles3/GLES3Buffer.h b/cocos/renderer/gfx-gles3/GLES3Buffer.h index 83470611159..6d474dff4d4 100644 --- a/cocos/renderer/gfx-gles3/GLES3Buffer.h +++ b/cocos/renderer/gfx-gles3/GLES3Buffer.h @@ -19,10 +19,8 @@ class CC_GLES3_API GLES3Buffer : public Buffer { virtual void update(void *buffer, uint offset, uint size) override; CC_INLINE GLES3GPUBuffer *gpuBuffer() const { return _gpuBuffer; } - CC_INLINE bool isBufferView() const { return _isBufferView; } private: - bool _isBufferView = false; GLES3GPUBuffer *_gpuBuffer = nullptr; }; diff --git a/cocos/renderer/gfx-gles3/GLES3CommandBuffer.cc b/cocos/renderer/gfx-gles3/GLES3CommandBuffer.cc index 0b2d017c7bf..a8f7ce2ba91 100644 --- a/cocos/renderer/gfx-gles3/GLES3CommandBuffer.cc +++ b/cocos/renderer/gfx-gles3/GLES3CommandBuffer.cc @@ -98,7 +98,7 @@ void GLES3CommandBuffer::bindPipelineState(PipelineState *pso) { } } -void GLES3CommandBuffer::bindDescriptorSet(uint set, DescriptorSet *descriptorSet, uint dynamicOffsetCount, uint *dynamicOffsets) { +void GLES3CommandBuffer::bindDescriptorSet(uint set, DescriptorSet *descriptorSet, uint dynamicOffsetCount, const uint *dynamicOffsets) { // these will break if using more sets than what's declared in DeviceInfo.bindingMappingInfo CCASSERT(_curGPUDescriptorSets.size() > set, ""); CCASSERT(_curDynamicOffsets.size() > set, ""); diff --git a/cocos/renderer/gfx-gles3/GLES3CommandBuffer.h b/cocos/renderer/gfx-gles3/GLES3CommandBuffer.h index 78082184588..1c951d0cf2e 100644 --- a/cocos/renderer/gfx-gles3/GLES3CommandBuffer.h +++ b/cocos/renderer/gfx-gles3/GLES3CommandBuffer.h @@ -24,7 +24,7 @@ class CC_GLES3_API GLES3CommandBuffer : public CommandBuffer { virtual void beginRenderPass(RenderPass *renderPass, Framebuffer *fbo, const Rect &renderArea, const vector &colors, float depth, int stencil) override; virtual void endRenderPass() override; virtual void bindPipelineState(PipelineState *pso) override; - virtual void bindDescriptorSet(uint set, DescriptorSet *descriptorSet, uint dynamicOffsetCount, uint *dynamicOffsets) override; + virtual void bindDescriptorSet(uint set, DescriptorSet *descriptorSet, uint dynamicOffsetCount, const uint *dynamicOffsets) override; virtual void bindInputAssembler(InputAssembler *ia) override; virtual void setViewport(const Viewport &vp) override; virtual void setScissor(const Rect &rect) override; diff --git a/cocos/renderer/gfx-gles3/GLES3Texture.cc b/cocos/renderer/gfx-gles3/GLES3Texture.cc index 7d261205080..898a3a122e1 100644 --- a/cocos/renderer/gfx-gles3/GLES3Texture.cc +++ b/cocos/renderer/gfx-gles3/GLES3Texture.cc @@ -97,7 +97,8 @@ bool GLES3Texture::initialize(const TextureInfo &info) { } bool GLES3Texture::initialize(const TextureViewInfo &info) { - _Type = ObjectType::TEXTURE_VIEW; + _isTextureView = true; + CC_LOG_ERROR("GLES3 doesn't support texture view."); _status = Status::FAILED; return false; diff --git a/cocos/renderer/gfx-vulkan/CMakeLists.txt b/cocos/renderer/gfx-vulkan/CMakeLists.txt index 4f4ffdb7a81..d916209a365 100644 --- a/cocos/renderer/gfx-vulkan/CMakeLists.txt +++ b/cocos/renderer/gfx-vulkan/CMakeLists.txt @@ -44,12 +44,6 @@ if(COCOS_PLATFORM_IOS OR COCOS_PLATFORM_OSX) set(ALL_FILES ${ALL_FILES} ${SOURCE_MM_FILES}) endif() -if(COCOS_PLATFORM_IOS OR COCOS_PLATFORM_OSX) - list(REMOVE_ITEM ALL_FILES "${COCOS_SRC_PATH}/renderer/gfx-vulkan/gles3w.c") -else() - list(REMOVE_ITEM ALL_FILES "${COCOS_SRC_PATH}/renderer/gfx-vulkan/gles3w.mm") -endif() - add_definitions("-DCC_VK_EXPORTS") if(WIN32) add_definitions("-DGLEW_BUILD") diff --git a/cocos/renderer/gfx-vulkan/VKBindingLayout.cc b/cocos/renderer/gfx-vulkan/VKBindingLayout.cc deleted file mode 100644 index 8cd41ec826f..00000000000 --- a/cocos/renderer/gfx-vulkan/VKBindingLayout.cc +++ /dev/null @@ -1,198 +0,0 @@ -#include "VKStd.h" - -#include "VKBindingLayout.h" -#include "VKBuffer.h" -#include "VKCommands.h" -#include "VKDevice.h" -#include "VKSampler.h" -#include "VKShader.h" -#include "VKTexture.h" - -namespace cc { -namespace gfx { - -CCVKBindingLayout::CCVKBindingLayout(Device *device) -: BindingLayout(device) { -} - -CCVKBindingLayout::~CCVKBindingLayout() { -} - -bool CCVKBindingLayout::initialize(const BindingLayoutInfo &info) { - - const CCVKGPUShader *gpuShader = ((CCVKShader *)info.shader)->gpuShader(); - const UniformBlockList &blocks = gpuShader->blocks; - const UniformSamplerList &samplers = gpuShader->samplers; - const uint bindingCount = blocks.size() + samplers.size(); - const uint descriptorCount = gpuShader->pipelineLayout->descriptorCounts[0]; - - if (bindingCount) { - _bindingUnits.resize(bindingCount); - for (size_t i = 0u; i < blocks.size(); ++i) { - const UniformBlock &binding = blocks[i]; - BindingUnit &bindingUnit = _bindingUnits[i]; - bindingUnit.shaderStages = binding.shaderStages; - bindingUnit.type = BindingType::UNIFORM_BUFFER; - bindingUnit.binding = binding.binding; - bindingUnit.name = binding.name; - bindingUnit.count = 1; - } - for (size_t i = 0u; i < samplers.size(); ++i) { - const UniformSampler &binding = samplers[i]; - BindingUnit &bindingUnit = _bindingUnits[blocks.size() + i]; - bindingUnit.shaderStages = binding.shaderStages; - bindingUnit.type = BindingType::SAMPLER; - bindingUnit.binding = binding.binding; - bindingUnit.name = binding.name; - bindingUnit.count = binding.count; - } - } - - _gpuBindingLayout = CC_NEW(CCVKGPUBindingLayout); - _gpuBindingLayout->gpuBindings.resize(1); - _gpuBindingLayout->descriptorSets.resize(1); - _gpuBindingLayout->gpuBindings[0].resize(bindingCount); - _gpuBindingLayout->descriptorInfos.resize(descriptorCount); - _gpuBindingLayout->descriptorIndices = &gpuShader->pipelineLayout->descriptorIndices; - - for (size_t i = blocks.size(); i < descriptorCount; ++i) { - _gpuBindingLayout->descriptorInfos[i].image.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - } - - if (!((CCVKDevice *)_device)->gpuDevice()->useDescriptorUpdateTemplate) { - vector &entries = _gpuBindingLayout->descriptorUpdateEntries; - entries.resize(descriptorCount, {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET}); - - for (size_t i = 0u, j = 0u; i < bindingCount; i++) { - BindingUnit &bindingUnit = _bindingUnits[i]; - // better not to assume that our descriptor layout will be contiguous - for (size_t k = 0u; k < bindingUnit.count; k++, j++) { - entries[j].dstBinding = bindingUnit.binding; - entries[j].dstArrayElement = k; - entries[j].descriptorCount = 1; - entries[j].descriptorType = MapVkDescriptorType(bindingUnit.type); - switch (entries[j].descriptorType) { - case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: - case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: - case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: - case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: - entries[j].pBufferInfo = &_gpuBindingLayout->descriptorInfos[j].buffer; - break; - case VK_DESCRIPTOR_TYPE_SAMPLER: - case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: - case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: - case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: - case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: - entries[j].pImageInfo = &_gpuBindingLayout->descriptorInfos[j].image; - break; - case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: - case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: - entries[j].pTexelBufferView = &_gpuBindingLayout->descriptorInfos[j].texelBufferView; - break; - default: break; - } - } - } - } - - _status = Status::SUCCESS; - - return true; -} - -void CCVKBindingLayout::destroy() { - if (_gpuBindingLayout) { - for (vector &bindings : _gpuBindingLayout->gpuBindings) { - for (uint i = 0u; i < bindings.size(); i++) { - CCVKGPUBinding &binding = bindings[i]; - const uint descriptorIndex = _gpuBindingLayout->descriptorIndices->at(0)[i]; - CCVKGPUDescriptorInfo &descriptorInfo = _gpuBindingLayout->descriptorInfos[descriptorIndex]; - CCVKGPUDescriptorHub *descriptorHub = ((CCVKDevice *)_device)->gpuDescriptorHub(); - if (binding.buffer) { - descriptorHub->disengage(binding.buffer, &descriptorInfo.buffer); - } - if (binding.texView) { - descriptorHub->disengage(binding.texView, &descriptorInfo.image); - } - if (binding.sampler) { - descriptorHub->disengage(binding.sampler, &descriptorInfo.image); - } - } - bindings.clear(); - } - _gpuBindingLayout->gpuBindings.clear(); - _gpuBindingLayout->descriptorInfos.clear(); - _gpuBindingLayout->descriptorSets.clear(); - _gpuBindingLayout->descriptorIndices = nullptr; - CC_DELETE(_gpuBindingLayout); - _gpuBindingLayout = nullptr; - } - - _status = Status::UNREADY; -} - -void CCVKBindingLayout::update() { - if (_isDirty && _gpuBindingLayout) { - CCVKGPUDescriptorHub *descriptorHub = ((CCVKDevice *)_device)->gpuDescriptorHub(); - for (size_t i = 0u; i < _bindingUnits.size(); ++i) { - BindingUnit &bindingUnit = _bindingUnits[i]; - CCVKGPUBinding &binding = _gpuBindingLayout->gpuBindings[0][i]; - const uint descriptorIndex = _gpuBindingLayout->descriptorIndices->at(0)[i]; - CCVKGPUDescriptorInfo &descriptorInfo = _gpuBindingLayout->descriptorInfos[descriptorIndex]; - switch (bindingUnit.type) { - case BindingType::UNIFORM_BUFFER: { - if (bindingUnit.buffer) { - CCVKGPUBuffer *buffer = ((CCVKBuffer *)bindingUnit.buffer)->gpuBuffer(); - if (binding.buffer != buffer) { - if (binding.buffer) { - descriptorHub->disengage(binding.buffer, &descriptorInfo.buffer); - } - if (buffer) { - descriptorHub->connect(buffer, &descriptorInfo.buffer); - descriptorHub->update(buffer, &descriptorInfo.buffer); - } - binding.buffer = buffer; - } - } - break; - } - case BindingType::SAMPLER: { - // TODO: handle texture arrays(need public interface changes) - if (bindingUnit.texture) { - CCVKGPUTextureView *texView = ((CCVKTexture *)bindingUnit.texture)->gpuTextureView(); - if (binding.texView != texView) { - if (binding.texView) { - descriptorHub->disengage(binding.texView, &descriptorInfo.image); - } - if (texView) { - descriptorHub->connect(texView, &descriptorInfo.image); - descriptorHub->update(texView, &descriptorInfo.image); - } - binding.texView = texView; - } - } - if (bindingUnit.sampler) { - CCVKGPUSampler *sampler = ((CCVKSampler *)bindingUnit.sampler)->gpuSampler(); - if (binding.sampler != sampler) { - if (binding.sampler) { - descriptorHub->disengage(binding.sampler, &descriptorInfo.image); - } - if (sampler) { - descriptorHub->connect(sampler, &descriptorInfo.image); - descriptorHub->update(sampler, &descriptorInfo.image); - } - binding.sampler = sampler; - } - } - break; - } - default: break; - } - } - - _isDirty = false; - } -} - -} // namespace gfx -} // namespace cc diff --git a/cocos/renderer/gfx-vulkan/VKBindingLayout.h b/cocos/renderer/gfx-vulkan/VKBindingLayout.h deleted file mode 100644 index b028b7121f7..00000000000 --- a/cocos/renderer/gfx-vulkan/VKBindingLayout.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef CC_GFXVULKAN_CCVK_BINDING_LAYOUT_H_ -#define CC_GFXVULKAN_CCVK_BINDING_LAYOUT_H_ - -namespace cc { -namespace gfx { - -class CCVKGPUBindingLayout; - -class CC_VULKAN_API CCVKBindingLayout : public BindingLayout { -public: - CCVKBindingLayout(Device *device); - ~CCVKBindingLayout(); - -public: - bool initialize(const BindingLayoutInfo &info); - void destroy(); - void update(); - - CC_INLINE CCVKGPUBindingLayout *gpuBindingLayout() const { return _gpuBindingLayout; } - -private: - CCVKGPUBindingLayout *_gpuBindingLayout = nullptr; -}; - -} // namespace gfx -} // namespace cc - -#endif diff --git a/cocos/renderer/gfx-vulkan/VKBuffer.cc b/cocos/renderer/gfx-vulkan/VKBuffer.cc index 8db03e9000f..0aad9a8c0e3 100644 --- a/cocos/renderer/gfx-vulkan/VKBuffer.cc +++ b/cocos/renderer/gfx-vulkan/VKBuffer.cc @@ -1,8 +1,8 @@ #include "VKStd.h" #include "VKBuffer.h" -#include "VKDevice.h" #include "VKCommands.h" +#include "VKDevice.h" namespace cc { namespace gfx { @@ -44,18 +44,54 @@ bool CCVKBuffer::initialize(const BufferInfo &info) { CCVKCmdFuncCreateBuffer((CCVKDevice *)_device, _gpuBuffer); _device->getMemoryStatus().bufferSize += _size; + + _gpuBufferView = CC_NEW(CCVKGPUBufferView); + createBufferView(); + _status = Status::SUCCESS; return true; } +bool CCVKBuffer::initialize(const BufferViewInfo &info) { + _isBufferView = true; + + CCVKBuffer *buffer = (CCVKBuffer *)info.buffer; + + _usage = buffer->_usage; + _memUsage = buffer->_memUsage; + _size = _stride = info.range; + _count = 1u; + _flags = buffer->_flags; + _offset = info.offset; + + _gpuBuffer = ((CCVKBuffer*)info.buffer)->gpuBuffer(); + _gpuBufferView = CC_NEW(CCVKGPUBufferView); + createBufferView(); + + return true; +} + +void CCVKBuffer::createBufferView() { + _gpuBufferView->gpuBuffer = _gpuBuffer; + _gpuBufferView->offset = _offset; + _gpuBufferView->range = _size; + ((CCVKDevice *)_device)->gpuDescriptorHub()->update(_gpuBufferView); +} + void CCVKBuffer::destroy() { - if (_gpuBuffer) { - ((CCVKDevice *)_device)->gpuDescriptorHub()->disengage(_gpuBuffer); - ((CCVKDevice *)_device)->gpuRecycleBin()->collect(_gpuBuffer); + if (_gpuBufferView) { + ((CCVKDevice *)_device)->gpuDescriptorHub()->disengage(_gpuBufferView); + CC_DELETE(_gpuBufferView); + _gpuBufferView = nullptr; + } - _device->getMemoryStatus().bufferSize -= _size; - CC_DELETE(_gpuBuffer); + if (_gpuBuffer) { + if (!_isBufferView) { + ((CCVKDevice *)_device)->gpuRecycleBin()->collect(_gpuBuffer); + _device->getMemoryStatus().bufferSize -= _size; + CC_DELETE(_gpuBuffer); + } _gpuBuffer = nullptr; } @@ -69,16 +105,22 @@ void CCVKBuffer::destroy() { } void CCVKBuffer::resize(uint size) { + CCASSERT(!_isBufferView, "Cannot resize buffer views"); + if (_size != size) { const uint oldSize = _size; _size = size; _count = _size / _stride; - MemoryStatus &status = _device->getMemoryStatus(); + ((CCVKDevice *)_device)->gpuRecycleBin()->collect(_gpuBuffer); + _gpuBuffer->size = _size; _gpuBuffer->count = _count; - ((CCVKDevice *)_device)->gpuRecycleBin()->collect(_gpuBuffer); CCVKCmdFuncCreateBuffer((CCVKDevice *)_device, _gpuBuffer); + + createBufferView(); + + MemoryStatus &status = _device->getMemoryStatus(); status.bufferSize -= oldSize; status.bufferSize += _size; @@ -102,6 +144,8 @@ void CCVKBuffer::resize(uint size) { } void CCVKBuffer::update(void *buffer, uint offset, uint size) { + CCASSERT(!_isBufferView, "Cannot update through buffer views"); + #if COCOS2D_DEBUG > 0 if (_usage & BufferUsageBit::INDIRECT) { DrawInfo *drawInfo = static_cast(buffer); @@ -115,6 +159,7 @@ void CCVKBuffer::update(void *buffer, uint offset, uint size) { } } #endif + if (_buffer) { memcpy(_buffer + offset, buffer, size); } diff --git a/cocos/renderer/gfx-vulkan/VKBuffer.h b/cocos/renderer/gfx-vulkan/VKBuffer.h index f02e9bb0f36..7a81556456c 100644 --- a/cocos/renderer/gfx-vulkan/VKBuffer.h +++ b/cocos/renderer/gfx-vulkan/VKBuffer.h @@ -5,6 +5,7 @@ namespace cc { namespace gfx { class CCVKGPUBuffer; +class CCVKGPUBufferView; class CC_VULKAN_API CCVKBuffer : public Buffer { public: @@ -13,14 +14,19 @@ class CC_VULKAN_API CCVKBuffer : public Buffer { public: bool initialize(const BufferInfo &info); + bool initialize(const BufferViewInfo &info); void destroy(); void resize(uint size); void update(void *buffer, uint offset, uint size); CC_INLINE CCVKGPUBuffer *gpuBuffer() const { return _gpuBuffer; } + CC_INLINE CCVKGPUBufferView *gpuBufferView() const { return _gpuBufferView; } private: + void createBufferView(); + CCVKGPUBuffer *_gpuBuffer = nullptr; + CCVKGPUBufferView *_gpuBufferView = nullptr; }; } // namespace gfx diff --git a/cocos/renderer/gfx-vulkan/VKCommandBuffer.cc b/cocos/renderer/gfx-vulkan/VKCommandBuffer.cc index f543e0eb50f..85a94c352cd 100644 --- a/cocos/renderer/gfx-vulkan/VKCommandBuffer.cc +++ b/cocos/renderer/gfx-vulkan/VKCommandBuffer.cc @@ -1,9 +1,9 @@ #include "VKStd.h" -#include "VKBindingLayout.h" #include "VKBuffer.h" #include "VKCommandBuffer.h" #include "VKCommands.h" +#include "VKDescriptorSet.h" #include "VKDevice.h" #include "VKFramebuffer.h" #include "VKInputAssembler.h" @@ -47,8 +47,12 @@ void CCVKCommandBuffer::destroy() { void CCVKCommandBuffer::begin(RenderPass *renderPass, uint subpass, Framebuffer *frameBuffer) { _curGPUPipelineState = nullptr; - _curGPUBindingLayout = nullptr; _curGPUInputAssember = nullptr; + _curGPUDescriptorSets.assign(_curGPUDescriptorSets.size(), nullptr); + for (size_t i = 0u; i < _curDynamicOffsets.size(); i++) { + _curDynamicOffsets[i].clear(); + } + _numDrawCalls = 0; _numInstances = 0; _numTriangles = 0; @@ -124,54 +128,49 @@ void CCVKCommandBuffer::bindPipelineState(PipelineState *pso) { if (_curGPUPipelineState != gpuPipelineState) { vkCmdBindPipeline(_gpuCommandBuffer->vkCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, gpuPipelineState->vkPipeline); _curGPUPipelineState = gpuPipelineState; + _curGPUDescriptorSets.resize(gpuPipelineState->gpuPipelineLayout->setLayouts.size()); } } -void CCVKCommandBuffer::bindBindingLayout(BindingLayout *layout) { +void CCVKCommandBuffer::bindDescriptorSet(uint set, DescriptorSet *descriptorSet, uint dynamicOffsetCount, const uint *dynamicOffsets) { if (!_curGPUPipelineState) { CC_LOG_ERROR("Command 'bindBindingLayout' must be recorded after 'bindPipelineState'."); return; } - CCVKGPUBindingLayout *gpuBindingLayout = ((CCVKBindingLayout *)layout)->gpuBindingLayout(); + CCVKGPUDescriptorSet *gpuDescriptorSet = ((CCVKDescriptorSet *)descriptorSet)->gpuDescriptorSet(); - if (_curGPUBindingLayout != gpuBindingLayout) { + CCVKDevice *device = (CCVKDevice *)_device; + CCVKGPUDevice *gpuDevice = device->gpuDevice(); + VkCommandBuffer cmdBuff = _gpuCommandBuffer->vkCommandBuffer; + CCVKGPUPipelineLayout *pipelineLayout = _curGPUPipelineState->gpuPipelineLayout; + vector &descriptorInfos = gpuDescriptorSet->descriptorInfos; - CCVKDevice *device = (CCVKDevice *)_device; - CCVKGPUDevice *gpuDevice = device->gpuDevice(); - VkCommandBuffer cmdBuff = _gpuCommandBuffer->vkCommandBuffer; - CCVKGPUPipelineLayout *pipelineLayout = _curGPUPipelineState->gpuShader->pipelineLayout; - vector &descriptorInfos = gpuBindingLayout->descriptorInfos; + if (gpuDevice->usePushDescriptorSet) { + vector &templates = pipelineLayout->vkDescriptorUpdateTemplates; + vkCmdPushDescriptorSetWithTemplateKHR(cmdBuff, templates[set], pipelineLayout->vkPipelineLayout, set, descriptorInfos.data()); + } else { + // TODO: update in batch + VkDescriptorSetLayout *layouts = &pipelineLayout->setLayouts[set]->vkDescriptorSetLayout; + VkDescriptorSet *sets = &gpuDescriptorSet->descriptorSet; - if (gpuDevice->usePushDescriptorSet) { - vector &templates = pipelineLayout->vkDescriptorUpdateTemplates; + device->gpuDescriptorSetPool()->alloc(layouts, sets, 1); - for (uint i = 0u; i < templates.size(); i++) { - vkCmdPushDescriptorSetWithTemplateKHR(cmdBuff, templates[i], pipelineLayout->vkPipelineLayout, i, descriptorInfos.data()); - } + if (gpuDevice->useDescriptorUpdateTemplate) { + vector &templates = pipelineLayout->vkDescriptorUpdateTemplates; + vkUpdateDescriptorSetWithTemplateKHR(device->gpuDevice()->vkDevice, sets[0], templates[set], descriptorInfos.data()); } else { - vector &layouts = pipelineLayout->vkDescriptorSetLayouts; - vector &sets = gpuBindingLayout->descriptorSets; - - device->gpuDescriptorSetPool()->alloc(layouts.data(), sets.data(), layouts.size()); + vector &entries = gpuDescriptorSet->descriptorUpdateEntries; - if (gpuDevice->useDescriptorUpdateTemplate) { - vector &templates = pipelineLayout->vkDescriptorUpdateTemplates; - - for (uint i = 0u; i < templates.size(); i++) { - vkUpdateDescriptorSetWithTemplateKHR(device->gpuDevice()->vkDevice, sets[i], templates[i], descriptorInfos.data()); - } - } else { - vector &entries = gpuBindingLayout->descriptorUpdateEntries; - - for (uint j = 0u; j < entries.size(); j++) { - entries[j].dstSet = sets[0]; - } - vkUpdateDescriptorSets(device->gpuDevice()->vkDevice, entries.size(), entries.data(), 0, nullptr); + for (uint j = 0u; j < entries.size(); j++) { + entries[j].dstSet = sets[0]; } - vkCmdBindDescriptorSets(cmdBuff, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout->vkPipelineLayout, 0, layouts.size(), sets.data(), 0, nullptr); + vkUpdateDescriptorSets(device->gpuDevice()->vkDevice, entries.size(), entries.data(), 0, nullptr); } - _curGPUBindingLayout = gpuBindingLayout; + vkCmdBindDescriptorSets(cmdBuff, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout->vkPipelineLayout, + 0, 1, sets, dynamicOffsetCount, dynamicOffsets); + + _curGPUDescriptorSets[set] = gpuDescriptorSet; } } diff --git a/cocos/renderer/gfx-vulkan/VKCommandBuffer.h b/cocos/renderer/gfx-vulkan/VKCommandBuffer.h index 47463e0218c..d590e2baa96 100644 --- a/cocos/renderer/gfx-vulkan/VKCommandBuffer.h +++ b/cocos/renderer/gfx-vulkan/VKCommandBuffer.h @@ -14,28 +14,28 @@ class CC_VULKAN_API CCVKCommandBuffer : public CommandBuffer { friend class CCVKQueue; public: - bool initialize(const CommandBufferInfo &info); - void destroy(); - - void begin(RenderPass *renderPass = nullptr, uint subpass = 0, Framebuffer *frameBuffer = nullptr); - void end(); - void beginRenderPass(RenderPass *renderPass, Framebuffer *fbo, const Rect &renderArea, const vector &colors, float depth, int stencil); - void endRenderPass(); - void bindPipelineState(PipelineState *pso); - void bindBindingLayout(BindingLayout *layout); - void bindInputAssembler(InputAssembler *ia); - void setViewport(const Viewport &vp); - void setScissor(const Rect &rect); - void setLineWidth(const float width); - void setDepthBias(float constant, float clamp, float slope); - void setBlendConstants(const Color &constants); - void setDepthBound(float min_bounds, float max_bounds); - void setStencilWriteMask(StencilFace face, uint mask); - void setStencilCompareMask(StencilFace face, int reference, uint mask); - void draw(InputAssembler *ia); - void updateBuffer(Buffer *buff, void *data, uint size, uint offset); - void copyBuffersToTexture(const BufferDataList &buffers, Texture *texture, const BufferTextureCopyList ®ions); - void execute(const CommandBufferList &cmd_buffs, uint count); + virtual bool initialize(const CommandBufferInfo &info) override; + virtual void destroy() override; + + virtual void begin(RenderPass *renderPass = nullptr, uint subpass = 0, Framebuffer *frameBuffer = nullptr) override; + virtual void end() override; + virtual void beginRenderPass(RenderPass *renderPass, Framebuffer *fbo, const Rect &renderArea, const vector &colors, float depth, int stencil) override; + virtual void endRenderPass() override; + virtual void bindPipelineState(PipelineState *pso) override; + virtual void bindDescriptorSet(uint set, DescriptorSet *descriptorSet, uint dynamicOffsetCount, const uint *dynamicOffsets) override; + virtual void bindInputAssembler(InputAssembler *ia) override; + virtual void setViewport(const Viewport &vp) override; + virtual void setScissor(const Rect &rect) override; + virtual void setLineWidth(const float width) override; + virtual void setDepthBias(float constant, float clamp, float slope) override; + virtual void setBlendConstants(const Color &constants) override; + virtual void setDepthBound(float min_bounds, float max_bounds) override; + virtual void setStencilWriteMask(StencilFace face, uint mask) override; + virtual void setStencilCompareMask(StencilFace face, int reference, uint mask) override; + virtual void draw(InputAssembler *ia) override; + virtual void updateBuffer(Buffer *buff, void *data, uint size, uint offset) override; + virtual void copyBuffersToTexture(const BufferDataList &buffers, Texture *texture, const BufferTextureCopyList ®ions) override; + virtual void execute(const CommandBufferList &cmd_buffs, uint count) override; CCVKGPUCommandBuffer *gpuCommandBuffer() const { return _gpuCommandBuffer; } @@ -43,7 +43,8 @@ class CC_VULKAN_API CCVKCommandBuffer : public CommandBuffer { CCVKGPUCommandBuffer *_gpuCommandBuffer = nullptr; CCVKGPUPipelineState *_curGPUPipelineState = nullptr; - CCVKGPUBindingLayout *_curGPUBindingLayout = nullptr; + vector _curGPUDescriptorSets; + vector> _curDynamicOffsets; CCVKGPUInputAssembler *_curGPUInputAssember = nullptr; CCVKGPUFramebuffer *_curGPUFBO = nullptr; diff --git a/cocos/renderer/gfx-vulkan/VKCommands.cc b/cocos/renderer/gfx-vulkan/VKCommands.cc index eb1b4771d23..481109d3839 100644 --- a/cocos/renderer/gfx-vulkan/VKCommands.cc +++ b/cocos/renderer/gfx-vulkan/VKCommands.cc @@ -175,8 +175,6 @@ void CCVKCmdFuncCreateBuffer(CCVKDevice *device, CCVKGPUBuffer *gpuBuffer) { gpuBuffer->mappedData = (uint8_t *)res.pMappedData; gpuBuffer->startOffset = 0; // we are creating one VkBuffer each for now - - device->gpuDescriptorHub()->update(gpuBuffer); } void CCVKCmdFuncCreateRenderPass(CCVKDevice *device, CCVKGPURenderPass *gpuRenderPass) { @@ -316,117 +314,93 @@ void CCVKCmdFuncCreateFramebuffer(CCVKDevice *device, CCVKGPUFramebuffer *gpuFra } } -void CCVKGPUPipelineLayoutPool::request(CCVKGPUShader *gpuShader) { - const UniformBlockList &blocks = gpuShader->blocks; - const UniformSamplerList &samplers = gpuShader->samplers; - const uint bindingCount = blocks.size() + samplers.size(); - - uint seed = bindingCount; - for (size_t i = 0u; i < blocks.size(); i++) { - const UniformBlock &block = blocks[i]; - uint hash = block.binding | ((uint)block.shaderStages << 16); - seed ^= hash + 0x9e3779b9 + (seed << 6) + (seed >> 2); - } - for (size_t i = 0u; i < samplers.size(); i++) { - const UniformSampler sampler = samplers[i]; - uint hash = sampler.binding | ((uint)sampler.shaderStages << 16) | (sampler.count << 22); - seed ^= hash + 0x9e3779b9 + (seed << 6) + (seed >> 2); +void CCVKCmdFuncCreateShader(CCVKDevice *device, CCVKGPUShader *gpuShader) { + for (CCVKGPUShaderStage &stage : gpuShader->gpuStages) { + vector spirv = GLSL2SPIRV(stage.type, "#version 450\n" + stage.source, ((CCVKContext *)device->getContext())->minorVersion()); + VkShaderModuleCreateInfo createInfo{VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO}; + createInfo.codeSize = spirv.size() * sizeof(unsigned int); + createInfo.pCode = spirv.data(); + VK_CHECK(vkCreateShaderModule(device->gpuDevice()->vkDevice, &createInfo, nullptr, &stage.vkShader)); } + CC_LOG_INFO("Shader '%s' compilation succeeded.", gpuShader->name.c_str()); +} - if (_pool.count(seed)) { - gpuShader->pipelineLayout = &_pool[seed]; - return; - } +void CCVKCmdFuncCreateDescriptorSetLayout(CCVKDevice *device, CCVKGPUDescriptorSetLayout *gpuDescriptorSetLayout) { + CCVKGPUDevice *gpuDevice = device->gpuDevice(); + size_t bindingCount = gpuDescriptorSetLayout->bindings.size(); - _pool.emplace(std::piecewise_construct, std::forward_as_tuple(seed), std::forward_as_tuple()); - - CCVKGPUPipelineLayout &pipelineLayout = _pool[seed]; - - pipelineLayout.vkDescriptorSetLayouts.resize(1); - pipelineLayout.descriptorCounts.resize(1); - pipelineLayout.descriptorIndices.resize(1); - pipelineLayout.descriptorIndices[0].resize(bindingCount); - - vector setBindings(bindingCount); - for (size_t i = 0u; i < blocks.size(); i++) { - const UniformBlock &binding = blocks[i]; - VkDescriptorSetLayoutBinding &setBinding = setBindings[i]; - setBinding.stageFlags = MapVkShaderStageFlags(binding.shaderStages); - setBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - setBinding.binding = binding.binding; - setBinding.descriptorCount = 1; // the effect compiler guarantees this to be non-array - pipelineLayout.descriptorIndices[0][i] = i; - } - uint descriptorCount = blocks.size(); - for (size_t i = 0u; i < samplers.size(); i++) { - const UniformSampler &binding = samplers[i]; - VkDescriptorSetLayoutBinding &setBinding = setBindings[blocks.size() + i]; - setBinding.stageFlags = MapVkShaderStageFlags(binding.shaderStages); - setBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - setBinding.binding = binding.binding; - setBinding.descriptorCount = binding.count; - pipelineLayout.descriptorIndices[0][blocks.size() + i] = descriptorCount; + uint descriptorCount = 0u; + gpuDescriptorSetLayout->vkBindings.resize(bindingCount); + gpuDescriptorSetLayout->descriptorIndices.resize(bindingCount); + for (size_t i = 0u; i < bindingCount; i++) { + const DescriptorSetLayoutBinding &binding = gpuDescriptorSetLayout->bindings[i]; + VkDescriptorSetLayoutBinding &vkBinding = gpuDescriptorSetLayout->vkBindings[i]; + vkBinding.stageFlags = MapVkShaderStageFlags(binding.stageFlags); + vkBinding.descriptorType = MapVkDescriptorType(binding.descriptorType); + vkBinding.binding = i; + vkBinding.descriptorCount = binding.count; + gpuDescriptorSetLayout->descriptorIndices[i] = descriptorCount; descriptorCount += binding.count; } - pipelineLayout.descriptorCounts[0] = descriptorCount; + gpuDescriptorSetLayout->descriptorCount = descriptorCount; VkDescriptorSetLayoutCreateInfo setCreateInfo{VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO}; - if (_device->usePushDescriptorSet) setCreateInfo.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR; + if (gpuDevice->usePushDescriptorSet) setCreateInfo.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR; setCreateInfo.bindingCount = bindingCount; - setCreateInfo.pBindings = setBindings.data(); - VK_CHECK(vkCreateDescriptorSetLayout(_device->vkDevice, &setCreateInfo, nullptr, &pipelineLayout.vkDescriptorSetLayouts[0])); + setCreateInfo.pBindings = gpuDescriptorSetLayout->vkBindings.data(); + VK_CHECK(vkCreateDescriptorSetLayout(gpuDevice->vkDevice, &setCreateInfo, nullptr, &gpuDescriptorSetLayout->vkDescriptorSetLayout)); +} - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo{VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO}; - pipelineLayoutCreateInfo.setLayoutCount = pipelineLayout.vkDescriptorSetLayouts.size(); - pipelineLayoutCreateInfo.pSetLayouts = pipelineLayout.vkDescriptorSetLayouts.data(); - VK_CHECK(vkCreatePipelineLayout(_device->vkDevice, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout.vkPipelineLayout)); - - if (_device->useDescriptorUpdateTemplate) { - pipelineLayout.vkDescriptorUpdateTemplates.resize(1); - - vector entries(bindingCount); - for (size_t i = 0u, j = 0u; i < bindingCount; i++) { - VkDescriptorSetLayoutBinding &binding = setBindings[i]; - if (binding.descriptorType != VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) { - entries[i].dstBinding = binding.binding; - entries[i].dstArrayElement = 0; - entries[i].descriptorCount = binding.descriptorCount; - entries[i].descriptorType = binding.descriptorType; - entries[i].offset = sizeof(CCVKGPUDescriptorInfo) * j; - entries[i].stride = sizeof(CCVKGPUDescriptorInfo); - j += binding.descriptorCount; - } // TODO: inline UBOs - } +void CCVKCmdFuncCreatePipelineLayout(CCVKDevice *device, CCVKGPUPipelineLayout *gpuPipelineLayout) { + CCVKGPUDevice *gpuDevice = device->gpuDevice(); + size_t layoutCount = gpuPipelineLayout->setLayouts.size(); - VkDescriptorUpdateTemplateCreateInfo createInfo = {VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO}; - createInfo.descriptorUpdateEntryCount = bindingCount; - createInfo.pDescriptorUpdateEntries = entries.data(); - if (_device->usePushDescriptorSet) { - createInfo.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR; - createInfo.descriptorSetLayout = VK_NULL_HANDLE; - } else { - createInfo.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET; - createInfo.descriptorSetLayout = pipelineLayout.vkDescriptorSetLayouts[0]; - } - createInfo.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - createInfo.pipelineLayout = pipelineLayout.vkPipelineLayout; - VK_CHECK(vkCreateDescriptorUpdateTemplateKHR(_device->vkDevice, &createInfo, nullptr, &pipelineLayout.vkDescriptorUpdateTemplates[0])); + vector layouts(layoutCount); + for (uint i = 0; i < layoutCount; i++) { + layouts[i] = gpuPipelineLayout->setLayouts[i]->vkDescriptorSetLayout; } - gpuShader->pipelineLayout = &pipelineLayout; -} + VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo{VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO}; + pipelineLayoutCreateInfo.setLayoutCount = layoutCount; + pipelineLayoutCreateInfo.pSetLayouts = layouts.data(); + VK_CHECK(vkCreatePipelineLayout(gpuDevice->vkDevice, &pipelineLayoutCreateInfo, nullptr, &gpuPipelineLayout->vkPipelineLayout)); + + if (gpuDevice->useDescriptorUpdateTemplate) { + gpuPipelineLayout->vkDescriptorUpdateTemplates.resize(layoutCount); + + for (uint i = 0; i < layoutCount; i++) { + const vector &bindings = gpuPipelineLayout->setLayouts[i]->vkBindings; + uint bindingCount = bindings.size(); + + vector entries(bindingCount); + for (size_t j = 0u, k = 0u; j < bindingCount; j++) { + const VkDescriptorSetLayoutBinding &binding = bindings[j]; + if (binding.descriptorType != VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) { + entries[j].dstBinding = binding.binding; + entries[j].dstArrayElement = 0; + entries[j].descriptorCount = binding.descriptorCount; + entries[j].descriptorType = binding.descriptorType; + entries[j].offset = sizeof(CCVKDescriptorInfo) * k; + entries[j].stride = sizeof(CCVKDescriptorInfo); + k += binding.descriptorCount; + } // TODO: inline UBOs + } -void CCVKCmdFuncCreateShader(CCVKDevice *device, CCVKGPUShader *gpuShader) { - for (CCVKGPUShaderStage &stage : gpuShader->gpuStages) { - vector spirv = GLSL2SPIRV(stage.type, "#version 450\n" + stage.source, ((CCVKContext *)device->getContext())->minorVersion()); - VkShaderModuleCreateInfo createInfo{VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO}; - createInfo.codeSize = spirv.size() * sizeof(unsigned int); - createInfo.pCode = spirv.data(); - VK_CHECK(vkCreateShaderModule(device->gpuDevice()->vkDevice, &createInfo, nullptr, &stage.vkShader)); + VkDescriptorUpdateTemplateCreateInfo createInfo = {VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO}; + createInfo.descriptorUpdateEntryCount = bindingCount; + createInfo.pDescriptorUpdateEntries = entries.data(); + if (gpuDevice->usePushDescriptorSet) { + createInfo.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR; + createInfo.descriptorSetLayout = VK_NULL_HANDLE; + } else { + createInfo.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET; + createInfo.descriptorSetLayout = gpuPipelineLayout->setLayouts[i]->vkDescriptorSetLayout; + } + createInfo.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + createInfo.pipelineLayout = gpuPipelineLayout->vkPipelineLayout; + VK_CHECK(vkCreateDescriptorUpdateTemplateKHR(gpuDevice->vkDevice, &createInfo, nullptr, &gpuPipelineLayout->vkDescriptorUpdateTemplates[i])); + } } - CC_LOG_INFO("Shader '%s' compilation succeeded.", gpuShader->name.c_str()); - - device->gpuPipelineLayoutPool()->request(gpuShader); } void CCVKCmdFuncCreatePipelineState(CCVKDevice *device, CCVKGPUPipelineState *gpuPipelineState) { @@ -613,7 +587,7 @@ void CCVKCmdFuncCreatePipelineState(CCVKDevice *device, CCVKGPUPipelineState *gp ///////////////////// References ///////////////////// - createInfo.layout = gpuPipelineState->gpuShader->pipelineLayout->vkPipelineLayout; + createInfo.layout = gpuPipelineState->gpuPipelineLayout->vkPipelineLayout; createInfo.renderPass = gpuPipelineState->gpuRenderPass->vkRenderPass; ///////////////////// Creation ///////////////////// @@ -831,7 +805,6 @@ void CCVKCmdFuncDestroyShader(CCVKGPUDevice *gpuDevice, CCVKGPUShader *gpuShader vkDestroyShaderModule(gpuDevice->vkDevice, stage.vkShader, nullptr); stage.vkShader = VK_NULL_HANDLE; } - gpuShader->pipelineLayout = nullptr; } void CCVKCmdFuncDestroyFramebuffer(CCVKGPUDevice *gpuDevice, CCVKGPUFramebuffer *gpuFramebuffer) { @@ -853,6 +826,25 @@ void CCVKCmdFuncDestroyFramebuffer(CCVKGPUDevice *gpuDevice, CCVKGPUFramebuffer } } +void CCVKCmdFuncDestroyDescriptorSetLayout(CCVKGPUDevice *gpuDevice, CCVKGPUDescriptorSetLayout *gpuDescriptorSetLayout) { + if (gpuDescriptorSetLayout->vkDescriptorSetLayout != VK_NULL_HANDLE) { + vkDestroyDescriptorSetLayout(gpuDevice->vkDevice, gpuDescriptorSetLayout->vkDescriptorSetLayout, nullptr); + gpuDescriptorSetLayout->vkDescriptorSetLayout = VK_NULL_HANDLE; + } +} + +void CCVKCmdFuncDestroyPipelineLayout(CCVKGPUDevice *gpuDevice, CCVKGPUPipelineLayout *gpuPipelineLayout) { + for (VkDescriptorUpdateTemplate updateTemplate : gpuPipelineLayout->vkDescriptorUpdateTemplates) { + vkDestroyDescriptorUpdateTemplateKHR(gpuDevice->vkDevice, updateTemplate, nullptr); + } + gpuPipelineLayout->vkDescriptorUpdateTemplates.clear(); + + if (gpuPipelineLayout->vkPipelineLayout != VK_NULL_HANDLE) { + vkDestroyPipelineLayout(gpuDevice->vkDevice, gpuPipelineLayout->vkPipelineLayout, nullptr); + gpuPipelineLayout->vkPipelineLayout = VK_NULL_HANDLE; + } +} + void CCVKCmdFuncDestroyPipelineState(CCVKGPUDevice *gpuDevice, CCVKGPUPipelineState *gpuPipelineState) { if (gpuPipelineState->vkPipeline != VK_NULL_HANDLE) { vkDestroyPipeline(gpuDevice->vkDevice, gpuPipelineState->vkPipeline, nullptr); @@ -871,62 +863,76 @@ void CCVKGPURecycleBin::clear() { for (uint i = 0u; i < _count; i++) { Resource &res = _resources[i]; switch (res.type) { - case ObjectType::BUFFER: + case RecycledType::BUFFER: if (res.buffer.vkBuffer) { vmaDestroyBuffer(_device->memoryAllocator, res.buffer.vkBuffer, res.buffer.vmaAllocation); res.buffer.vkBuffer = VK_NULL_HANDLE; res.buffer.vmaAllocation = VK_NULL_HANDLE; } break; - case ObjectType::TEXTURE: + case RecycledType::TEXTURE: if (res.image.vkImage) { vmaDestroyImage(_device->memoryAllocator, res.image.vkImage, res.image.vmaAllocation); res.image.vkImage = VK_NULL_HANDLE; res.image.vmaAllocation = VK_NULL_HANDLE; } break; - case ObjectType::TEXTURE_VIEW: + case RecycledType::TEXTURE_VIEW: if (res.vkImageView) { vkDestroyImageView(_device->vkDevice, res.vkImageView, nullptr); res.vkImageView = VK_NULL_HANDLE; } break; - case ObjectType::RENDER_PASS: + case RecycledType::RENDER_PASS: if (res.gpuRenderPass) { CCVKCmdFuncDestroyRenderPass(_device, res.gpuRenderPass); CC_DELETE(res.gpuRenderPass); res.gpuRenderPass = nullptr; } break; - case ObjectType::FRAMEBUFFER: + case RecycledType::FRAMEBUFFER: if (res.gpuFramebuffer) { CCVKCmdFuncDestroyFramebuffer(_device, res.gpuFramebuffer); CC_DELETE(res.gpuFramebuffer); res.gpuFramebuffer = nullptr; } break; - case ObjectType::SAMPLER: + case RecycledType::SAMPLER: if (res.gpuSampler) { CCVKCmdFuncDestroySampler(_device, res.gpuSampler); CC_DELETE(res.gpuSampler); res.gpuSampler = nullptr; } break; - case ObjectType::SHADER: + case RecycledType::SHADER: if (res.gpuShader) { CCVKCmdFuncDestroyShader(_device, res.gpuShader); CC_DELETE(res.gpuShader); res.gpuShader = nullptr; } break; - case ObjectType::PIPELINE_STATE: + case RecycledType::DESCRIPTOR_SET_LAYOUT: + if (res.gpuDescriptorSetLayout) { + CCVKCmdFuncDestroyDescriptorSetLayout(_device, res.gpuDescriptorSetLayout); + CC_DELETE(res.gpuDescriptorSetLayout); + res.gpuDescriptorSetLayout = nullptr; + } + break; + case RecycledType::PIPELINE_LAYOUT: + if (res.gpuPipelineLayout) { + CCVKCmdFuncDestroyPipelineLayout(_device, res.gpuPipelineLayout); + CC_DELETE(res.gpuPipelineLayout); + res.gpuPipelineLayout = nullptr; + } + break; + case RecycledType::PIPELINE_STATE: if (res.gpuPipelineState) { CCVKCmdFuncDestroyPipelineState(_device, res.gpuPipelineState); CC_DELETE(res.gpuPipelineState); res.gpuPipelineState = nullptr; } break; - case ObjectType::FENCE: + case RecycledType::FENCE: if (res.gpuFence) { CCVKCmdFuncDestroyFence(_device, res.gpuFence); CC_DELETE(res.gpuFence); @@ -935,7 +941,7 @@ void CCVKGPURecycleBin::clear() { break; default: break; } - res.type = ObjectType::UNKNOWN; + res.type = RecycledType::UNKNOWN; } _count = 0; } diff --git a/cocos/renderer/gfx-vulkan/VKCommands.h b/cocos/renderer/gfx-vulkan/VKCommands.h index 62e6ba0a04a..e9224e1a4b3 100644 --- a/cocos/renderer/gfx-vulkan/VKCommands.h +++ b/cocos/renderer/gfx-vulkan/VKCommands.h @@ -39,6 +39,8 @@ CC_VULKAN_API void CCVKCmdFuncCreateBuffer(CCVKDevice *device, CCVKGPUBuffer *gp CC_VULKAN_API void CCVKCmdFuncCreateRenderPass(CCVKDevice *device, CCVKGPURenderPass *gpuRenderPass); CC_VULKAN_API void CCVKCmdFuncCreateFramebuffer(CCVKDevice *device, CCVKGPUFramebuffer *gpuFramebuffer); CC_VULKAN_API void CCVKCmdFuncCreateShader(CCVKDevice *device, CCVKGPUShader *gpuShader); +CC_VULKAN_API void CCVKCmdFuncCreateDescriptorSetLayout(CCVKDevice *device, CCVKGPUDescriptorSetLayout *gpuDescriptorSetLayout); +CC_VULKAN_API void CCVKCmdFuncCreatePipelineLayout(CCVKDevice *device, CCVKGPUPipelineLayout *gpuPipelineLayout); CC_VULKAN_API void CCVKCmdFuncCreatePipelineState(CCVKDevice *device, CCVKGPUPipelineState *gpuPipelineState); CC_VULKAN_API void CCVKCmdFuncCreateFence(CCVKDevice *device, CCVKGPUFence *gpuFence); @@ -49,6 +51,8 @@ CC_VULKAN_API void CCVKCmdFuncDestroyRenderPass(CCVKGPUDevice *device, CCVKGPURe CC_VULKAN_API void CCVKCmdFuncDestroySampler(CCVKGPUDevice *device, CCVKGPUSampler *gpuSampler); CC_VULKAN_API void CCVKCmdFuncDestroyShader(CCVKGPUDevice *device, CCVKGPUShader *gpuShader); CC_VULKAN_API void CCVKCmdFuncDestroyFramebuffer(CCVKGPUDevice *device, CCVKGPUFramebuffer *gpuFramebuffer); +CC_VULKAN_API void CCVKCmdFuncDestroyDescriptorSetLayout(CCVKGPUDevice *device, CCVKGPUDescriptorSetLayout *gpuDescriptorSetLayout); +CC_VULKAN_API void CCVKCmdFuncDestroyPipelineLayout(CCVKGPUDevice *device, CCVKGPUPipelineLayout *gpuPipelineLayout); CC_VULKAN_API void CCVKCmdFuncDestroyPipelineState(CCVKGPUDevice *device, CCVKGPUPipelineState *gpuPipelineState); CC_VULKAN_API void CCVKCmdFuncDestroyFence(CCVKGPUDevice *device, CCVKGPUFence *gpuFence); diff --git a/cocos/renderer/gfx-vulkan/VKDescriptorSet.cc b/cocos/renderer/gfx-vulkan/VKDescriptorSet.cc new file mode 100644 index 00000000000..252cac4c79d --- /dev/null +++ b/cocos/renderer/gfx-vulkan/VKDescriptorSet.cc @@ -0,0 +1,170 @@ +#include "VKStd.h" + +#include "VKBuffer.h" +#include "VKCommands.h" +#include "VKDescriptorSet.h" +#include "VKDescriptorSetLayout.h" +#include "VKDevice.h" +#include "VKSampler.h" +#include "VKShader.h" +#include "VKTexture.h" + +namespace cc { +namespace gfx { + +CCVKDescriptorSet::CCVKDescriptorSet(Device *device) +: DescriptorSet(device) { +} + +CCVKDescriptorSet::~CCVKDescriptorSet() { +} + +bool CCVKDescriptorSet::initialize(const DescriptorSetInfo &info) { + + _layout = info.layout; + + const CCVKGPUDescriptorSetLayout *gpuDescriptorSetLayout = ((CCVKDescriptorSetLayout *)_layout)->gpuDescriptorSetLayout(); + const uint bindingCount = gpuDescriptorSetLayout->bindings.size(); + const uint descriptorCount = gpuDescriptorSetLayout->descriptorCount; + + _buffers.resize(bindingCount); + _textures.resize(bindingCount); + _samplers.resize(bindingCount); + + _gpuDescriptorSet = CC_NEW(CCVKGPUDescriptorSet); + _gpuDescriptorSet->gpuDescriptors.resize(bindingCount); + _gpuDescriptorSet->descriptorInfos.resize(bindingCount); + for (size_t i = 0u; i < bindingCount; i++) { + DescriptorSetLayoutBinding binding = gpuDescriptorSetLayout->bindings[i]; + _gpuDescriptorSet->gpuDescriptors[i].type = binding.descriptorType; + if ((uint)binding.descriptorType & DESCRIPTOR_SAMPLER_TYPE) { + _gpuDescriptorSet->descriptorInfos[i].image.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + } + } + + if (!((CCVKDevice *)_device)->gpuDevice()->useDescriptorUpdateTemplate) { + vector &entries = _gpuDescriptorSet->descriptorUpdateEntries; + entries.resize(descriptorCount, {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET}); + + for (size_t i = 0u, j = 0u; i < bindingCount; i++) { + const VkDescriptorSetLayoutBinding &descriptor = gpuDescriptorSetLayout->vkBindings[i]; + for (size_t k = 0u; k < descriptor.descriptorCount; k++, j++) { + entries[j].dstBinding = descriptor.binding; + entries[j].dstArrayElement = k; + entries[j].descriptorCount = 1; + entries[j].descriptorType = descriptor.descriptorType; + switch (entries[j].descriptorType) { + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: + entries[j].pBufferInfo = &_gpuDescriptorSet->descriptorInfos[j].buffer; + break; + case VK_DESCRIPTOR_TYPE_SAMPLER: + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: + case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: + entries[j].pImageInfo = &_gpuDescriptorSet->descriptorInfos[j].image; + break; + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + entries[j].pTexelBufferView = &_gpuDescriptorSet->descriptorInfos[j].texelBufferView; + break; + default: break; + } + } + } + } + + _status = Status::SUCCESS; + + return true; +} + +void CCVKDescriptorSet::destroy() { + if (_gpuDescriptorSet) { + CCVKGPUDescriptorHub *descriptorHub = ((CCVKDevice *)_device)->gpuDescriptorHub(); + const vector &indicies = ((CCVKDescriptorSetLayout *)_layout)->gpuDescriptorSetLayout()->descriptorIndices; + + for (uint i = 0u; i < _gpuDescriptorSet->gpuDescriptors.size(); i++) { + CCVKGPUDescriptor &binding = _gpuDescriptorSet->gpuDescriptors[i]; + const uint descriptorIndex = indicies[i]; + CCVKDescriptorInfo &descriptorInfo = _gpuDescriptorSet->descriptorInfos[descriptorIndex]; + if (binding.gpuBufferView) { + descriptorHub->disengage(binding.gpuBufferView, &descriptorInfo.buffer); + } + if (binding.gpuTextureView) { + descriptorHub->disengage(binding.gpuTextureView, &descriptorInfo.image); + } + if (binding.gpuSampler) { + descriptorHub->disengage(binding.gpuSampler, &descriptorInfo.image); + } + } + CC_DELETE(_gpuDescriptorSet); + _gpuDescriptorSet = nullptr; + } + + _status = Status::UNREADY; +} + +void CCVKDescriptorSet::update() { + if (_isDirty && _gpuDescriptorSet) { + CCVKGPUDescriptorHub *descriptorHub = ((CCVKDevice *)_device)->gpuDescriptorHub(); + const vector &indicies = ((CCVKDescriptorSetLayout *)_layout)->gpuDescriptorSetLayout()->descriptorIndices; + uint bindingCount = _gpuDescriptorSet->gpuDescriptors.size(); + + for (size_t i = 0u; i < bindingCount; i++) { + CCVKDescriptorInfo &descriptorInfo = _gpuDescriptorSet->descriptorInfos[indicies[i]]; + CCVKGPUDescriptor &binding = _gpuDescriptorSet->gpuDescriptors[i]; + + if ((uint)binding.type & DESCRIPTOR_BUFFER_TYPE) { + if (_buffers[i]) { + CCVKGPUBufferView *bufferView = ((CCVKBuffer *)_buffers[i])->gpuBufferView(); + if (binding.gpuBufferView != bufferView) { + if (binding.gpuBufferView) { + descriptorHub->disengage(binding.gpuBufferView, &descriptorInfo.buffer); + } + if (bufferView) { + descriptorHub->connect(bufferView, &descriptorInfo.buffer); + descriptorHub->update(bufferView, &descriptorInfo.buffer); + } + binding.gpuBufferView = bufferView; + } + } + } else if ((uint)binding.type & DESCRIPTOR_SAMPLER_TYPE) { + // TODO: handle texture arrays (need public interface changes) + if (_textures[i]) { + CCVKGPUTextureView *textureView = ((CCVKTexture *)_textures[i])->gpuTextureView(); + if (binding.gpuTextureView != textureView) { + if (binding.gpuTextureView) { + descriptorHub->disengage(binding.gpuTextureView, &descriptorInfo.image); + } + if (textureView) { + descriptorHub->connect(textureView, &descriptorInfo.image); + descriptorHub->update(textureView, &descriptorInfo.image); + } + binding.gpuTextureView = textureView; + } + } + if (_samplers[i]) { + CCVKGPUSampler *sampler = ((CCVKSampler *)_samplers[i])->gpuSampler(); + if (binding.gpuSampler != sampler) { + if (binding.gpuSampler) { + descriptorHub->disengage(binding.gpuSampler, &descriptorInfo.image); + } + if (sampler) { + descriptorHub->connect(sampler, &descriptorInfo.image); + descriptorHub->update(sampler, &descriptorInfo.image); + } + binding.gpuSampler = sampler; + } + } + } + } + _isDirty = false; + } +} + +} // namespace gfx +} // namespace cc diff --git a/cocos/renderer/gfx-vulkan/VKDescriptorSet.h b/cocos/renderer/gfx-vulkan/VKDescriptorSet.h new file mode 100644 index 00000000000..0cef32e6625 --- /dev/null +++ b/cocos/renderer/gfx-vulkan/VKDescriptorSet.h @@ -0,0 +1,28 @@ +#ifndef CC_GFXVULKAN_CCVK_BINDING_LAYOUT_H_ +#define CC_GFXVULKAN_CCVK_BINDING_LAYOUT_H_ + +namespace cc { +namespace gfx { + +class CCVKGPUDescriptorSet; + +class CC_VULKAN_API CCVKDescriptorSet : public DescriptorSet { +public: + CCVKDescriptorSet(Device *device); + ~CCVKDescriptorSet(); + +public: + virtual bool initialize(const DescriptorSetInfo &info) override; + virtual void destroy() override; + virtual void update() override; + + CC_INLINE CCVKGPUDescriptorSet *gpuDescriptorSet() const { return _gpuDescriptorSet; } + +private: + CCVKGPUDescriptorSet *_gpuDescriptorSet = nullptr; +}; + +} // namespace gfx +} // namespace cc + +#endif diff --git a/cocos/renderer/gfx-vulkan/VKDescriptorSetLayout.cc b/cocos/renderer/gfx-vulkan/VKDescriptorSetLayout.cc new file mode 100644 index 00000000000..9b82a417c20 --- /dev/null +++ b/cocos/renderer/gfx-vulkan/VKDescriptorSetLayout.cc @@ -0,0 +1,44 @@ +#include "VKStd.h" + +#include "VKCommands.h" +#include "VKDescriptorSetLayout.h" +#include "VKDevice.h" + +namespace cc { +namespace gfx { + +CCVKDescriptorSetLayout::CCVKDescriptorSetLayout(Device *device) +: DescriptorSetLayout(device) { +} + +CCVKDescriptorSetLayout::~CCVKDescriptorSetLayout() { +} + +bool CCVKDescriptorSetLayout::initialize(const DescriptorSetLayoutInfo &info) { + + _bindings = info.bindings; + + _gpuDescriptorSetLayout = CC_NEW(CCVKGPUDescriptorSetLayout); + + for (DescriptorSetLayoutBinding binding : _bindings) { + _gpuDescriptorSetLayout->bindings.push_back(binding); + } + + CCVKCmdFuncCreateDescriptorSetLayout((CCVKDevice *)_device, _gpuDescriptorSetLayout); + + _status = Status::SUCCESS; + + return true; +} + +void CCVKDescriptorSetLayout::destroy() { + if (_gpuDescriptorSetLayout) { + ((CCVKDevice *)_device)->gpuRecycleBin()->collect(_gpuDescriptorSetLayout); + _gpuDescriptorSetLayout = nullptr; + } + + _status = Status::UNREADY; +} + +} // namespace gfx +} // namespace cc diff --git a/cocos/renderer/gfx-vulkan/VKDescriptorSetLayout.h b/cocos/renderer/gfx-vulkan/VKDescriptorSetLayout.h new file mode 100644 index 00000000000..96d009db421 --- /dev/null +++ b/cocos/renderer/gfx-vulkan/VKDescriptorSetLayout.h @@ -0,0 +1,27 @@ +#ifndef CC_GFXVULKAN_CCVK_DESCRIPTOR_SET_LAYOUT_H_ +#define CC_GFXVULKAN_CCVK_DESCRIPTOR_SET_LAYOUT_H_ + +namespace cc { +namespace gfx { + +class CCVKGPUDescriptorSetLayout; + +class CC_VULKAN_API CCVKDescriptorSetLayout : public DescriptorSetLayout { +public: + CCVKDescriptorSetLayout(Device *device); + ~CCVKDescriptorSetLayout(); + +public: + virtual bool initialize(const DescriptorSetLayoutInfo &info) override; + virtual void destroy() override; + + CC_INLINE CCVKGPUDescriptorSetLayout *gpuDescriptorSetLayout() const { return _gpuDescriptorSetLayout; } + +private: + CCVKGPUDescriptorSetLayout *_gpuDescriptorSetLayout = nullptr; +}; + +} // namespace gfx +} // namespace cc + +#endif // CC_GFXVULKAN_CCVK_DESCRIPTOR_SET_LAYOUT_H_ diff --git a/cocos/renderer/gfx-vulkan/VKDevice.cc b/cocos/renderer/gfx-vulkan/VKDevice.cc index a8cd0b743ea..7e80301fbed 100644 --- a/cocos/renderer/gfx-vulkan/VKDevice.cc +++ b/cocos/renderer/gfx-vulkan/VKDevice.cc @@ -1,13 +1,15 @@ #include "VKStd.h" -#include "VKBindingLayout.h" #include "VKBuffer.h" #include "VKCommandBuffer.h" #include "VKContext.h" +#include "VKDescriptorSet.h" +#include "VKDescriptorSetLayout.h" #include "VKDevice.h" #include "VKFence.h" #include "VKFramebuffer.h" #include "VKInputAssembler.h" +#include "VKPipelineLayout.h" #include "VKPipelineState.h" #include "VKQueue.h" #include "VKRenderPass.h" @@ -223,6 +225,7 @@ bool CCVKDevice::initialize(const DeviceInfo &info) { _maxVertexTextureUnits = limits.maxPerStageDescriptorSampledImages; _maxTextureSize = limits.maxImageDimension2D; _maxCubeMapTextureSize = limits.maxImageDimensionCube; + _uboOffsetAlignment = (uint)limits.minUniformBufferOffsetAlignment; MapDepthStencilBits(_context->getDepthStencilFormat(), _depthBits, _stencilBits); ///////////////////// Resource Initialization ///////////////////// @@ -274,7 +277,6 @@ bool CCVKDevice::initialize(const DeviceInfo &info) { _gpuDescriptorSetPool = CC_NEW(CCVKGPUDescriptorSetPool(_gpuDevice)); _gpuCommandBufferPool = CC_NEW(CCVKGPUCommandBufferPool(_gpuDevice)); _gpuStagingBufferPool = CC_NEW(CCVKGPUStagingBufferPool(_gpuDevice)); - _gpuPipelineLayoutPool = CC_NEW(CCVKGPUPipelineLayoutPool(_gpuDevice)); _gpuTransportHub->link(((CCVKQueue *)_queue)->gpuQueue(), _gpuFencePool, _gpuCommandBufferPool, _gpuStagingBufferPool); @@ -366,7 +368,6 @@ void CCVKDevice::destroy() { CC_SAFE_DESTROY(_queue); CC_SAFE_DELETE(_gpuSwapchain); - CC_SAFE_DELETE(_gpuPipelineLayoutPool); CC_SAFE_DELETE(_gpuStagingBufferPool); CC_SAFE_DELETE(_gpuCommandBufferPool); CC_SAFE_DELETE(_gpuDescriptorSetPool); @@ -572,6 +573,15 @@ Buffer *CCVKDevice::createBuffer(const BufferInfo &info) { return nullptr; } +Buffer *CCVKDevice::createBuffer(const BufferViewInfo &info) { + Buffer *buffer = CC_NEW(CCVKBuffer(this)); + if (buffer->initialize(info)) + return buffer; + + CC_SAFE_DESTROY(buffer); + return nullptr; +} + Texture *CCVKDevice::createTexture(const TextureInfo &info) { Texture *texture = CC_NEW(CCVKTexture(this)); if (texture->initialize(info)) @@ -635,12 +645,30 @@ Framebuffer *CCVKDevice::createFramebuffer(const FramebufferInfo &info) { return nullptr; } -BindingLayout *CCVKDevice::createBindingLayout(const BindingLayoutInfo &info) { - BindingLayout *bindingLayout = CC_NEW(CCVKBindingLayout(this)); - if (bindingLayout->initialize(info)) - return bindingLayout; +DescriptorSet *CCVKDevice::createDescriptorSet(const DescriptorSetInfo &info) { + DescriptorSet *descriptorSet = CC_NEW(CCVKDescriptorSet(this)); + if (descriptorSet->initialize(info)) + return descriptorSet; + + CC_SAFE_DESTROY(descriptorSet); + return nullptr; +} + +DescriptorSetLayout *CCVKDevice::createDescriptorSetLayout(const DescriptorSetLayoutInfo &info) { + DescriptorSetLayout *descriptorSetLayout = CC_NEW(CCVKDescriptorSetLayout(this)); + if (descriptorSetLayout->initialize(info)) + return descriptorSetLayout; + + CC_SAFE_DESTROY(descriptorSetLayout); + return nullptr; +} + +PipelineLayout *CCVKDevice::createPipelineLayout(const PipelineLayoutInfo &info) { + PipelineLayout *pipelineLayout = CC_NEW(CCVKPipelineLayout(this)); + if (pipelineLayout->initialize(info)) + return pipelineLayout; - CC_SAFE_DESTROY(bindingLayout); + CC_SAFE_DESTROY(pipelineLayout); return nullptr; } diff --git a/cocos/renderer/gfx-vulkan/VKDevice.h b/cocos/renderer/gfx-vulkan/VKDevice.h index 101066cf0e6..c603e0b6495 100644 --- a/cocos/renderer/gfx-vulkan/VKDevice.h +++ b/cocos/renderer/gfx-vulkan/VKDevice.h @@ -20,7 +20,6 @@ class CCVKGPUSemaphorePool; class CCVKGPUDescriptorSetPool; class CCVKGPUCommandBufferPool; class CCVKGPUStagingBufferPool; -class CCVKGPUPipelineLayoutPool; class CC_VULKAN_API CCVKDevice : public Device { public: @@ -37,6 +36,7 @@ class CC_VULKAN_API CCVKDevice : public Device { virtual Fence *createFence(const FenceInfo &info) override; virtual Queue *createQueue(const QueueInfo &info) override; virtual Buffer *createBuffer(const BufferInfo &info) override; + virtual Buffer *createBuffer(const BufferViewInfo &info) override; virtual Texture *createTexture(const TextureInfo &info) override; virtual Texture *createTexture(const TextureViewInfo &info) override; virtual Sampler *createSampler(const SamplerInfo &info) override; @@ -45,6 +45,8 @@ class CC_VULKAN_API CCVKDevice : public Device { virtual RenderPass *createRenderPass(const RenderPassInfo &info) override; virtual Framebuffer *createFramebuffer(const FramebufferInfo &info) override; virtual DescriptorSet *createDescriptorSet(const DescriptorSetInfo &info) override; + virtual DescriptorSetLayout *createDescriptorSetLayout(const DescriptorSetLayoutInfo &info) override; + virtual PipelineLayout *createPipelineLayout(const PipelineLayoutInfo &info) override; virtual PipelineState *createPipelineState(const PipelineStateInfo &info) override; virtual void copyBuffersToTexture(const BufferDataList &buffers, Texture *dst, const BufferTextureCopyList ®ions) override; @@ -67,7 +69,6 @@ class CC_VULKAN_API CCVKDevice : public Device { CC_INLINE CCVKGPUDescriptorSetPool *gpuDescriptorSetPool() { return _gpuDescriptorSetPool; } CC_INLINE CCVKGPUCommandBufferPool *gpuCommandBufferPool() { return _gpuCommandBufferPool; } CC_INLINE CCVKGPUStagingBufferPool *gpuStagingBufferPool() { return _gpuStagingBufferPool; } - CC_INLINE CCVKGPUPipelineLayoutPool *gpuPipelineLayoutPool() { return _gpuPipelineLayoutPool; } private: void buildSwapchain(); @@ -84,7 +85,6 @@ class CC_VULKAN_API CCVKDevice : public Device { CCVKGPUDescriptorSetPool *_gpuDescriptorSetPool = nullptr; CCVKGPUCommandBufferPool *_gpuCommandBufferPool = nullptr; CCVKGPUStagingBufferPool *_gpuStagingBufferPool = nullptr; - CCVKGPUPipelineLayoutPool *_gpuPipelineLayoutPool = nullptr; vector _layers; vector _extensions; diff --git a/cocos/renderer/gfx-vulkan/VKGPUObjects.h b/cocos/renderer/gfx-vulkan/VKGPUObjects.h index e105804b32c..c60fa472ba8 100644 --- a/cocos/renderer/gfx-vulkan/VKGPUObjects.h +++ b/cocos/renderer/gfx-vulkan/VKGPUObjects.h @@ -130,6 +130,13 @@ class CCVKGPUBuffer : public Object { }; typedef vector CCVKGPUBufferList; +class CCVKGPUBufferView : public Object { +public: + CCVKGPUBuffer *gpuBuffer = nullptr; + uint offset = 0u; + uint range = 0u; +}; + class CCVKGPUSwapchain; class CCVKGPUFramebuffer : public Object { public: @@ -177,23 +184,16 @@ class CCVKGPUQueue : public Object { }; struct CCVKGPUShaderStage { - CCVKGPUShaderStage(ShaderType t, String s, ShaderMacroList m) + CCVKGPUShaderStage(ShaderStageFlagBit t, String s, ShaderMacroList m) : type(t), source(s), macros(m) { } - ShaderType type; + ShaderStageFlagBit type; String source; ShaderMacroList macros; VkShaderModule vkShader = VK_NULL_HANDLE; }; typedef vector CCVKGPUShaderStageList; -struct CCVKGPUPipelineLayout { - vector vkDescriptorSetLayouts; - vector vkDescriptorUpdateTemplates; - VkPipelineLayout vkPipelineLayout = VK_NULL_HANDLE; - vector> descriptorIndices; - vector descriptorCounts; -}; class CCVKGPUShader : public Object { public: String name; @@ -201,7 +201,6 @@ class CCVKGPUShader : public Object { UniformBlockList blocks; UniformSamplerList samplers; CCVKGPUShaderStageList gpuStages; - CCVKGPUPipelineLayout *pipelineLayout = nullptr; }; class CCVKGPUInputAssembler : public Object { @@ -214,34 +213,52 @@ class CCVKGPUInputAssembler : public Object { vector vertexBufferOffsets; }; -union CCVKGPUDescriptorInfo { +union CCVKDescriptorInfo { VkDescriptorImageInfo image; VkDescriptorBufferInfo buffer; VkBufferView texelBufferView; }; -class CCVKGPUBinding : public Object { -public: - CCVKGPUBuffer *buffer = nullptr; - CCVKGPUTextureView *texView = nullptr; - CCVKGPUSampler *sampler = nullptr; +struct CCVKGPUDescriptor { + DescriptorType type = DescriptorType::UNKNOWN; + CCVKGPUBufferView *gpuBufferView = nullptr; + CCVKGPUTextureView *gpuTextureView = nullptr; + CCVKGPUSampler *gpuSampler = nullptr; }; -class CCVKGPUBindingLayout : public Object { +typedef vector CCVKGPUDescriptorList; + +class CCVKGPUDescriptorSet : public Object { public: - vector> gpuBindings; - // contiguous across different sets - vector descriptorInfos; + CCVKGPUDescriptorList gpuDescriptors; + + vector descriptorInfos; vector descriptorUpdateEntries; - vector descriptorSets; + VkDescriptorSet descriptorSet; +}; - // external references - const vector> *descriptorIndices = nullptr; +class CCVKGPUDescriptorSetLayout : public Object { +public: + DescriptorSetLayoutBindingList bindings; + + vector vkBindings; + VkDescriptorSetLayout vkDescriptorSetLayout = VK_NULL_HANDLE; + vector descriptorIndices; + uint descriptorCount = 0u; +}; +typedef vector CCVKGPUDescriptorSetLayoutList; + +class CCVKGPUPipelineLayout : public Object { +public: + CCVKGPUDescriptorSetLayoutList setLayouts; + VkPipelineLayout vkPipelineLayout = VK_NULL_HANDLE; + vector vkDescriptorUpdateTemplates; }; class CCVKGPUPipelineState : public Object { public: PrimitiveMode primitive = PrimitiveMode::TRIANGLE_LIST; CCVKGPUShader *gpuShader = nullptr; + CCVKGPUPipelineLayout *gpuPipelineLayout = nullptr; InputState inputState; RasterizerState rs; DepthStencilState dss; @@ -567,51 +584,6 @@ class CCVKGPUStagingBufferPool : public Object { vector _pool; }; -/** - * Pipeline layout pool, reuse if the hash matches. - * Is more useful when compiling lots of shader variants with the same descriptor set layouts. - */ -class CCVKGPUPipelineLayoutPool : public Object { -public: - CCVKGPUPipelineLayoutPool(CCVKGPUDevice *device) - : _device(device) { - } - - ~CCVKGPUPipelineLayoutPool() { - for (PipelineLayoutPool::iterator it = _pool.begin(); it != _pool.end(); it++) { - CCVKGPUPipelineLayout &pipelineLayout = it->second; - for (uint i = 0u; i < pipelineLayout.vkDescriptorUpdateTemplates.size(); i++) { - if (pipelineLayout.vkDescriptorUpdateTemplates[i] != VK_NULL_HANDLE) { - vkDestroyDescriptorUpdateTemplateKHR(_device->vkDevice, pipelineLayout.vkDescriptorUpdateTemplates[i], nullptr); - } - } - pipelineLayout.vkDescriptorUpdateTemplates.clear(); - - if (pipelineLayout.vkPipelineLayout != VK_NULL_HANDLE) { - vkDestroyPipelineLayout(_device->vkDevice, pipelineLayout.vkPipelineLayout, nullptr); - pipelineLayout.vkPipelineLayout = VK_NULL_HANDLE; - } - - for (uint i = 0u; i < pipelineLayout.vkDescriptorSetLayouts.size(); i++) { - if (pipelineLayout.vkDescriptorSetLayouts[i] != VK_NULL_HANDLE) { - vkDestroyDescriptorSetLayout(_device->vkDevice, pipelineLayout.vkDescriptorSetLayouts[i], nullptr); - } - } - pipelineLayout.vkDescriptorSetLayouts.clear(); - } - _pool.clear(); - } - - void request(CCVKGPUShader *gpuShader); - -private: - typedef map PipelineLayoutPool; - typedef PipelineLayoutPool::iterator PipelineLayoutPoolIt; - - CCVKGPUDevice *_device; - PipelineLayoutPool _pool; -}; - /** * Descriptor data maintenance hub, events like buffer/texture resizing, * descriptor set binding change, etc. should all request an update operation here. @@ -623,8 +595,8 @@ class CCVKGPUDescriptorHub : public Object { } #define DEFINE_DESCRIPTOR_HUB_FN(name) \ - CC_INLINE void name(const CCVKGPUBuffer *buffer) { name(_buffers, buffer, (VkDescriptorBufferInfo *)nullptr); } \ - CC_INLINE void name(const CCVKGPUBuffer *buffer, VkDescriptorBufferInfo *descriptor) { name(_buffers, buffer, descriptor); } \ + CC_INLINE void name(const CCVKGPUBufferView *buffer) { name(_buffers, buffer, (VkDescriptorBufferInfo *)nullptr); } \ + CC_INLINE void name(const CCVKGPUBufferView *buffer, VkDescriptorBufferInfo *descriptor) { name(_buffers, buffer, descriptor); } \ CC_INLINE void name(const CCVKGPUTextureView *texture) { name(_textures, texture, (VkDescriptorImageInfo *)nullptr); } \ CC_INLINE void name(const CCVKGPUTextureView *texture, VkDescriptorImageInfo *descriptor) { name(_textures, texture, descriptor); } \ CC_INLINE void name(const CCVKGPUSampler *sampler) { name(_samplers, sampler, (VkDescriptorImageInfo *)nullptr); } \ @@ -640,10 +612,10 @@ class CCVKGPUDescriptorHub : public Object { map[name].push(descriptor); } - CC_INLINE void _doUpdate(const CCVKGPUBuffer *buffer, VkDescriptorBufferInfo *descriptor) { - descriptor->buffer = buffer->vkBuffer; - descriptor->offset = buffer->startOffset; - descriptor->range = buffer->size; + CC_INLINE void _doUpdate(const CCVKGPUBufferView *buffer, VkDescriptorBufferInfo *descriptor) { + descriptor->buffer = buffer->gpuBuffer->vkBuffer; + descriptor->offset = buffer->gpuBuffer->startOffset + buffer->offset; + descriptor->range = buffer->range; } CC_INLINE void _doUpdate(const CCVKGPUTextureView *texture, VkDescriptorImageInfo *descriptor) { @@ -686,7 +658,7 @@ class CCVKGPUDescriptorHub : public Object { } CCVKGPUDevice *_device = nullptr; - map> _buffers; + map> _buffers; map> _textures; map> _samplers; }; // namespace gfx @@ -711,19 +683,35 @@ class CCVKGPURecycleBin : public Object { res.type = typeValue; \ expr; \ } - DEFINE_RECYCLE_BIN_COLLECT_FN(CCVKGPUBuffer, ObjectType::BUFFER, (res.buffer = {gpuRes->vkBuffer, gpuRes->vmaAllocation})) - DEFINE_RECYCLE_BIN_COLLECT_FN(CCVKGPUTexture, ObjectType::TEXTURE, (res.image = {gpuRes->vkImage, gpuRes->vmaAllocation})) - DEFINE_RECYCLE_BIN_COLLECT_FN(CCVKGPUTextureView, ObjectType::TEXTURE_VIEW, res.vkImageView = gpuRes->vkImageView) - DEFINE_RECYCLE_BIN_COLLECT_FN(CCVKGPURenderPass, ObjectType::RENDER_PASS, res.gpuRenderPass = gpuRes) - DEFINE_RECYCLE_BIN_COLLECT_FN(CCVKGPUFramebuffer, ObjectType::FRAMEBUFFER, res.gpuFramebuffer = gpuRes) - DEFINE_RECYCLE_BIN_COLLECT_FN(CCVKGPUSampler, ObjectType::SAMPLER, res.gpuSampler = gpuRes) - DEFINE_RECYCLE_BIN_COLLECT_FN(CCVKGPUShader, ObjectType::SHADER, res.gpuShader = gpuRes) - DEFINE_RECYCLE_BIN_COLLECT_FN(CCVKGPUPipelineState, ObjectType::PIPELINE_STATE, res.gpuPipelineState = gpuRes) - DEFINE_RECYCLE_BIN_COLLECT_FN(CCVKGPUFence, ObjectType::FENCE, res.gpuFence = gpuRes) + DEFINE_RECYCLE_BIN_COLLECT_FN(CCVKGPUBuffer, RecycledType::BUFFER, (res.buffer = {gpuRes->vkBuffer, gpuRes->vmaAllocation})) + DEFINE_RECYCLE_BIN_COLLECT_FN(CCVKGPUTexture, RecycledType::TEXTURE, (res.image = {gpuRes->vkImage, gpuRes->vmaAllocation})) + DEFINE_RECYCLE_BIN_COLLECT_FN(CCVKGPUTextureView, RecycledType::TEXTURE_VIEW, res.vkImageView = gpuRes->vkImageView) + DEFINE_RECYCLE_BIN_COLLECT_FN(CCVKGPURenderPass, RecycledType::RENDER_PASS, res.gpuRenderPass = gpuRes) + DEFINE_RECYCLE_BIN_COLLECT_FN(CCVKGPUFramebuffer, RecycledType::FRAMEBUFFER, res.gpuFramebuffer = gpuRes) + DEFINE_RECYCLE_BIN_COLLECT_FN(CCVKGPUSampler, RecycledType::SAMPLER, res.gpuSampler = gpuRes) + DEFINE_RECYCLE_BIN_COLLECT_FN(CCVKGPUShader, RecycledType::SHADER, res.gpuShader = gpuRes) + DEFINE_RECYCLE_BIN_COLLECT_FN(CCVKGPUDescriptorSetLayout, RecycledType::DESCRIPTOR_SET_LAYOUT, res.gpuDescriptorSetLayout = gpuRes) + DEFINE_RECYCLE_BIN_COLLECT_FN(CCVKGPUPipelineLayout, RecycledType::PIPELINE_LAYOUT, res.gpuPipelineLayout = gpuRes) + DEFINE_RECYCLE_BIN_COLLECT_FN(CCVKGPUPipelineState, RecycledType::PIPELINE_STATE, res.gpuPipelineState = gpuRes) + DEFINE_RECYCLE_BIN_COLLECT_FN(CCVKGPUFence, RecycledType::FENCE, res.gpuFence = gpuRes) void clear(); private: + enum class RecycledType : uint8_t { + UNKNOWN, + BUFFER, + TEXTURE, + TEXTURE_VIEW, + RENDER_PASS, + FRAMEBUFFER, + SAMPLER, + SHADER, + DESCRIPTOR_SET_LAYOUT, + PIPELINE_LAYOUT, + PIPELINE_STATE, + FENCE, + }; struct Buffer { VkBuffer vkBuffer; VmaAllocation vmaAllocation; @@ -733,7 +721,8 @@ class CCVKGPURecycleBin : public Object { VmaAllocation vmaAllocation; }; struct Resource { - ObjectType type = ObjectType::UNKNOWN; + RecycledType type = RecycledType::UNKNOWN; + bool isView = false; union { // resizable resources, cannot take over directly // or descriptor sets won't work @@ -745,6 +734,8 @@ class CCVKGPURecycleBin : public Object { CCVKGPUFramebuffer *gpuFramebuffer; CCVKGPUSampler *gpuSampler; CCVKGPUShader *gpuShader; + CCVKGPUDescriptorSetLayout *gpuDescriptorSetLayout; + CCVKGPUPipelineLayout *gpuPipelineLayout; CCVKGPUPipelineState *gpuPipelineState; CCVKGPUFence *gpuFence; }; diff --git a/cocos/renderer/gfx-vulkan/VKPipelineLayout.cc b/cocos/renderer/gfx-vulkan/VKPipelineLayout.cc new file mode 100644 index 00000000000..88b2ca23d2b --- /dev/null +++ b/cocos/renderer/gfx-vulkan/VKPipelineLayout.cc @@ -0,0 +1,47 @@ +#include "VKStd.h" + +#include "VKCommands.h" +#include "VKDescriptorSetLayout.h" +#include "VKDevice.h" +#include "VKPipelineLayout.h" + +namespace cc { +namespace gfx { + +CCVKPipelineLayout::CCVKPipelineLayout(Device *device) +: PipelineLayout(device) { +} + +CCVKPipelineLayout::~CCVKPipelineLayout() { +} + +bool CCVKPipelineLayout::initialize(const PipelineLayoutInfo &info) { + + _setLayouts = info.setLayouts; + + _gpuPipelineLayout = CC_NEW(CCVKGPUPipelineLayout); + + for (uint i = 0u; i < _setLayouts.size(); i++) { + DescriptorSetLayout *setLayout = _setLayouts[i]; + _gpuPipelineLayout->setLayouts.push_back(((CCVKDescriptorSetLayout *)setLayout)->gpuDescriptorSetLayout()); + } + + CCVKCmdFuncCreatePipelineLayout((CCVKDevice *)_device, _gpuPipelineLayout); + + _status = Status::SUCCESS; + + return true; +} + +void CCVKPipelineLayout::destroy() { + + if (_gpuPipelineLayout) { + ((CCVKDevice *)_device)->gpuRecycleBin()->collect(_gpuPipelineLayout); + _gpuPipelineLayout = nullptr; + } + + _status = Status::UNREADY; +} + +} // namespace gfx +} // namespace cc diff --git a/cocos/renderer/gfx-vulkan/VKPipelineLayout.h b/cocos/renderer/gfx-vulkan/VKPipelineLayout.h new file mode 100644 index 00000000000..674d4cbf283 --- /dev/null +++ b/cocos/renderer/gfx-vulkan/VKPipelineLayout.h @@ -0,0 +1,27 @@ +#ifndef CC_GFXVULKAN_CCVK_PIPELINE_LAYOUT_H_ +#define CC_GFXVULKAN_CCVK_PIPELINE_LAYOUT_H_ + +namespace cc { +namespace gfx { + +class CCVKGPUPipelineLayout; + +class CC_VULKAN_API CCVKPipelineLayout : public PipelineLayout { +public: + CCVKPipelineLayout(Device *device); + ~CCVKPipelineLayout(); + +public: + virtual bool initialize(const PipelineLayoutInfo &info) override; + virtual void destroy() override; + + CC_INLINE CCVKGPUPipelineLayout *gpuPipelineLayout() const { return _gpuPipelineLayout; } + +private: + CCVKGPUPipelineLayout *_gpuPipelineLayout = nullptr; +}; + +} // namespace gfx +} // namespace cc + +#endif // CC_GFXVULKAN_CCVK_PIPELINE_LAYOUT_H_ diff --git a/cocos/renderer/gfx-vulkan/VKPipelineState.cc b/cocos/renderer/gfx-vulkan/VKPipelineState.cc index 74205ee7173..acc12d44586 100644 --- a/cocos/renderer/gfx-vulkan/VKPipelineState.cc +++ b/cocos/renderer/gfx-vulkan/VKPipelineState.cc @@ -2,6 +2,7 @@ #include "VKCommands.h" #include "VKDevice.h" +#include "VKPipelineLayout.h" #include "VKPipelineState.h" #include "VKRenderPass.h" #include "VKShader.h" @@ -25,6 +26,7 @@ bool CCVKPipelineState::initialize(const PipelineStateInfo &info) { _blendState = info.blendState; _dynamicStates = info.dynamicStates; _renderPass = info.renderPass; + _pipelineLayout = info.pipelineLayout; _gpuPipelineState = CC_NEW(CCVKGPUPipelineState); _gpuPipelineState->primitive = _primitive; @@ -34,6 +36,7 @@ bool CCVKPipelineState::initialize(const PipelineStateInfo &info) { _gpuPipelineState->dss = _depthStencilState; _gpuPipelineState->bs = _blendState; _gpuPipelineState->gpuRenderPass = ((CCVKRenderPass *)_renderPass)->gpuRenderPass(); + _gpuPipelineState->gpuPipelineLayout = ((CCVKPipelineLayout *)_pipelineLayout)->gpuPipelineLayout(); for (uint i = 0; i < 31; i++) { if ((uint)_dynamicStates & (1 << i)) { diff --git a/cocos/renderer/gfx-vulkan/VKSPIRV.h b/cocos/renderer/gfx-vulkan/VKSPIRV.h index d5e6a41253f..9929e8be627 100644 --- a/cocos/renderer/gfx-vulkan/VKSPIRV.h +++ b/cocos/renderer/gfx-vulkan/VKSPIRV.h @@ -9,16 +9,16 @@ namespace cc { namespace gfx { namespace { -EShLanguage getShaderStage(ShaderType type) { +EShLanguage getShaderStage(ShaderStageFlagBit type) { switch (type) { - case ShaderType::VERTEX: return EShLangVertex; - case ShaderType::CONTROL: return EShLangTessControl; - case ShaderType::EVALUATION: return EShLangTessEvaluation; - case ShaderType::GEOMETRY: return EShLangGeometry; - case ShaderType::FRAGMENT: return EShLangFragment; - case ShaderType::COMPUTE: return EShLangCompute; + case ShaderStageFlagBit::VERTEX: return EShLangVertex; + case ShaderStageFlagBit::CONTROL: return EShLangTessControl; + case ShaderStageFlagBit::EVALUATION: return EShLangTessEvaluation; + case ShaderStageFlagBit::GEOMETRY: return EShLangGeometry; + case ShaderStageFlagBit::FRAGMENT: return EShLangFragment; + case ShaderStageFlagBit::COMPUTE: return EShLangCompute; default: { - CCASSERT(false, "Unsupported ShaderType, convert to EShLanguage failed."); + CCASSERT(false, "Unsupported ShaderStageFlagBit, convert to EShLanguage failed."); return EShLangVertex; } } @@ -50,7 +50,7 @@ glslang::EShTargetLanguageVersion getTargetVersion(int vulkanMinorVersion) { bool glslangInitialized = false; -const vector GLSL2SPIRV(ShaderType type, const String &source, int vulkanMinorVersion = 0) { +const vector GLSL2SPIRV(ShaderStageFlagBit type, const String &source, int vulkanMinorVersion = 0) { if (!glslangInitialized) { glslang::InitializeProcess(); glslangInitialized = true; diff --git a/cocos/renderer/gfx-vulkan/VKTexture.cc b/cocos/renderer/gfx-vulkan/VKTexture.cc index dcb6ab12c97..d0ff216ddfa 100644 --- a/cocos/renderer/gfx-vulkan/VKTexture.cc +++ b/cocos/renderer/gfx-vulkan/VKTexture.cc @@ -91,7 +91,7 @@ bool CCVKTexture::initialize(const TextureInfo &info) { } bool CCVKTexture::initialize(const TextureViewInfo &info) { - _Type = ObjectType::TEXTURE_VIEW; + _isTextureView = true; if (!info.texture) { _status = Status::FAILED; @@ -140,9 +140,11 @@ void CCVKTexture::destroy() { } if (_gpuTexture) { - ((CCVKDevice *)_device)->gpuRecycleBin()->collect(_gpuTexture); - _device->getMemoryStatus().textureSize -= _size; - CC_DELETE(_gpuTexture); + if (!_isTextureView) { + ((CCVKDevice *)_device)->gpuRecycleBin()->collect(_gpuTexture); + _device->getMemoryStatus().textureSize -= _size; + CC_DELETE(_gpuTexture); + } _gpuTexture = nullptr; } @@ -155,6 +157,8 @@ void CCVKTexture::destroy() { } void CCVKTexture::resize(uint width, uint height) { + CCASSERT(!_isTextureView, "Cannot resize texture views"); + uint size = FormatSize(_format, width, height, _depth); if (_size != size) { const uint old_size = _size; diff --git a/cocos/renderer/gfx-vulkan/VKUtils.h b/cocos/renderer/gfx-vulkan/VKUtils.h index 7a949be0514..398712238e1 100644 --- a/cocos/renderer/gfx-vulkan/VKUtils.h +++ b/cocos/renderer/gfx-vulkan/VKUtils.h @@ -375,13 +375,15 @@ VkCommandBufferLevel MapVkCommandBufferLevel(CommandBufferType type) { } } -VkDescriptorType MapVkDescriptorType(BindingType type) { +VkDescriptorType MapVkDescriptorType(DescriptorType type) { switch (type) { - case BindingType::UNIFORM_BUFFER: return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - case BindingType::SAMPLER: return VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - case BindingType::STORAGE_BUFFER: return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + case DescriptorType::DYNAMIC_UNIFORM_BUFFER: return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; + case DescriptorType::UNIFORM_BUFFER: return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + case DescriptorType::DYNAMIC_STORAGE_BUFFER: return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; + case DescriptorType::STORAGE_BUFFER: return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + case DescriptorType::SAMPLER: return VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; default: { - CCASSERT(false, "Unsupported BindingType, convert to VkDescriptorType failed."); + CCASSERT(false, "Unsupported DescriptorType, convert to VkDescriptorType failed."); return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; } } @@ -397,29 +399,29 @@ VkColorComponentFlags MapVkColorComponentFlags(ColorMask colorMask) { return (VkColorComponentFlags)flags; } -VkShaderStageFlagBits MapVkShaderStageFlagBits(ShaderType stage) { +VkShaderStageFlagBits MapVkShaderStageFlagBits(ShaderStageFlagBit stage) { switch (stage) { - case ShaderType::VERTEX: return VK_SHADER_STAGE_VERTEX_BIT; - case ShaderType::CONTROL: return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; - case ShaderType::EVALUATION: return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; - case ShaderType::GEOMETRY: return VK_SHADER_STAGE_GEOMETRY_BIT; - case ShaderType::FRAGMENT: return VK_SHADER_STAGE_FRAGMENT_BIT; - case ShaderType::COMPUTE: return VK_SHADER_STAGE_COMPUTE_BIT; + case ShaderStageFlagBit::VERTEX: return VK_SHADER_STAGE_VERTEX_BIT; + case ShaderStageFlagBit::CONTROL: return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; + case ShaderStageFlagBit::EVALUATION: return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; + case ShaderStageFlagBit::GEOMETRY: return VK_SHADER_STAGE_GEOMETRY_BIT; + case ShaderStageFlagBit::FRAGMENT: return VK_SHADER_STAGE_FRAGMENT_BIT; + case ShaderStageFlagBit::COMPUTE: return VK_SHADER_STAGE_COMPUTE_BIT; default: { - CCASSERT(false, "Unsupported ShaderType, convert to VkShaderStageFlagBits failed."); + CCASSERT(false, "Unsupported ShaderStageFlagBit, convert to VkShaderStageFlagBits failed."); return VK_SHADER_STAGE_VERTEX_BIT; } } } -VkShaderStageFlags MapVkShaderStageFlags(ShaderType stages) { +VkShaderStageFlags MapVkShaderStageFlags(ShaderStageFlagBit stages) { uint flags = 0u; - if (stages & ShaderType::VERTEX) flags |= VK_SHADER_STAGE_VERTEX_BIT; - if (stages & ShaderType::CONTROL) flags |= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; - if (stages & ShaderType::EVALUATION) flags |= VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; - if (stages & ShaderType::GEOMETRY) flags |= VK_SHADER_STAGE_GEOMETRY_BIT; - if (stages & ShaderType::FRAGMENT) flags |= VK_SHADER_STAGE_FRAGMENT_BIT; - if (stages & ShaderType::COMPUTE) flags |= VK_SHADER_STAGE_COMPUTE_BIT; + if (stages & ShaderStageFlagBit::VERTEX) flags |= VK_SHADER_STAGE_VERTEX_BIT; + if (stages & ShaderStageFlagBit::CONTROL) flags |= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; + if (stages & ShaderStageFlagBit::EVALUATION) flags |= VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; + if (stages & ShaderStageFlagBit::GEOMETRY) flags |= VK_SHADER_STAGE_GEOMETRY_BIT; + if (stages & ShaderStageFlagBit::FRAGMENT) flags |= VK_SHADER_STAGE_FRAGMENT_BIT; + if (stages & ShaderStageFlagBit::COMPUTE) flags |= VK_SHADER_STAGE_COMPUTE_BIT; return (VkShaderStageFlags)flags; }