Commit 5547b384 by Jamie Madill

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/720072Reviewed-by: 's avatarFrank Henigman <fjhenigman@chromium.org>
parent cc4ce4a2
...@@ -54,7 +54,8 @@ enum ...@@ -54,7 +54,8 @@ enum
IMPLEMENTATION_MAX_TEXTURE_LEVELS = 15, IMPLEMENTATION_MAX_TEXTURE_LEVELS = 15,
// Limit active textures so we can use fast bitsets. // Limit active textures so we can use fast bitsets.
IMPLEMENTATION_MAX_ACTIVE_TEXTURES = 64, IMPLEMENTATION_MAX_SHADER_TEXTURES = 32,
IMPLEMENTATION_MAX_ACTIVE_TEXTURES = IMPLEMENTATION_MAX_SHADER_TEXTURES * 2,
}; };
} }
......
...@@ -343,15 +343,19 @@ gl::Error ContextVk::setupDraw(const gl::Context *context, GLenum mode) ...@@ -343,15 +343,19 @@ gl::Error ContextVk::setupDraw(const gl::Context *context, GLenum mode)
// TODO(jmadill): Can probably use more dirty bits here. // TODO(jmadill): Can probably use more dirty bits here.
ContextVk *contextVk = GetImplAs<ContextVk>(context); ContextVk *contextVk = GetImplAs<ContextVk>(context);
ANGLE_TRY(programVk->updateUniforms(contextVk)); ANGLE_TRY(programVk->updateUniforms(contextVk));
programVk->updateTexturesDescriptorSet(contextVk);
// Bind the graphics descriptor sets. // Bind the graphics descriptor sets.
// TODO(jmadill): Handle multiple command buffers. // TODO(jmadill): Handle multiple command buffers.
VkDescriptorSet uniformDescriptorSet = programVk->getDescriptorSet(); const auto &descriptorSets = programVk->getDescriptorSets();
if (uniformDescriptorSet != VK_NULL_HANDLE) uint32_t firstSet = programVk->getDescriptorSetOffset();
uint32_t setCount = static_cast<uint32_t>(descriptorSets.size());
if (!descriptorSets.empty() && ((setCount - firstSet) > 0))
{ {
const vk::PipelineLayout &pipelineLayout = programVk->getPipelineLayout(); const vk::PipelineLayout &pipelineLayout = programVk->getPipelineLayout();
commandBuffer->bindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, commandBuffer->bindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, firstSet,
&uniformDescriptorSet, 0, nullptr); setCount - firstSet, &descriptorSets[firstSet], 0,
nullptr);
} }
return gl::NoError(); return gl::NoError();
...@@ -514,6 +518,7 @@ void ContextVk::syncState(const gl::Context *context, const gl::State::DirtyBits ...@@ -514,6 +518,7 @@ void ContextVk::syncState(const gl::Context *context, const gl::State::DirtyBits
const auto &glState = context->getGLState(); const auto &glState = context->getGLState();
// TODO(jmadill): Full dirty bits implementation. // TODO(jmadill): Full dirty bits implementation.
bool dirtyTextures = false;
for (auto dirtyBit : dirtyBits) for (auto dirtyBit : dirtyBits)
{ {
...@@ -714,13 +719,15 @@ void ContextVk::syncState(const gl::Context *context, const gl::State::DirtyBits ...@@ -714,13 +719,15 @@ void ContextVk::syncState(const gl::Context *context, const gl::State::DirtyBits
// Also invalidate the vertex descriptions cache in the Vertex Array. // Also invalidate the vertex descriptions cache in the Vertex Array.
VertexArrayVk *vaoVk = GetImplAs<VertexArrayVk>(glState.getVertexArray()); VertexArrayVk *vaoVk = GetImplAs<VertexArrayVk>(glState.getVertexArray());
vaoVk->invalidateVertexDescriptions(); vaoVk->invalidateVertexDescriptions();
dirtyTextures = true;
break; break;
} }
case gl::State::DIRTY_BIT_TEXTURE_BINDINGS: case gl::State::DIRTY_BIT_TEXTURE_BINDINGS:
WARN() << "DIRTY_BIT_TEXTURE_BINDINGS unimplemented"; dirtyTextures = true;
break; break;
case gl::State::DIRTY_BIT_SAMPLER_BINDINGS: case gl::State::DIRTY_BIT_SAMPLER_BINDINGS:
WARN() << "DIRTY_BIT_SAMPLER_BINDINGS unimplemented"; dirtyTextures = true;
break; break;
case gl::State::DIRTY_BIT_MULTISAMPLING: case gl::State::DIRTY_BIT_MULTISAMPLING:
WARN() << "DIRTY_BIT_MULTISAMPLING unimplemented"; WARN() << "DIRTY_BIT_MULTISAMPLING unimplemented";
...@@ -756,6 +763,12 @@ void ContextVk::syncState(const gl::Context *context, const gl::State::DirtyBits ...@@ -756,6 +763,12 @@ void ContextVk::syncState(const gl::Context *context, const gl::State::DirtyBits
break; break;
} }
} }
if (dirtyTextures)
{
ProgramVk *programVk = GetImplAs<ProgramVk>(glState.getProgram());
programVk->invalidateTextures();
}
} }
GLint ContextVk::getGPUDisjoint() GLint ContextVk::getGPUDisjoint()
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "libANGLE/renderer/vulkan/ContextVk.h" #include "libANGLE/renderer/vulkan/ContextVk.h"
#include "libANGLE/renderer/vulkan/GlslangWrapper.h" #include "libANGLE/renderer/vulkan/GlslangWrapper.h"
#include "libANGLE/renderer/vulkan/RendererVk.h" #include "libANGLE/renderer/vulkan/RendererVk.h"
#include "libANGLE/renderer/vulkan/TextureVk.h"
namespace rx namespace rx
{ {
...@@ -134,7 +135,7 @@ ProgramVk::DefaultUniformBlock::DefaultUniformBlock() ...@@ -134,7 +135,7 @@ ProgramVk::DefaultUniformBlock::DefaultUniformBlock()
} }
ProgramVk::ProgramVk(const gl::ProgramState &state) ProgramVk::ProgramVk(const gl::ProgramState &state)
: ProgramImpl(state), mDefaultUniformBlocks(), mDescriptorSet(VK_NULL_HANDLE) : ProgramImpl(state), mDefaultUniformBlocks(), mDescriptorSetOffset(0), mDirtyTextures(true)
{ {
} }
...@@ -169,7 +170,9 @@ void ProgramVk::reset(VkDevice device) ...@@ -169,7 +170,9 @@ void ProgramVk::reset(VkDevice device)
mPipelineLayout.destroy(device); mPipelineLayout.destroy(device);
// Descriptor Sets are pool allocated, so do not need to be explicitly freed. // 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, gl::LinkResult ProgramVk::load(const gl::Context *contextImpl,
...@@ -351,6 +354,11 @@ gl::Error ProgramVk::initDefaultUniformBlocks(const gl::Context *glContext) ...@@ -351,6 +354,11 @@ gl::Error ProgramVk::initDefaultUniformBlocks(const gl::Context *glContext)
ANGLE_TRY(updateDefaultUniformsDescriptorSet(contextVk)); ANGLE_TRY(updateDefaultUniformsDescriptorSet(contextVk));
} }
else
{
// If the program has no uniforms, note this in the offset.
mDescriptorSetOffset = 1;
}
return gl::NoError(); return gl::NoError();
} }
...@@ -609,6 +617,60 @@ vk::Error ProgramVk::initPipelineLayout(ContextVk *context) ...@@ -609,6 +617,60 @@ vk::Error ProgramVk::initPipelineLayout(ContextVk *context)
mDescriptorSetLayouts.push_back(std::move(uniformLayout)); 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; VkPipelineLayoutCreateInfo createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
createInfo.pNext = nullptr; createInfo.pNext = nullptr;
...@@ -625,7 +687,7 @@ vk::Error ProgramVk::initPipelineLayout(ContextVk *context) ...@@ -625,7 +687,7 @@ vk::Error ProgramVk::initPipelineLayout(ContextVk *context)
vk::Error ProgramVk::initDescriptorSets(ContextVk *contextVk) vk::Error ProgramVk::initDescriptorSets(ContextVk *contextVk)
{ {
ASSERT(mDescriptorSet == VK_NULL_HANDLE); ASSERT(mDescriptorSets.empty());
VkDevice device = contextVk->getDevice(); VkDevice device = contextVk->getDevice();
...@@ -633,16 +695,17 @@ vk::Error ProgramVk::initDescriptorSets(ContextVk *contextVk) ...@@ -633,16 +695,17 @@ vk::Error ProgramVk::initDescriptorSets(ContextVk *contextVk)
// TODO(jmadill): Handle descriptor set lifetime. // TODO(jmadill): Handle descriptor set lifetime.
vk::DescriptorPool *descriptorPool = contextVk->getDescriptorPool(); vk::DescriptorPool *descriptorPool = contextVk->getDescriptorPool();
VkDescriptorSetAllocateInfo allocInfo; uint32_t descriptorSetCount = static_cast<uint32_t>(mDescriptorSetLayouts.size());
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.pNext = nullptr;
allocInfo.descriptorPool = descriptorPool->getHandle();
// TODO(jmadill): Handle descriptor set layouts for textures. VkDescriptorSetAllocateInfo allocInfo;
allocInfo.descriptorSetCount = 1; allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.pNext = nullptr;
allocInfo.descriptorPool = descriptorPool->getHandle();
allocInfo.descriptorSetCount = descriptorSetCount;
allocInfo.pSetLayouts = mDescriptorSetLayouts[0].ptr(); 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(); return vk::NoError();
} }
...@@ -669,6 +732,8 @@ vk::Error ProgramVk::updateUniforms(ContextVk *contextVk) ...@@ -669,6 +732,8 @@ vk::Error ProgramVk::updateUniforms(ContextVk *contextVk)
return vk::NoError(); return vk::NoError();
} }
ASSERT(mDescriptorSetOffset == 0);
VkDevice device = contextVk->getDevice(); VkDevice device = contextVk->getDevice();
// Update buffer memory by immediate mapping. This immediate update only works once. // Update buffer memory by immediate mapping. This immediate update only works once.
...@@ -712,7 +777,7 @@ vk::Error ProgramVk::updateDefaultUniformsDescriptorSet(ContextVk *contextVk) ...@@ -712,7 +777,7 @@ vk::Error ProgramVk::updateDefaultUniformsDescriptorSet(ContextVk *contextVk)
writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
writeInfo.pNext = nullptr; writeInfo.pNext = nullptr;
writeInfo.dstSet = mDescriptorSet; writeInfo.dstSet = mDescriptorSets[0];
writeInfo.dstBinding = bufferCount; writeInfo.dstBinding = bufferCount;
writeInfo.dstArrayElement = 0; writeInfo.dstArrayElement = 0;
writeInfo.descriptorCount = 1; writeInfo.descriptorCount = 1;
...@@ -731,9 +796,82 @@ vk::Error ProgramVk::updateDefaultUniformsDescriptorSet(ContextVk *contextVk) ...@@ -731,9 +796,82 @@ vk::Error ProgramVk::updateDefaultUniformsDescriptorSet(ContextVk *contextVk)
return vk::NoError(); return vk::NoError();
} }
VkDescriptorSet ProgramVk::getDescriptorSet() const const std::vector<VkDescriptorSet> &ProgramVk::getDescriptorSets() const
{
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()
{ {
return mDescriptorSet; mDirtyTextures = true;
} }
} // namespace rx } // namespace rx
...@@ -10,9 +10,12 @@ ...@@ -10,9 +10,12 @@
#ifndef LIBANGLE_RENDERER_VULKAN_PROGRAMVK_H_ #ifndef LIBANGLE_RENDERER_VULKAN_PROGRAMVK_H_
#define LIBANGLE_RENDERER_VULKAN_PROGRAMVK_H_ #define LIBANGLE_RENDERER_VULKAN_PROGRAMVK_H_
#include "libANGLE/Constants.h"
#include "libANGLE/renderer/ProgramImpl.h" #include "libANGLE/renderer/ProgramImpl.h"
#include "libANGLE/renderer/vulkan/renderervk_utils.h" #include "libANGLE/renderer/vulkan/renderervk_utils.h"
#include <array>
namespace rx namespace rx
{ {
...@@ -114,7 +117,16 @@ class ProgramVk : public ProgramImpl ...@@ -114,7 +117,16 @@ class ProgramVk : public ProgramImpl
vk::Error updateUniforms(ContextVk *contextVk); vk::Error updateUniforms(ContextVk *contextVk);
VkDescriptorSet getDescriptorSet() const; const std::vector<VkDescriptorSet> &getDescriptorSets() const;
// In Vulkan, it is invalid to pass in a NULL descriptor set to vkCmdBindDescriptorSets.
// However, it's valid to leave them in an undefined, unbound state, if they are never used.
// This means when we want to ignore a descriptor set index, we need to pass in an offset
// parameter to BindDescriptorSets, which is an offset into the getDescriptorSets array.
uint32_t getDescriptorSetOffset() const;
void updateTexturesDescriptorSet(ContextVk *contextVk);
void invalidateTextures();
private: private:
void reset(VkDevice device); void reset(VkDevice device);
...@@ -154,8 +166,13 @@ class ProgramVk : public ProgramImpl ...@@ -154,8 +166,13 @@ class ProgramVk : public ProgramImpl
// and Vulkan does not tolerate having null handles in a descriptor set. // and Vulkan does not tolerate having null handles in a descriptor set.
vk::BufferAndMemory mEmptyUniformBlockStorage; vk::BufferAndMemory mEmptyUniformBlockStorage;
// Descriptor set for the uniform blocks for this program. // Descriptor sets for uniform blocks and textures for this program.
VkDescriptorSet mDescriptorSet; std::vector<VkDescriptorSet> mDescriptorSets;
uint32_t mDescriptorSetOffset;
bool mDirtyTextures;
template <typename T>
using ShaderTextureArray = std::array<T, gl::IMPLEMENTATION_MAX_SHADER_TEXTURES>;
}; };
} // namespace rx } // namespace rx
......
...@@ -34,6 +34,7 @@ gl::Error TextureVk::onDestroy(const gl::Context *context) ...@@ -34,6 +34,7 @@ gl::Error TextureVk::onDestroy(const gl::Context *context)
renderer->enqueueGarbageOrDeleteNow(*this, std::move(mImage)); renderer->enqueueGarbageOrDeleteNow(*this, std::move(mImage));
renderer->enqueueGarbageOrDeleteNow(*this, std::move(mDeviceMemory)); renderer->enqueueGarbageOrDeleteNow(*this, std::move(mDeviceMemory));
renderer->enqueueGarbageOrDeleteNow(*this, std::move(mImageView)); renderer->enqueueGarbageOrDeleteNow(*this, std::move(mImageView));
renderer->enqueueGarbageOrDeleteNow(*this, std::move(mSampler));
return gl::NoError(); return gl::NoError();
} }
...@@ -77,7 +78,7 @@ gl::Error TextureVk::setImage(const gl::Context *context, ...@@ -77,7 +78,7 @@ gl::Error TextureVk::setImage(const gl::Context *context,
// TODO(jmadill): Are all these image transfer bits necessary? // TODO(jmadill): Are all these image transfer bits necessary?
imageInfo.usage = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | imageInfo.usage = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_TRANSFER_SRC_BIT); VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
imageInfo.queueFamilyIndexCount = 0; imageInfo.queueFamilyIndexCount = 0;
imageInfo.pQueueFamilyIndices = nullptr; imageInfo.pQueueFamilyIndices = nullptr;
...@@ -125,6 +126,30 @@ gl::Error TextureVk::setImage(const gl::Context *context, ...@@ -125,6 +126,30 @@ gl::Error TextureVk::setImage(const gl::Context *context,
ANGLE_TRY(mImageView.init(device, viewInfo)); ANGLE_TRY(mImageView.init(device, viewInfo));
// Create a simple sampler. Force basic parameter settings.
// TODO(jmadill): Sampler parameters.
VkSamplerCreateInfo samplerInfo;
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
samplerInfo.pNext = nullptr;
samplerInfo.flags = 0;
samplerInfo.magFilter = VK_FILTER_NEAREST;
samplerInfo.minFilter = VK_FILTER_NEAREST;
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerInfo.mipLodBias = 0.0f;
samplerInfo.anisotropyEnable = VK_FALSE;
samplerInfo.maxAnisotropy = 1.0f;
samplerInfo.compareEnable = VK_FALSE;
samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
samplerInfo.minLod = 0.0f;
samplerInfo.maxLod = 1.0f;
samplerInfo.borderColor = VK_BORDER_COLOR_INT_TRANSPARENT_BLACK;
samplerInfo.unnormalizedCoordinates = VK_FALSE;
ANGLE_TRY(mSampler.init(device, samplerInfo));
// Handle initial data. // Handle initial data.
// TODO(jmadill): Consider re-using staging texture. // TODO(jmadill): Consider re-using staging texture.
if (pixels) if (pixels)
...@@ -317,7 +342,7 @@ gl::Error TextureVk::getAttachmentRenderTarget(const gl::Context *context, ...@@ -317,7 +342,7 @@ gl::Error TextureVk::getAttachmentRenderTarget(const gl::Context *context,
void TextureVk::syncState(const gl::Texture::DirtyBits &dirtyBits) void TextureVk::syncState(const gl::Texture::DirtyBits &dirtyBits)
{ {
UNIMPLEMENTED(); // TODO(jmadill): Texture sync state.
} }
gl::Error TextureVk::setStorageMultisample(const gl::Context *context, gl::Error TextureVk::setStorageMultisample(const gl::Context *context,
...@@ -338,4 +363,22 @@ gl::Error TextureVk::initializeContents(const gl::Context *context, ...@@ -338,4 +363,22 @@ gl::Error TextureVk::initializeContents(const gl::Context *context,
return gl::NoError(); return gl::NoError();
} }
const vk::Image &TextureVk::getImage() const
{
ASSERT(mImage.valid());
return mImage;
}
const vk::ImageView &TextureVk::getImageView() const
{
ASSERT(mImageView.valid());
return mImageView;
}
const vk::Sampler &TextureVk::getSampler() const
{
ASSERT(mSampler.valid());
return mSampler;
}
} // namespace rx } // namespace rx
...@@ -110,11 +110,16 @@ class TextureVk : public TextureImpl, public ResourceVk ...@@ -110,11 +110,16 @@ class TextureVk : public TextureImpl, public ResourceVk
gl::Error initializeContents(const gl::Context *context, gl::Error initializeContents(const gl::Context *context,
const gl::ImageIndex &imageIndex) override; const gl::ImageIndex &imageIndex) override;
const vk::Image &getImage() const;
const vk::ImageView &getImageView() const;
const vk::Sampler &getSampler() const;
private: private:
// TODO(jmadill): support a more flexible storage back-end. // TODO(jmadill): support a more flexible storage back-end.
vk::Image mImage; vk::Image mImage;
vk::DeviceMemory mDeviceMemory; vk::DeviceMemory mDeviceMemory;
vk::ImageView mImageView; vk::ImageView mImageView;
vk::Sampler mSampler;
}; };
} // namespace rx } // namespace rx
......
...@@ -951,6 +951,27 @@ Error DescriptorPool::allocateDescriptorSets(VkDevice device, ...@@ -951,6 +951,27 @@ Error DescriptorPool::allocateDescriptorSets(VkDevice device,
return NoError(); return NoError();
} }
// Sampler implementation.
Sampler::Sampler()
{
}
void Sampler::destroy(VkDevice device)
{
if (valid())
{
vkDestroySampler(device, mHandle, nullptr);
mHandle = VK_NULL_HANDLE;
}
}
Error Sampler::init(VkDevice device, const VkSamplerCreateInfo &createInfo)
{
ASSERT(!valid());
ANGLE_VK_TRY(vkCreateSampler(device, &createInfo, nullptr, &mHandle));
return NoError();
}
// Fence implementation. // Fence implementation.
Fence::Fence() Fence::Fence()
{ {
......
...@@ -457,6 +457,14 @@ class DescriptorPool final : public WrappedObject<DescriptorPool, VkDescriptorPo ...@@ -457,6 +457,14 @@ class DescriptorPool final : public WrappedObject<DescriptorPool, VkDescriptorPo
VkDescriptorSet *descriptorSetsOut); VkDescriptorSet *descriptorSetsOut);
}; };
class Sampler final : public WrappedObject<Sampler, VkSampler>
{
public:
Sampler();
void destroy(VkDevice device);
Error init(VkDevice device, const VkSamplerCreateInfo &createInfo);
};
class Fence final : public WrappedObject<Fence, VkFence> class Fence final : public WrappedObject<Fence, VkFence>
{ {
public: public:
......
...@@ -470,6 +470,30 @@ TEST_P(SimpleOperationTest, LinkProgramWithTexture) ...@@ -470,6 +470,30 @@ TEST_P(SimpleOperationTest, LinkProgramWithTexture)
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
} }
// Creates a program with a texture and renders with it.
TEST_P(SimpleOperationTest, DrawWithTexture)
{
std::array<GLColor, 4> colors = {
{GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
GLTexture tex;
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
draw2DTexturedQuad(0.5f, 1.0f, true);
EXPECT_GL_NO_ERROR();
int w = getWindowWidth() - 2;
int h = getWindowHeight() - 2;
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
EXPECT_PIXEL_COLOR_EQ(w, 0, GLColor::green);
EXPECT_PIXEL_COLOR_EQ(0, h, GLColor::blue);
EXPECT_PIXEL_COLOR_EQ(w, h, GLColor::yellow);
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against. // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
ANGLE_INSTANTIATE_TEST(SimpleOperationTest, ANGLE_INSTANTIATE_TEST(SimpleOperationTest,
ES2_D3D9(), ES2_D3D9(),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment