From 31ec1442270fdb8b8fca9ac17eb75ae74327d08d Mon Sep 17 00:00:00 2001 From: Greg Daniel Date: Mon, 8 May 2017 10:30:59 -0400 Subject: [PATCH] Add support for using texel buffers in Vulkan backend. Bug: skia: Change-Id: I5cc7b18263dbe28d5d8d89301111ef240109704a Reviewed-on: https://skia-review.googlesource.com/15770 Reviewed-by: Jim Van Verth Commit-Queue: Greg Daniel --- src/gpu/vk/GrVkBufferView.h | 3 - src/gpu/vk/GrVkDescriptorSetManager.cpp | 2 +- src/gpu/vk/GrVkPipelineState.cpp | 217 ++++++++++++++++++++------------ src/gpu/vk/GrVkPipelineState.h | 60 +++------ src/gpu/vk/GrVkPipelineStateBuilder.cpp | 12 +- src/gpu/vk/GrVkUniformHandler.cpp | 32 +++++ src/gpu/vk/GrVkUniformHandler.h | 11 +- 7 files changed, 199 insertions(+), 138 deletions(-) diff --git a/src/gpu/vk/GrVkBufferView.h b/src/gpu/vk/GrVkBufferView.h index fc53258..5f01925 100644 --- a/src/gpu/vk/GrVkBufferView.h +++ b/src/gpu/vk/GrVkBufferView.h @@ -30,9 +30,6 @@ public: private: GrVkBufferView(VkBufferView bufferView) : INHERITED(), fBufferView(bufferView) {} - GrVkBufferView(const GrVkBufferView&); - GrVkBufferView& operator=(const GrVkBufferView&); - void freeGPUData(const GrVkGpu* gpu) const override; VkBufferView fBufferView; diff --git a/src/gpu/vk/GrVkDescriptorSetManager.cpp b/src/gpu/vk/GrVkDescriptorSetManager.cpp index 456531c..7d70b33 100644 --- a/src/gpu/vk/GrVkDescriptorSetManager.cpp +++ b/src/gpu/vk/GrVkDescriptorSetManager.cpp @@ -116,7 +116,7 @@ bool GrVkDescriptorSetManager::isCompatible(VkDescriptorType type, if (fBindingVisibilities.count() != uniHandler->numTexelBuffers()) { return false; } - for (int i = 0; i < uniHandler->numSamplers(); ++i) { + for (int i = 0; i < uniHandler->numTexelBuffers(); ++i) { if (uniHandler->texelBufferVisibility(i) != fBindingVisibilities[i]) { return false; } diff --git a/src/gpu/vk/GrVkPipelineState.cpp b/src/gpu/vk/GrVkPipelineState.cpp index ef0a962..c4d723f 100644 --- a/src/gpu/vk/GrVkPipelineState.cpp +++ b/src/gpu/vk/GrVkPipelineState.cpp @@ -9,6 +9,7 @@ #include "GrPipeline.h" #include "GrTexturePriv.h" +#include "GrVkBufferView.h" #include "GrVkCommandBuffer.h" #include "GrVkDescriptorPool.h" #include "GrVkDescriptorSet.h" @@ -18,6 +19,7 @@ #include "GrVkPipeline.h" #include "GrVkRenderTarget.h" #include "GrVkSampler.h" +#include "GrVkTexelBuffer.h" #include "GrVkTexture.h" #include "GrVkUniformBuffer.h" #include "glsl/GrGLSLFragmentProcessor.h" @@ -30,11 +32,13 @@ GrVkPipelineState::GrVkPipelineState(GrVkGpu* gpu, GrVkPipeline* pipeline, VkPipelineLayout layout, const GrVkDescriptorSetManager::Handle& samplerDSHandle, + const GrVkDescriptorSetManager::Handle& texelBufferDSHandle, const BuiltinUniformHandles& builtinUniformHandles, const UniformInfoArray& uniforms, uint32_t geometryUniformSize, uint32_t fragmentUniformSize, uint32_t numSamplers, + uint32_t numTexelBuffers, GrGLSLPrimitiveProcessor* geometryProcessor, GrGLSLXferProcessor* xferProcessor, const GrGLSLFragProcs& fragmentProcessors) @@ -42,9 +46,9 @@ GrVkPipelineState::GrVkPipelineState(GrVkGpu* gpu, , fPipelineLayout(layout) , fUniformDescriptorSet(nullptr) , fSamplerDescriptorSet(nullptr) + , fTexelBufferDescriptorSet(nullptr) , fSamplerDSHandle(samplerDSHandle) - , fStartDS(SK_MaxS32) - , fDSCount(0) + , fTexelBufferDSHandle(texelBufferDSHandle) , fBuiltinUniformHandles(builtinUniformHandles) , fGeometryProcessor(geometryProcessor) , fXferProcessor(xferProcessor) @@ -54,24 +58,18 @@ GrVkPipelineState::GrVkPipelineState(GrVkGpu* gpu, fSamplers.setReserve(numSamplers); fTextureViews.setReserve(numSamplers); fTextures.setReserve(numSamplers); + fBufferViews.setReserve(numTexelBuffers); + fTexelBuffers.setReserve(numTexelBuffers); fDescriptorSets[0] = VK_NULL_HANDLE; fDescriptorSets[1] = VK_NULL_HANDLE; - - // Currently we are always binding a descriptor set for uniform buffers. - if (geometryUniformSize || fragmentUniformSize) { - fDSCount++; - fStartDS = GrVkUniformHandler::kUniformBufferDescSet; - } - if (numSamplers) { - fDSCount++; - fStartDS = SkTMin(fStartDS, (int)GrVkUniformHandler::kSamplerDescSet); - } + fDescriptorSets[2] = VK_NULL_HANDLE; fGeometryUniformBuffer.reset(GrVkUniformBuffer::Create(gpu, geometryUniformSize)); fFragmentUniformBuffer.reset(GrVkUniformBuffer::Create(gpu, fragmentUniformSize)); fNumSamplers = numSamplers; + fNumTexelBuffers = numTexelBuffers; } GrVkPipelineState::~GrVkPipelineState() { @@ -81,6 +79,9 @@ GrVkPipelineState::~GrVkPipelineState() { SkASSERT(!fSamplers.count()); SkASSERT(!fTextureViews.count()); SkASSERT(!fTextures.count()); + SkASSERT(!fBufferViews.count()); + SkASSERT(!fTexelBuffers.count()); + for (int i = 0; i < fFragmentProcessors.count(); ++i) { delete fFragmentProcessors[i]; } @@ -93,14 +94,24 @@ void GrVkPipelineState::freeTempResources(const GrVkGpu* gpu) { fSamplers.rewind(); for (int i = 0; i < fTextureViews.count(); ++i) { - fTextureViews[i]->unref(gpu); + fTextureViews[i]->unref(gpu); } fTextureViews.rewind(); for (int i = 0; i < fTextures.count(); ++i) { - fTextures[i]->unref(gpu); + fTextures[i]->unref(gpu); } fTextures.rewind(); + + for (int i = 0; i < fBufferViews.count(); ++i) { + fBufferViews[i]->unref(gpu); + } + fBufferViews.rewind(); + + for (int i = 0; i < fTexelBuffers.count(); ++i) { + fTexelBuffers[i]->unref(gpu); + } + fTexelBuffers.rewind(); } void GrVkPipelineState::freeGPUResources(const GrVkGpu* gpu) { @@ -134,6 +145,12 @@ void GrVkPipelineState::freeGPUResources(const GrVkGpu* gpu) { fSamplerDescriptorSet = nullptr; } + if (fTexelBufferDescriptorSet) { + fTexelBufferDescriptorSet->recycle(const_cast(gpu)); + fTexelBufferDescriptorSet = nullptr; + } + + this->freeTempResources(gpu); } @@ -161,6 +178,16 @@ void GrVkPipelineState::abandonGPUResources() { } fTextures.rewind(); + for (int i = 0; i < fBufferViews.count(); ++i) { + fBufferViews[i]->unrefAndAbandon(); + } + fBufferViews.rewind(); + + for (int i = 0; i < fTexelBuffers.count(); ++i) { + fTexelBuffers[i]->unrefAndAbandon(); + } + + fTexelBuffers.rewind(); if (fUniformDescriptorSet) { fUniformDescriptorSet->unrefAndAbandon(); fUniformDescriptorSet = nullptr; @@ -170,11 +197,17 @@ void GrVkPipelineState::abandonGPUResources() { fSamplerDescriptorSet->unrefAndAbandon(); fSamplerDescriptorSet = nullptr; } + + if (fTexelBufferDescriptorSet) { + fTexelBufferDescriptorSet->unrefAndAbandon(); + fTexelBufferDescriptorSet = nullptr; + } } static void append_texture_bindings( const GrResourceIOProcessor& processor, - SkTArray* textureBindings) { + SkTArray* textureBindings, + SkTArray* bufferAccesses) { // We don't support image storages in VK. SkASSERT(!processor.numImageStorages()); if (int numTextureSamplers = processor.numTextureSamplers()) { @@ -185,6 +218,14 @@ static void append_texture_bindings( bindings[i] = &processor.textureSampler(i); } while (++i < numTextureSamplers); } + if (int numTexelBuffers = processor.numBuffers()) { + const GrResourceIOProcessor::BufferAccess** accesses = + bufferAccesses->push_back_n(numTexelBuffers); + int i = 0; + do { + accesses[i] = &processor.bufferAccess(i); + } while (++i < numTexelBuffers); + } } void GrVkPipelineState::setData(GrVkGpu* gpu, @@ -197,10 +238,11 @@ void GrVkPipelineState::setData(GrVkGpu* gpu, this->setRenderTargetState(pipeline.getRenderTarget()); SkSTArray<8, const GrResourceIOProcessor::TextureSampler*> textureBindings; + SkSTArray<8, const GrResourceIOProcessor::BufferAccess*> bufferAccesses; fGeometryProcessor->setData(fDataManager, primProc, GrFragmentProcessor::CoordTransformIter(pipeline)); - append_texture_bindings(primProc, &textureBindings); + append_texture_bindings(primProc, &textureBindings, &bufferAccesses); GrFragmentProcessor::Iter iter(pipeline); GrGLSLFragmentProcessor::Iter glslIter(fFragmentProcessors.begin(), @@ -209,7 +251,7 @@ void GrVkPipelineState::setData(GrVkGpu* gpu, GrGLSLFragmentProcessor* glslFP = glslIter.next(); while (fp && glslFP) { glslFP->setData(fDataManager, *fp); - append_texture_bindings(*fp, &textureBindings); + append_texture_bindings(*fp, &textureBindings, &bufferAccesses); fp = iter.next(); glslFP = glslIter.next(); } @@ -236,6 +278,17 @@ void GrVkPipelineState::setData(GrVkGpu* gpu, this->writeSamplers(gpu, textureBindings, pipeline.getAllowSRGBInputs()); } + if (fNumTexelBuffers) { + if (fTexelBufferDescriptorSet) { + fTexelBufferDescriptorSet->recycle(gpu); + } + fTexelBufferDescriptorSet = + gpu->resourceProvider().getSamplerDescriptorSet(fTexelBufferDSHandle); + int texelBufferDSIdx = GrVkUniformHandler::kTexelBufferDescSet; + fDescriptorSets[texelBufferDSIdx] = fTexelBufferDescriptorSet->descriptorSet(); + this->writeTexelBuffers(gpu, bufferAccesses); + } + if (fGeometryUniformBuffer || fFragmentUniformBuffer) { if (fDataManager.uploadUniformBuffers(gpu, fGeometryUniformBuffer.get(), @@ -360,6 +413,49 @@ void GrVkPipelineState::writeSamplers( } } +void GrVkPipelineState::writeTexelBuffers( + GrVkGpu* gpu, + const SkTArray& bufferAccesses) { + SkASSERT(fNumTexelBuffers == bufferAccesses.count()); + + for (int i = 0; i < bufferAccesses.count(); ++i) { + GrPixelConfig config = bufferAccesses[i]->texelConfig(); + VkFormat format; + SkAssertResult(GrPixelConfigToVkFormat(config, &format)); + + GrVkTexelBuffer* buffer = static_cast(bufferAccesses[i]->buffer()); + + const GrVkBufferView* bufferView = GrVkBufferView::Create(gpu, buffer->buffer(), + format, buffer->offset(), + buffer->size()); + fBufferViews.push(bufferView); + + const GrVkResource* bufferResource = buffer->resource(); + bufferResource->ref(); + fTexelBuffers.push(bufferResource); + + VkWriteDescriptorSet writeInfo; + memset(&writeInfo, 0, sizeof(VkWriteDescriptorSet)); + writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + writeInfo.pNext = nullptr; + writeInfo.dstSet = fDescriptorSets[GrVkUniformHandler::kTexelBufferDescSet]; + writeInfo.dstBinding = i; + writeInfo.dstArrayElement = 0; + writeInfo.descriptorCount = 1; + writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; + writeInfo.pImageInfo = nullptr; + writeInfo.pBufferInfo = nullptr; + VkBufferView vkBufferView = bufferView->bufferView(); + writeInfo.pTexelBufferView = &vkBufferView; + + GR_VK_CALL(gpu->vkInterface(), UpdateDescriptorSets(gpu->device(), + 1, + &writeInfo, + 0, + nullptr)); + } +} + void GrVkPipelineState::setRenderTargetState(const GrRenderTarget* rt) { // Load the RT height uniform if it is needed to y-flip gl_FragCoord. if (fBuiltinUniformHandles.fRTHeightUni.isValid() && @@ -385,9 +481,23 @@ void GrVkPipelineState::setRenderTargetState(const GrRenderTarget* rt) { void GrVkPipelineState::bind(const GrVkGpu* gpu, GrVkCommandBuffer* commandBuffer) { commandBuffer->bindPipeline(gpu, fPipeline); - if (fDSCount) { - commandBuffer->bindDescriptorSets(gpu, this, fPipelineLayout, fStartDS, fDSCount, - &fDescriptorSets[fStartDS], 0, nullptr); + if (fGeometryUniformBuffer || fFragmentUniformBuffer) { + int dsIndex = GrVkUniformHandler::kUniformBufferDescSet; + commandBuffer->bindDescriptorSets(gpu, this, fPipelineLayout, + dsIndex, 1, + &fDescriptorSets[dsIndex], 0, nullptr); + } + if (fNumSamplers) { + int dsIndex = GrVkUniformHandler::kSamplerDescSet; + commandBuffer->bindDescriptorSets(gpu, this, fPipelineLayout, + dsIndex, 1, + &fDescriptorSets[dsIndex], 0, nullptr); + } + if (fNumTexelBuffers) { + int dsIndex = GrVkUniformHandler::kTexelBufferDescSet; + commandBuffer->bindDescriptorSets(gpu, this, fPipelineLayout, + dsIndex, 1, + &fDescriptorSets[dsIndex], 0, nullptr); } } @@ -398,6 +508,9 @@ void GrVkPipelineState::addUniformResources(GrVkCommandBuffer& commandBuffer) { if (fSamplerDescriptorSet) { commandBuffer.addRecycledResource(fSamplerDescriptorSet); } + if (fTexelBufferDescriptorSet) { + commandBuffer.addRecycledResource(fTexelBufferDescriptorSet); + } if (fGeometryUniformBuffer.get()) { commandBuffer.addRecycledResource(fGeometryUniformBuffer->resource()); @@ -417,71 +530,17 @@ void GrVkPipelineState::addUniformResources(GrVkCommandBuffer& commandBuffer) { for (int i = 0; i < fTextures.count(); ++i) { commandBuffer.addResource(fTextures[i]); } -} - -//////////////////////////////////////////////////////////////////////////////// - -void GrVkPipelineState::DescriptorPoolManager::getNewPool(GrVkGpu* gpu) { - if (fPool) { - fPool->unref(gpu); - uint32_t newPoolSize = fMaxDescriptors + ((fMaxDescriptors + 1) >> 1); - if (newPoolSize < kMaxDescLimit) { - fMaxDescriptors = newPoolSize; - } else { - fMaxDescriptors = kMaxDescLimit; - } - - } - if (fMaxDescriptors) { - fPool = gpu->resourceProvider().findOrCreateCompatibleDescriptorPool(fDescType, - fMaxDescriptors); - } - SkASSERT(fPool || !fMaxDescriptors); -} - -void GrVkPipelineState::DescriptorPoolManager::getNewDescriptorSet(GrVkGpu* gpu, - VkDescriptorSet* ds) { - if (!fMaxDescriptors) { - return; - } - fCurrentDescriptorCount += fDescCountPerSet; - if (fCurrentDescriptorCount > fMaxDescriptors) { - this->getNewPool(gpu); - fCurrentDescriptorCount = fDescCountPerSet; - } - - VkDescriptorSetAllocateInfo dsAllocateInfo; - memset(&dsAllocateInfo, 0, sizeof(VkDescriptorSetAllocateInfo)); - dsAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - dsAllocateInfo.pNext = nullptr; - dsAllocateInfo.descriptorPool = fPool->descPool(); - dsAllocateInfo.descriptorSetCount = 1; - dsAllocateInfo.pSetLayouts = &fDescLayout; - GR_VK_CALL_ERRCHECK(gpu->vkInterface(), AllocateDescriptorSets(gpu->device(), - &dsAllocateInfo, - ds)); -} -void GrVkPipelineState::DescriptorPoolManager::freeGPUResources(const GrVkGpu* gpu) { - if (fDescLayout) { - GR_VK_CALL(gpu->vkInterface(), DestroyDescriptorSetLayout(gpu->device(), fDescLayout, - nullptr)); - fDescLayout = VK_NULL_HANDLE; + for (int i = 0; i < fBufferViews.count(); ++i) { + commandBuffer.addResource(fBufferViews[i]); } - if (fPool) { - fPool->unref(gpu); - fPool = nullptr; + for (int i = 0; i < fTexelBuffers.count(); ++i) { + commandBuffer.addResource(fTexelBuffers[i]); } } -void GrVkPipelineState::DescriptorPoolManager::abandonGPUResources() { - fDescLayout = VK_NULL_HANDLE; - if (fPool) { - fPool->unrefAndAbandon(); - fPool = nullptr; - } -} +//////////////////////////////////////////////////////////////////////////////// uint32_t get_blend_info_key(const GrPipeline& pipeline) { GrXferProcessor::BlendInfo blendInfo; diff --git a/src/gpu/vk/GrVkPipelineState.h b/src/gpu/vk/GrVkPipelineState.h index 8f4672c..190ad06 100644 --- a/src/gpu/vk/GrVkPipelineState.h +++ b/src/gpu/vk/GrVkPipelineState.h @@ -19,6 +19,7 @@ #include "vk/GrVkDefines.h" class GrPipeline; +class GrVkBufferView; class GrVkCommandBuffer; class GrVkDescriptorPool; class GrVkDescriptorSet; @@ -92,53 +93,17 @@ private: GrVkPipeline* pipeline, VkPipelineLayout layout, const GrVkDescriptorSetManager::Handle& samplerDSHandle, + const GrVkDescriptorSetManager::Handle& texelBufferDSHandle, const BuiltinUniformHandles& builtinUniformHandles, const UniformInfoArray& uniforms, uint32_t geometryUniformSize, uint32_t fragmentUniformSize, uint32_t numSamplers, + uint32_t numTexelBuffers, GrGLSLPrimitiveProcessor* geometryProcessor, GrGLSLXferProcessor* xferProcessor, const GrGLSLFragProcs& fragmentProcessors); - // Each pool will manage one type of descriptor. Thus each descriptor set we use will all be of - // one VkDescriptorType. - struct DescriptorPoolManager { - DescriptorPoolManager(VkDescriptorSetLayout layout, VkDescriptorType type, - uint32_t descCount, GrVkGpu* gpu) - : fDescLayout(layout) - , fDescType(type) - , fDescCountPerSet(descCount) - , fCurrentDescriptorCount(0) - , fPool(nullptr) { - SkASSERT(descCount < kMaxDescLimit >> 2); - fMaxDescriptors = fDescCountPerSet << 2; - this->getNewPool(gpu); - } - - ~DescriptorPoolManager() { - SkASSERT(!fDescLayout); - SkASSERT(!fPool); - } - - void getNewDescriptorSet(GrVkGpu* gpu, VkDescriptorSet* ds); - - void freeGPUResources(const GrVkGpu* gpu); - void abandonGPUResources(); - - VkDescriptorSetLayout fDescLayout; - VkDescriptorType fDescType; - uint32_t fDescCountPerSet; - uint32_t fMaxDescriptors; - uint32_t fCurrentDescriptorCount; - GrVkDescriptorPool* fPool; - - private: - static const uint32_t kMaxDescLimit = 1 << 10; - - void getNewPool(GrVkGpu* gpu); - }; - void writeUniformBuffers(const GrVkGpu* gpu); void writeSamplers( @@ -146,6 +111,10 @@ private: const SkTArray& textureBindings, bool allowSRGBInputs); + void writeTexelBuffers( + GrVkGpu* gpu, + const SkTArray& bufferAccesses); + /** * We use the RT's size and origin to adjust from Skia device space to vulkan normalized device * space and to make device space positions have the correct origin for processors that require @@ -197,18 +166,14 @@ private: // descriptor pool alive through the draw, the descritor sets will also stay alive. Thus we do // not need a GrVkResource versions of VkDescriptorSet. We hold on to these in the // GrVkPipelineState since we update the descriptor sets and bind them at separate times; - VkDescriptorSet fDescriptorSets[2]; + VkDescriptorSet fDescriptorSets[3]; - // Once we move samplers over to use the resource provider for descriptor sets we will not need - // the above array and instead just use GrVkDescriptorSet like the uniform one here. const GrVkDescriptorSet* fUniformDescriptorSet; const GrVkDescriptorSet* fSamplerDescriptorSet; + const GrVkDescriptorSet* fTexelBufferDescriptorSet; const GrVkDescriptorSetManager::Handle fSamplerDSHandle; - - // Meta data so we know which descriptor sets we are using and need to bind. - int fStartDS; - int fDSCount; + const GrVkDescriptorSetManager::Handle fTexelBufferDSHandle; std::unique_ptr fGeometryUniformBuffer; std::unique_ptr fFragmentUniformBuffer; @@ -218,6 +183,10 @@ private: SkTDArray fTextureViews; SkTDArray fTextures; + // GrVkResource used for TexelBuffers + SkTDArray fBufferViews; + SkTDArray fTexelBuffers; + // Tracks the current render target uniforms stored in the vertex buffer. RenderTargetState fRenderTargetState; BuiltinUniformHandles fBuiltinUniformHandles; @@ -232,6 +201,7 @@ private: GrVkPipelineStateDataManager fDataManager; int fNumSamplers; + int fNumTexelBuffers; friend class GrVkPipelineStateBuilder; }; diff --git a/src/gpu/vk/GrVkPipelineStateBuilder.cpp b/src/gpu/vk/GrVkPipelineStateBuilder.cpp index 45b2978..51c15fb 100644 --- a/src/gpu/vk/GrVkPipelineStateBuilder.cpp +++ b/src/gpu/vk/GrVkPipelineStateBuilder.cpp @@ -90,7 +90,7 @@ GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrStencilSettings& s GrPrimitiveType primitiveType, const GrVkRenderPass& renderPass, GrVkPipelineState::Desc* desc) { - VkDescriptorSetLayout dsLayout[2]; + VkDescriptorSetLayout dsLayout[3]; VkPipelineLayout pipelineLayout; VkShaderModule vertShaderModule; VkShaderModule fragShaderModule; @@ -105,13 +105,19 @@ GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrStencilSettings& s dsLayout[GrVkUniformHandler::kSamplerDescSet] = resourceProvider.getSamplerDSLayout(samplerDSHandle); + GrVkDescriptorSetManager::Handle texelBufferDSHandle; + resourceProvider.getSamplerDescriptorSetHandle(VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + fUniformHandler, &texelBufferDSHandle); + dsLayout[GrVkUniformHandler::kTexelBufferDescSet] = + resourceProvider.getSamplerDSLayout(texelBufferDSHandle); + // Create the VkPipelineLayout VkPipelineLayoutCreateInfo layoutCreateInfo; memset(&layoutCreateInfo, 0, sizeof(VkPipelineLayoutCreateFlags)); layoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; layoutCreateInfo.pNext = 0; layoutCreateInfo.flags = 0; - layoutCreateInfo.setLayoutCount = 2; + layoutCreateInfo.setLayoutCount = 3; layoutCreateInfo.pSetLayouts = dsLayout; layoutCreateInfo.pushConstantRangeCount = 0; layoutCreateInfo.pPushConstantRanges = nullptr; @@ -175,11 +181,13 @@ GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrStencilSettings& s pipeline, pipelineLayout, samplerDSHandle, + texelBufferDSHandle, fUniformHandles, fUniformHandler.fUniforms, fUniformHandler.fCurrentGeometryUBOOffset, fUniformHandler.fCurrentFragmentUBOOffset, (uint32_t)fUniformHandler.numSamplers(), + (uint32_t)fUniformHandler.numTexelBuffers(), fGeometryProcessor, fXferProcessor, fFragmentProcessors); diff --git a/src/gpu/vk/GrVkUniformHandler.cpp b/src/gpu/vk/GrVkUniformHandler.cpp index 6f6d1d3..74f12e4 100644 --- a/src/gpu/vk/GrVkUniformHandler.cpp +++ b/src/gpu/vk/GrVkUniformHandler.cpp @@ -225,6 +225,30 @@ GrGLSLUniformHandler::SamplerHandle GrVkUniformHandler::addSampler(uint32_t visi return GrGLSLUniformHandler::SamplerHandle(fSamplers.count() - 1); } +GrGLSLUniformHandler::TexelBufferHandle GrVkUniformHandler::addTexelBuffer(uint32_t visibility, + GrSLPrecision precision, + const char* name) { + SkASSERT(name && strlen(name)); + SkDEBUGCODE(static const uint32_t kVisMask = kVertex_GrShaderFlag | kFragment_GrShaderFlag); + SkASSERT(0 == (~kVisMask & visibility)); + SkASSERT(0 != visibility); + SkString mangleName; + char prefix = 'u'; + fProgramBuilder->nameVariable(&mangleName, prefix, name, true); + + UniformInfo& info = fTexelBuffers.push_back(); + info.fVariable.setType(kBufferSampler_GrSLType); + info.fVariable.setTypeModifier(GrShaderVar::kUniform_TypeModifier); + info.fVariable.setPrecision(precision); + info.fVariable.setName(mangleName); + SkString layoutQualifier; + layoutQualifier.appendf("set=%d, binding=%d", kTexelBufferDescSet, fTexelBuffers.count()- 1); + info.fVariable.addLayoutQualifier(layoutQualifier.c_str()); + info.fVisibility = visibility; + info.fUBOffset = 0; + return GrGLSLUniformHandler::TexelBufferHandle(fTexelBuffers.count() - 1); +} + void GrVkUniformHandler::appendUniformDecls(GrShaderFlags visibility, SkString* out) const { SkASSERT(kVertex_GrShaderFlag == visibility || kGeometry_GrShaderFlag == visibility || @@ -239,6 +263,14 @@ void GrVkUniformHandler::appendUniformDecls(GrShaderFlags visibility, SkString* } } + for (int i = 0; i < fTexelBuffers.count(); ++i) { + const UniformInfo& texelBuffer = fTexelBuffers[i]; + if (visibility == texelBuffer.fVisibility) { + texelBuffer.fVariable.appendDecl(fProgramBuilder->shaderCaps(), out); + out->append(";\n"); + } + } + SkDEBUGCODE(bool firstOffsetCheck = false); SkString uniformsString; for (int i = 0; i < fUniforms.count(); ++i) { diff --git a/src/gpu/vk/GrVkUniformHandler.h b/src/gpu/vk/GrVkUniformHandler.h index 66aff61..862fbfc 100644 --- a/src/gpu/vk/GrVkUniformHandler.h +++ b/src/gpu/vk/GrVkUniformHandler.h @@ -49,8 +49,7 @@ private: , fSamplers(kUniformsPerBlock) , fTexelBuffers(kUniformsPerBlock) , fCurrentGeometryUBOOffset(0) - , fCurrentFragmentUBOOffset(0) - , fCurrentSamplerBinding(0) { + , fCurrentFragmentUBOOffset(0) { } UniformHandle internalAddUniformArray(uint32_t visibility, @@ -79,16 +78,13 @@ private: } TexelBufferHandle addTexelBuffer(uint32_t visibility, GrSLPrecision, - const char* name) override { - SkFAIL("Texel buffers not implemented for Vulkan."); - return 0; - } + const char* name) override; int numTexelBuffers() const { return fTexelBuffers.count(); } const GrShaderVar& texelBufferVariable(TexelBufferHandle handle) const override { return fTexelBuffers[handle.toIndex()].fVariable; } - uint32_t texelBufferVisibility(SamplerHandle handle) const { + uint32_t texelBufferVisibility(TexelBufferHandle handle) const { return fTexelBuffers[handle.toIndex()].fVisibility; } @@ -123,7 +119,6 @@ private: uint32_t fCurrentGeometryUBOOffset; uint32_t fCurrentFragmentUBOOffset; - uint32_t fCurrentSamplerBinding; friend class GrVkPipelineStateBuilder; friend class GrVkDescriptorSetManager; -- 2.7.4