Vulkan: Implement simple static textures.
After this change, the SimpleTexture2D sample mostly runs.
BUG=angleproject:2167
Change-Id: Ie6d56f890b1aede329e11d1e987d0f8c17a2d0b4
Reviewed-on: https://chromium-review.googlesource.com/720072
Reviewed-by: Frank Henigman <fjhenigman@chromium.org>
diff --git a/src/libANGLE/renderer/vulkan/ProgramVk.cpp b/src/libANGLE/renderer/vulkan/ProgramVk.cpp
index 13a157a..d942cd6 100644
--- a/src/libANGLE/renderer/vulkan/ProgramVk.cpp
+++ b/src/libANGLE/renderer/vulkan/ProgramVk.cpp
@@ -15,6 +15,7 @@
#include "libANGLE/renderer/vulkan/ContextVk.h"
#include "libANGLE/renderer/vulkan/GlslangWrapper.h"
#include "libANGLE/renderer/vulkan/RendererVk.h"
+#include "libANGLE/renderer/vulkan/TextureVk.h"
namespace rx
{
@@ -134,7 +135,7 @@
}
ProgramVk::ProgramVk(const gl::ProgramState &state)
- : ProgramImpl(state), mDefaultUniformBlocks(), mDescriptorSet(VK_NULL_HANDLE)
+ : ProgramImpl(state), mDefaultUniformBlocks(), mDescriptorSetOffset(0), mDirtyTextures(true)
{
}
@@ -169,7 +170,9 @@
mPipelineLayout.destroy(device);
// Descriptor Sets are pool allocated, so do not need to be explicitly freed.
- mDescriptorSet = VK_NULL_HANDLE;
+ mDescriptorSets.clear();
+ mDescriptorSetOffset = 0;
+ mDirtyTextures = false;
}
gl::LinkResult ProgramVk::load(const gl::Context *contextImpl,
@@ -351,6 +354,11 @@
ANGLE_TRY(updateDefaultUniformsDescriptorSet(contextVk));
}
+ else
+ {
+ // If the program has no uniforms, note this in the offset.
+ mDescriptorSetOffset = 1;
+ }
return gl::NoError();
}
@@ -609,6 +617,60 @@
mDescriptorSetLayouts.push_back(std::move(uniformLayout));
}
+ const auto &samplerBindings = mState.getSamplerBindings();
+
+ if (!samplerBindings.empty())
+ {
+ std::vector<VkDescriptorSetLayoutBinding> textureBindings;
+ uint32_t textureCount = 0;
+ const auto &uniforms = mState.getUniforms();
+ for (unsigned int uniformIndex : mState.getSamplerUniformRange())
+ {
+ const gl::LinkedUniform &samplerUniform = uniforms[uniformIndex];
+ unsigned int samplerIndex = mState.getSamplerIndexFromUniformIndex(uniformIndex);
+ const gl::SamplerBinding &samplerBinding = samplerBindings[samplerIndex];
+
+ ASSERT(!samplerBinding.unreferenced);
+
+ VkDescriptorSetLayoutBinding layoutBinding;
+
+ uint32_t elementCount = samplerUniform.elementCount();
+
+ layoutBinding.binding = textureCount;
+ layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+ layoutBinding.descriptorCount = elementCount;
+
+ layoutBinding.stageFlags = 0;
+ if (samplerUniform.vertexStaticUse)
+ {
+ layoutBinding.stageFlags |= VK_SHADER_STAGE_VERTEX_BIT;
+ }
+ if (samplerUniform.fragmentStaticUse)
+ {
+ layoutBinding.stageFlags |= VK_SHADER_STAGE_FRAGMENT_BIT;
+ }
+
+ layoutBinding.pImmutableSamplers = nullptr;
+
+ textureCount += elementCount;
+
+ textureBindings.push_back(layoutBinding);
+ }
+
+ VkDescriptorSetLayoutCreateInfo textureInfo;
+ textureInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
+ textureInfo.pNext = nullptr;
+ textureInfo.flags = 0;
+ textureInfo.bindingCount = static_cast<uint32_t>(textureBindings.size());
+ textureInfo.pBindings = textureBindings.data();
+
+ vk::DescriptorSetLayout textureLayout;
+ ANGLE_TRY(textureLayout.init(device, textureInfo));
+ mDescriptorSetLayouts.push_back(std::move(textureLayout));
+
+ mDirtyTextures = true;
+ }
+
VkPipelineLayoutCreateInfo createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
createInfo.pNext = nullptr;
@@ -625,7 +687,7 @@
vk::Error ProgramVk::initDescriptorSets(ContextVk *contextVk)
{
- ASSERT(mDescriptorSet == VK_NULL_HANDLE);
+ ASSERT(mDescriptorSets.empty());
VkDevice device = contextVk->getDevice();
@@ -633,16 +695,17 @@
// TODO(jmadill): Handle descriptor set lifetime.
vk::DescriptorPool *descriptorPool = contextVk->getDescriptorPool();
- VkDescriptorSetAllocateInfo allocInfo;
- allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
- allocInfo.pNext = nullptr;
- allocInfo.descriptorPool = descriptorPool->getHandle();
+ uint32_t descriptorSetCount = static_cast<uint32_t>(mDescriptorSetLayouts.size());
- // TODO(jmadill): Handle descriptor set layouts for textures.
- allocInfo.descriptorSetCount = 1;
+ VkDescriptorSetAllocateInfo allocInfo;
+ allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
+ allocInfo.pNext = nullptr;
+ allocInfo.descriptorPool = descriptorPool->getHandle();
+ allocInfo.descriptorSetCount = descriptorSetCount;
allocInfo.pSetLayouts = mDescriptorSetLayouts[0].ptr();
- ANGLE_TRY(descriptorPool->allocateDescriptorSets(device, allocInfo, &mDescriptorSet));
+ mDescriptorSets.resize(descriptorSetCount, VK_NULL_HANDLE);
+ ANGLE_TRY(descriptorPool->allocateDescriptorSets(device, allocInfo, &mDescriptorSets[0]));
return vk::NoError();
}
@@ -669,6 +732,8 @@
return vk::NoError();
}
+ ASSERT(mDescriptorSetOffset == 0);
+
VkDevice device = contextVk->getDevice();
// Update buffer memory by immediate mapping. This immediate update only works once.
@@ -712,7 +777,7 @@
writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
writeInfo.pNext = nullptr;
- writeInfo.dstSet = mDescriptorSet;
+ writeInfo.dstSet = mDescriptorSets[0];
writeInfo.dstBinding = bufferCount;
writeInfo.dstArrayElement = 0;
writeInfo.descriptorCount = 1;
@@ -731,9 +796,82 @@
return vk::NoError();
}
-VkDescriptorSet ProgramVk::getDescriptorSet() const
+const std::vector<VkDescriptorSet> &ProgramVk::getDescriptorSets() const
{
- return mDescriptorSet;
+ return mDescriptorSets;
+}
+
+uint32_t ProgramVk::getDescriptorSetOffset() const
+{
+ return mDescriptorSetOffset;
+}
+
+void ProgramVk::updateTexturesDescriptorSet(ContextVk *contextVk)
+{
+ if (mState.getSamplerBindings().empty() || !mDirtyTextures)
+ {
+ return;
+ }
+
+ VkDescriptorSet descriptorSet = mDescriptorSets.back();
+
+ // TODO(jmadill): Don't hard-code the texture limit.
+ ShaderTextureArray<VkDescriptorImageInfo> descriptorImageInfo;
+ ShaderTextureArray<VkWriteDescriptorSet> writeDescriptorInfo;
+ uint32_t imageCount = 0;
+
+ const gl::State &glState = contextVk->getGLState();
+ const auto &completeTextures = glState.getCompleteTextureCache();
+
+ for (const auto &samplerBinding : mState.getSamplerBindings())
+ {
+ ASSERT(!samplerBinding.unreferenced);
+
+ // TODO(jmadill): Sampler arrays
+ ASSERT(samplerBinding.boundTextureUnits.size() == 1);
+
+ GLuint textureUnit = samplerBinding.boundTextureUnits[0];
+ const gl::Texture *texture = completeTextures[textureUnit];
+
+ // TODO(jmadill): Incomplete textures handling.
+ ASSERT(texture);
+
+ TextureVk *textureVk = GetImplAs<TextureVk>(texture);
+ const vk::Image &image = textureVk->getImage();
+
+ VkDescriptorImageInfo &imageInfo = descriptorImageInfo[imageCount];
+
+ imageInfo.sampler = textureVk->getSampler().getHandle();
+ imageInfo.imageView = textureVk->getImageView().getHandle();
+ imageInfo.imageLayout = image.getCurrentLayout();
+
+ auto &writeInfo = writeDescriptorInfo[imageCount];
+
+ writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ writeInfo.pNext = nullptr;
+ writeInfo.dstSet = descriptorSet;
+ writeInfo.dstBinding = imageCount;
+ writeInfo.dstArrayElement = 0;
+ writeInfo.descriptorCount = 1;
+ writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+ writeInfo.pImageInfo = &imageInfo;
+ writeInfo.pBufferInfo = nullptr;
+ writeInfo.pTexelBufferView = nullptr;
+
+ imageCount++;
+ }
+
+ VkDevice device = contextVk->getDevice();
+
+ ASSERT(imageCount > 0);
+ vkUpdateDescriptorSets(device, imageCount, writeDescriptorInfo.data(), 0, nullptr);
+
+ mDirtyTextures = false;
+}
+
+void ProgramVk::invalidateTextures()
+{
+ mDirtyTextures = true;
}
} // namespace rx