Commit 242c4fe8 by Jamie Madill Committed by Commit Bot

Vulkan: Store ProgramVk shaders in ShaderInfo.

This encapsulates most of the logic for a Program into a helper class. Now we can store multiple instances of the Program's back-end to implement different shader behaviour at draw time. This will be useful for shader patching for OpenGL line segment raster. Bug: angleproject:2598 Change-Id: I800a737088574e28f3a4ec23b91c0cb2647e4e12 Reviewed-on: https://chromium-review.googlesource.com/1127302Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent b4927eb0
......@@ -185,16 +185,15 @@ gl::Error ContextVk::initPipeline(const gl::DrawCallParams &drawCallParams)
// Trigger draw call shader patching and fill out the pipeline desc.
const vk::ShaderAndSerial *vertexShaderAndSerial = nullptr;
const vk::ShaderAndSerial *fragmentShaderAndSerial = nullptr;
const vk::PipelineLayout *pipelineLayout = nullptr;
ANGLE_TRY(programVk->initShaders(this, drawCallParams, &vertexShaderAndSerial,
&fragmentShaderAndSerial));
&fragmentShaderAndSerial, &pipelineLayout));
mPipelineDesc->updateShaders(vertexShaderAndSerial->getSerial(),
fragmentShaderAndSerial->getSerial());
const vk::PipelineLayout &pipelineLayout = programVk->getPipelineLayout();
ANGLE_TRY(mRenderer->getPipeline(this, *vertexShaderAndSerial, *fragmentShaderAndSerial,
pipelineLayout, *mPipelineDesc, activeAttribLocationsMask,
*pipelineLayout, *mPipelineDesc, activeAttribLocationsMask,
&mCurrentPipeline));
return gl::NoError();
......@@ -262,30 +261,9 @@ gl::Error ContextVk::setupDraw(const gl::Context *context,
ASSERT(mCurrentPipeline && mCurrentPipeline->valid());
mCurrentPipeline->updateSerial(queueSerial);
// TODO(jmadill): Can probably use more dirty bits here.
ANGLE_TRY(programVk->updateUniforms(this));
ANGLE_TRY(programVk->updateTexturesDescriptorSet(this));
// Bind the graphics descriptor sets.
// TODO(jmadill): Handle multiple command buffers.
const auto &descriptorSets = programVk->getDescriptorSets();
const gl::RangeUI &usedRange = programVk->getUsedDescriptorSetRange();
const vk::PipelineLayout &pipelineLayout = programVk->getPipelineLayout();
if (!usedRange.empty())
{
ASSERT(!descriptorSets.empty());
(*commandBufferOut)
->bindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, usedRange.low(),
usedRange.length(), &descriptorSets[usedRange.low()],
programVk->getDynamicOffsetsCount(),
programVk->getDynamicOffsets());
}
(*commandBufferOut)
->bindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout,
kDriverUniformsDescriptorSetIndex, 1, &mDriverUniformsDescriptorSet, 0,
nullptr);
ANGLE_TRY(programVk->updateDescriptorSets(this, drawCallParams, mDriverUniformsDescriptorSet,
*commandBufferOut));
return gl::NoError();
}
......@@ -980,7 +958,7 @@ void ContextVk::handleError(VkResult errorCode, const char *file, unsigned int l
gl::Error ContextVk::updateActiveTextures(const gl::Context *context)
{
const auto &completeTextures = mState.getState().getCompleteTextureCache();
const gl::Program *program = mState.getState().getProgram();
const gl::Program *program = mState.getState().getProgram();
mActiveTextures.fill(nullptr);
......
......@@ -285,11 +285,12 @@ void GlslangWrapper::GetShaderSource(const gl::Context *glContext,
}
// static
gl::LinkResult GlslangWrapper::GetShaderCode(const gl::Caps &glCaps,
const std::string &vertexSource,
const std::string &fragmentSource,
std::vector<uint32_t> *vertexCodeOut,
std::vector<uint32_t> *fragmentCodeOut)
angle::Result GlslangWrapper::GetShaderCode(vk::Context *context,
const gl::Caps &glCaps,
const std::string &vertexSource,
const std::string &fragmentSource,
std::vector<uint32_t> *vertexCodeOut,
std::vector<uint32_t> *fragmentCodeOut)
{
std::array<const char *, 2> strings = {{vertexSource.c_str(), fragmentSource.c_str()}};
std::array<int, 2> lengths = {
......@@ -309,9 +310,10 @@ gl::LinkResult GlslangWrapper::GetShaderCode(const gl::Caps &glCaps,
vertexShader.parse(&builtInResources, 450, ECoreProfile, false, false, messages);
if (!vertexResult)
{
return gl::InternalError() << "Internal error parsing Vulkan vertex shader:\n"
<< vertexShader.getInfoLog() << "\n"
<< vertexShader.getInfoDebugLog() << "\n";
ERR() << "Internal error parsing Vulkan vertex shader:\n"
<< vertexShader.getInfoLog() << "\n"
<< vertexShader.getInfoDebugLog() << "\n";
ANGLE_VK_CHECK(context, false, VK_ERROR_INVALID_SHADER_NV);
}
glslang::TShader fragmentShader(EShLangFragment);
......@@ -321,9 +323,10 @@ gl::LinkResult GlslangWrapper::GetShaderCode(const gl::Caps &glCaps,
fragmentShader.parse(&builtInResources, 450, ECoreProfile, false, false, messages);
if (!fragmentResult)
{
return gl::InternalError() << "Internal error parsing Vulkan fragment shader:\n"
<< fragmentShader.getInfoLog() << "\n"
<< fragmentShader.getInfoDebugLog() << "\n";
ERR() << "Internal error parsing Vulkan fragment shader:\n"
<< fragmentShader.getInfoLog() << "\n"
<< fragmentShader.getInfoDebugLog() << "\n";
ANGLE_VK_CHECK(context, false, VK_ERROR_INVALID_SHADER_NV);
}
glslang::TProgram program;
......@@ -332,8 +335,8 @@ gl::LinkResult GlslangWrapper::GetShaderCode(const gl::Caps &glCaps,
bool linkResult = program.link(messages);
if (!linkResult)
{
return gl::InternalError() << "Internal error linking Vulkan shaders:\n"
<< program.getInfoLog() << "\n";
ERR() << "Internal error linking Vulkan shaders:\n" << program.getInfoLog() << "\n";
ANGLE_VK_CHECK(context, false, VK_ERROR_INVALID_SHADER_NV);
}
glslang::TIntermediate *vertexStage = program.getIntermediate(EShLangVertex);
......@@ -341,6 +344,6 @@ gl::LinkResult GlslangWrapper::GetShaderCode(const gl::Caps &glCaps,
glslang::GlslangToSpv(*vertexStage, *vertexCodeOut);
glslang::GlslangToSpv(*fragmentStage, *fragmentCodeOut);
return true;
return angle::Result::Continue();
}
} // namespace rx
......@@ -10,6 +10,7 @@
#define LIBANGLE_RENDERER_VULKAN_GLSLANG_WRAPPER_H_
#include "libANGLE/renderer/ProgramImpl.h"
#include "libANGLE/renderer/vulkan/vk_utils.h"
namespace rx
{
......@@ -27,11 +28,12 @@ class GlslangWrapper
std::string *vertexSourceOut,
std::string *fragmentSourceOut);
static gl::LinkResult GetShaderCode(const gl::Caps &glCaps,
const std::string &vertexSource,
const std::string &fragmentSource,
std::vector<uint32_t> *vertexCodeOut,
std::vector<uint32_t> *fragmentCodeOut);
static angle::Result GetShaderCode(vk::Context *context,
const gl::Caps &glCaps,
const std::string &vertexSource,
const std::string &fragmentSource,
std::vector<uint32_t> *vertexCodeOut,
std::vector<uint32_t> *fragmentCodeOut);
};
} // namespace rx
......
......@@ -26,13 +26,11 @@ namespace
constexpr size_t kUniformBlockDynamicBufferMinSize = 256 * 128;
void InitDefaultUniformBlock(const gl::Context *context,
void InitDefaultUniformBlock(const std::vector<sh::Uniform> &uniforms,
gl::Shader *shader,
sh::BlockLayoutMap *blockLayoutMapOut,
size_t *blockSizeOut)
{
const auto &uniforms = shader->getUniforms(context);
if (uniforms.empty())
{
*blockSizeOut = 0;
......@@ -132,37 +130,70 @@ angle::Result SyncDefaultUniformBlock(ContextVk *contextVk,
}
} // anonymous namespace
// ProgramVk::ShaderInfo implementation.
ProgramVk::ShaderInfo::ShaderInfo()
{
}
ProgramVk::ShaderInfo::~ShaderInfo() = default;
angle::Result ProgramVk::ShaderInfo::getShaders(
ContextVk *contextVk,
const std::string &vertexSource,
const std::string &fragmentSource,
const vk::ShaderAndSerial **vertexShaderAndSerialOut,
const vk::ShaderAndSerial **fragmentShaderAndSerialOut)
{
if (!valid())
{
std::vector<uint32_t> vertexCode;
std::vector<uint32_t> fragmentCode;
ANGLE_TRY(GlslangWrapper::GetShaderCode(contextVk, contextVk->getCaps(), vertexSource,
fragmentSource, &vertexCode, &fragmentCode));
ANGLE_TRY(vk::InitShaderAndSerial(contextVk, &mVertexShaderAndSerial, vertexCode.data(),
vertexCode.size() * sizeof(uint32_t)));
ANGLE_TRY(vk::InitShaderAndSerial(contextVk, &mFragmentShaderAndSerial, fragmentCode.data(),
fragmentCode.size() * sizeof(uint32_t)));
}
*fragmentShaderAndSerialOut = &mFragmentShaderAndSerial;
*vertexShaderAndSerialOut = &mVertexShaderAndSerial;
return angle::Result::Continue();
}
void ProgramVk::ShaderInfo::destroy(VkDevice device)
{
mVertexShaderAndSerial.destroy(device);
mFragmentShaderAndSerial.destroy(device);
}
bool ProgramVk::ShaderInfo::valid() const
{
return mVertexShaderAndSerial.valid();
}
// ProgramVk implementation.
ProgramVk::DefaultUniformBlock::DefaultUniformBlock()
: storage(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
kUniformBlockDynamicBufferMinSize),
uniformData(),
uniformsDirty(false),
uniformLayout()
uniformsDirty(false)
{
}
ProgramVk::DefaultUniformBlock::~DefaultUniformBlock()
{
}
ProgramVk::DefaultUniformBlock::~DefaultUniformBlock() = default;
ProgramVk::ProgramVk(const gl::ProgramState &state)
: ProgramImpl(state),
mDefaultUniformBlocks(),
mUniformBlocksOffsets(),
mUsedDescriptorSetRange(),
mDirtyTextures(true)
: ProgramImpl(state), mUniformBlocksOffsets{}, mDirtyTextures(false)
{
mUniformBlocksOffsets.fill(0);
mUsedDescriptorSetRange.invalidate();
}
ProgramVk::~ProgramVk()
{
}
ProgramVk::~ProgramVk() = default;
gl::Error ProgramVk::destroy(const gl::Context *contextImpl)
gl::Error ProgramVk::destroy(const gl::Context *context)
{
ContextVk *contextVk = vk::GetImpl(contextImpl);
ContextVk *contextVk = vk::GetImpl(context);
return reset(contextVk);
}
......@@ -182,13 +213,13 @@ angle::Result ProgramVk::reset(ContextVk *contextVk)
uniformBlock.storage.release(renderer);
}
// TODO(jmadill): Line rasterization emulation shaders. http://anglebug.com/2598
mDefaultShaderInfo.destroy(device);
Serial currentSerial = renderer->getCurrentQueueSerial();
renderer->releaseObject(currentSerial, &mEmptyUniformBlockStorage.memory);
renderer->releaseObject(currentSerial, &mEmptyUniformBlockStorage.buffer);
mDefaultVertexShaderAndSerial.destroy(device);
mDefaultFragmentShaderAndSerial.destroy(device);
mDescriptorSets.clear();
mUsedDescriptorSetRange.invalidate();
mDirtyTextures = false;
......@@ -196,7 +227,7 @@ angle::Result ProgramVk::reset(ContextVk *contextVk)
return angle::Result::Continue();
}
gl::LinkResult ProgramVk::load(const gl::Context *contextImpl,
gl::LinkResult ProgramVk::load(const gl::Context *context,
gl::InfoLog &infoLog,
gl::BinaryInputStream *stream)
{
......@@ -228,25 +259,7 @@ gl::LinkResult ProgramVk::link(const gl::Context *glContext,
ANGLE_TRY(reset(contextVk));
std::string vertexSource;
std::string fragmentSource;
GlslangWrapper::GetShaderSource(glContext, mState, resources, &vertexSource, &fragmentSource);
std::vector<uint32_t> vertexCode;
std::vector<uint32_t> fragmentCode;
bool linkSuccess = false;
ANGLE_TRY_RESULT(GlslangWrapper::GetShaderCode(glContext->getCaps(), vertexSource,
fragmentSource, &vertexCode, &fragmentCode),
linkSuccess);
if (!linkSuccess)
{
return false;
}
ANGLE_TRY(vk::InitShaderAndSerial(contextVk, &mDefaultVertexShaderAndSerial, vertexCode.data(),
vertexCode.size() * sizeof(uint32_t)));
ANGLE_TRY(vk::InitShaderAndSerial(contextVk, &mDefaultFragmentShaderAndSerial,
fragmentCode.data(), fragmentCode.size() * sizeof(uint32_t)));
GlslangWrapper::GetShaderSource(glContext, mState, resources, &mVertexSource, &mFragmentSource);
ANGLE_TRY(initDefaultUniformBlocks(glContext));
......@@ -298,10 +311,28 @@ gl::LinkResult ProgramVk::link(const gl::Context *glContext,
ANGLE_TRY(renderer->getPipelineLayout(contextVk, pipelineLayoutDesc, mDescriptorSetLayouts,
&mPipelineLayout));
if (!mState.getUniforms().empty())
{
const gl::RangeUI &samplerRange = mState.getSamplerUniformRange();
if (mState.getUniforms().size() > samplerRange.length())
{
// Ensure the descriptor set range includes the uniform buffers at position 0.
mUsedDescriptorSetRange.extend(kUniformsDescriptorSetIndex);
}
if (!samplerRange.empty())
{
// Ensure the descriptor set range includes the textures at position 1.
mUsedDescriptorSetRange.extend(kTextureDescriptorSetIndex);
mDirtyTextures = true;
}
}
return true;
}
gl::Error ProgramVk::initDefaultUniformBlocks(const gl::Context *glContext)
angle::Result ProgramVk::initDefaultUniformBlocks(const gl::Context *glContext)
{
ContextVk *contextVk = vk::GetImpl(glContext);
RendererVk *renderer = contextVk->getRenderer();
......@@ -314,18 +345,18 @@ gl::Error ProgramVk::initDefaultUniformBlocks(const gl::Context *glContext)
for (vk::ShaderType shaderType : vk::AllShaderTypes())
{
gl::ShaderType glShaderType = static_cast<gl::ShaderType>(shaderType);
InitDefaultUniformBlock(glContext, mState.getAttachedShader(glShaderType),
&layoutMap[shaderType], &requiredBufferSize[shaderType]);
gl::Shader *shader = mState.getAttachedShader(glShaderType);
const std::vector<sh::Uniform> &uniforms = shader->getUniforms(glContext);
InitDefaultUniformBlock(uniforms, shader, &layoutMap[shaderType],
&requiredBufferSize[shaderType]);
}
// Init the default block layout info.
const auto &locations = mState.getUniformLocations();
const auto &uniforms = mState.getUniforms();
for (size_t locationIndex = 0; locationIndex < locations.size(); ++locationIndex)
for (const gl::VariableLocation &location : mState.getUniformLocations())
{
vk::ShaderMap<sh::BlockMemberInfo> layoutInfo;
const auto &location = locations[locationIndex];
if (location.used() && !location.ignored)
{
const auto &uniform = uniforms[location.index];
......@@ -371,7 +402,7 @@ gl::Error ProgramVk::initDefaultUniformBlocks(const gl::Context *glContext)
if (!mDefaultUniformBlocks[shaderType].uniformData.resize(
requiredBufferSize[shaderType]))
{
return gl::OutOfMemory() << "Memory allocation failure.";
ANGLE_VK_CHECK(contextVk, false, VK_ERROR_OUT_OF_HOST_MEMORY);
}
size_t minAlignment = static_cast<size_t>(
renderer->getPhysicalDeviceProperties().limits.minUniformBufferOffsetAlignment);
......@@ -413,12 +444,9 @@ gl::Error ProgramVk::initDefaultUniformBlocks(const gl::Context *glContext)
ANGLE_TRY(AllocateBufferMemory(contextVk, flags, &mEmptyUniformBlockStorage.buffer,
&mEmptyUniformBlockStorage.memory));
}
// Ensure the descriptor set range includes the uniform buffers at position 0.
mUsedDescriptorSetRange.extend(0);
}
return gl::NoError();
return angle::Result::Continue();
}
GLboolean ProgramVk::validate(const gl::Caps &caps, gl::InfoLog *infoLog)
......@@ -699,18 +727,20 @@ void ProgramVk::setPathFragmentInputGen(const std::string &inputName,
UNIMPLEMENTED();
}
gl::Error ProgramVk::initShaders(const ContextVk *contextVk,
const gl::DrawCallParams &drawCallParams,
const vk::ShaderAndSerial **vertexShaderAndSerialOut,
const vk::ShaderAndSerial **fragmentShaderAndSerialOut)
angle::Result ProgramVk::initShaders(ContextVk *contextVk,
const gl::DrawCallParams &drawCallParams,
const vk::ShaderAndSerial **vertexShaderAndSerialOut,
const vk::ShaderAndSerial **fragmentShaderAndSerialOut,
const vk::PipelineLayout **pipelineLayoutOut)
{
// TODO(jmadill): Move more init into this method. http://anglebug.com/2598
// TODO(jmadill): Line rasterization emulation shaders. http://anglebug.com/2598
ASSERT(mDefaultVertexShaderAndSerial.valid());
ASSERT(mDefaultFragmentShaderAndSerial.valid());
*vertexShaderAndSerialOut = &mDefaultVertexShaderAndSerial;
*fragmentShaderAndSerialOut = &mDefaultFragmentShaderAndSerial;
return gl::NoError();
ANGLE_TRY(mDefaultShaderInfo.getShaders(contextVk, mVertexSource, mFragmentSource,
vertexShaderAndSerialOut, fragmentShaderAndSerialOut));
ASSERT(mDefaultShaderInfo.valid());
*pipelineLayoutOut = &mPipelineLayout.get();
return angle::Result::Continue();
}
angle::Result ProgramVk::allocateDescriptorSet(ContextVk *contextVk, uint32_t descriptorSetIndex)
......@@ -755,10 +785,7 @@ angle::Result ProgramVk::updateUniforms(ContextVk *contextVk)
return angle::Result::Continue();
}
ASSERT(mUsedDescriptorSetRange.contains(0));
// Update buffer memory by immediate mapping. This immediate update only works once.
// TODO(jmadill): Handle inserting updates into the command stream, or use dynamic buffers.
bool anyNewBufferAllocated = false;
for (vk::ShaderType shaderType : vk::AllShaderTypes())
{
......@@ -797,9 +824,9 @@ angle::Result ProgramVk::updateDefaultUniformsDescriptorSet(ContextVk *contextVk
for (vk::ShaderType shaderType : vk::AllShaderTypes())
{
auto &uniformBlock = mDefaultUniformBlocks[shaderType];
auto &bufferInfo = descriptorBufferInfo[shaderType];
auto &writeInfo = writeDescriptorInfo[shaderType];
DefaultUniformBlock &uniformBlock = mDefaultUniformBlocks[shaderType];
VkDescriptorBufferInfo &bufferInfo = descriptorBufferInfo[shaderType];
VkWriteDescriptorSet &writeInfo = writeDescriptorInfo[shaderType];
if (!uniformBlock.uniformData.empty())
{
......@@ -832,34 +859,6 @@ angle::Result ProgramVk::updateDefaultUniformsDescriptorSet(ContextVk *contextVk
return angle::Result::Continue();
}
const std::vector<VkDescriptorSet> &ProgramVk::getDescriptorSets() const
{
return mDescriptorSets;
}
const uint32_t *ProgramVk::getDynamicOffsets()
{
// If we have no descriptor set being used, we do not need to specify any offsets when binding
// the descriptor sets.
if (!mUsedDescriptorSetRange.contains(0))
return nullptr;
return mUniformBlocksOffsets.data();
}
uint32_t ProgramVk::getDynamicOffsetsCount()
{
if (!mUsedDescriptorSetRange.contains(0))
return 0;
return static_cast<uint32_t>(mUniformBlocksOffsets.size());
}
const gl::RangeUI &ProgramVk::getUsedDescriptorSetRange() const
{
return mUsedDescriptorSetRange;
}
angle::Result ProgramVk::updateTexturesDescriptorSet(ContextVk *contextVk)
{
if (mState.getSamplerBindings().empty() || !mDirtyTextures)
......@@ -929,11 +928,6 @@ void ProgramVk::invalidateTextures()
mDirtyTextures = true;
}
const vk::PipelineLayout &ProgramVk::getPipelineLayout() const
{
return mPipelineLayout.get();
}
void ProgramVk::setDefaultUniformBlocksMinSizeForTesting(size_t minSize)
{
for (DefaultUniformBlock &block : mDefaultUniformBlocks)
......@@ -941,4 +935,43 @@ void ProgramVk::setDefaultUniformBlocksMinSizeForTesting(size_t minSize)
block.storage.setMinimumSizeForTesting(minSize);
}
}
angle::Result ProgramVk::updateDescriptorSets(ContextVk *contextVk,
const gl::DrawCallParams &drawCallParams,
VkDescriptorSet driverUniformsDescriptorSet,
vk::CommandBuffer *commandBuffer)
{
// TODO(jmadill): Line rasterization emulation shaders. http://anglebug.com/2598
// Can probably use better dirty bits here.
ANGLE_TRY(updateUniforms(contextVk));
ANGLE_TRY(updateTexturesDescriptorSet(contextVk));
commandBuffer->bindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, mPipelineLayout.get(),
kDriverUniformsDescriptorSetIndex, 1,
&driverUniformsDescriptorSet, 0, nullptr);
if (mUsedDescriptorSetRange.empty())
return angle::Result::Continue();
ASSERT(!mDescriptorSets.empty());
unsigned int low = mUsedDescriptorSetRange.low();
// No uniforms descriptor set means no need to specify dynamic buffer offsets.
if (mUsedDescriptorSetRange.contains(kUniformsDescriptorSetIndex))
{
commandBuffer->bindDescriptorSets(
VK_PIPELINE_BIND_POINT_GRAPHICS, mPipelineLayout.get(), low,
mUsedDescriptorSetRange.length(), &mDescriptorSets[low],
static_cast<uint32_t>(mUniformBlocksOffsets.size()), mUniformBlocksOffsets.data());
}
else
{
commandBuffer->bindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, mPipelineLayout.get(),
low, mUsedDescriptorSetRange.length(),
&mDescriptorSets[low], 0, nullptr);
}
return angle::Result::Continue();
}
} // namespace rx
......@@ -12,7 +12,6 @@
#include <array>
#include "libANGLE/Constants.h"
#include "libANGLE/renderer/ProgramImpl.h"
#include "libANGLE/renderer/vulkan/RendererVk.h"
#include "libANGLE/renderer/vulkan/vk_helpers.h"
......@@ -100,29 +99,20 @@ class ProgramVk : public ProgramImpl
const GLfloat *coeffs) override;
// Also initializes the pipeline layout, descriptor set layouts, and used descriptor ranges.
gl::Error initShaders(const ContextVk *contextVk,
const gl::DrawCallParams &drawCallParams,
const vk::ShaderAndSerial **vertexShaderAndSerialOut,
const vk::ShaderAndSerial **fragmentShaderAndSerialOut);
angle::Result initShaders(ContextVk *contextVk,
const gl::DrawCallParams &drawCallParams,
const vk::ShaderAndSerial **vertexShaderAndSerialOut,
const vk::ShaderAndSerial **fragmentShaderAndSerialOut,
const vk::PipelineLayout **pipelineLayoutOut);
angle::Result updateUniforms(ContextVk *contextVk);
const std::vector<VkDescriptorSet> &getDescriptorSets() const;
const uint32_t *getDynamicOffsets();
uint32_t getDynamicOffsetsCount();
// 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.
// This allows us to skip binding blank descriptor sets when the Program doesn't use Uniforms
// or Textures.
const gl::RangeUI &getUsedDescriptorSetRange() const;
angle::Result updateTexturesDescriptorSet(ContextVk *contextVk);
void invalidateTextures();
const vk::PipelineLayout &getPipelineLayout() const;
angle::Result updateDescriptorSets(ContextVk *contextVk,
const gl::DrawCallParams &drawCallParams,
VkDescriptorSet driverUniformsDescriptorSet,
vk::CommandBuffer *commandBuffer);
// For testing only.
void setDefaultUniformBlocksMinSizeForTesting(size_t minSize);
......@@ -136,8 +126,10 @@ class ProgramVk : public ProgramImpl
angle::Result reset(ContextVk *contextVk);
angle::Result allocateDescriptorSet(ContextVk *contextVk, uint32_t descriptorSetIndex);
gl::Error initDefaultUniformBlocks(const gl::Context *glContext);
angle::Result initDefaultUniformBlocks(const gl::Context *glContext);
angle::Result updateDefaultUniformsDescriptorSet(ContextVk *contextVk);
angle::Result updateTexturesDescriptorSet(ContextVk *contextVk);
template <class T>
void getUniformImpl(GLint location, T *v, GLenum entryPointType) const;
......@@ -145,9 +137,6 @@ class ProgramVk : public ProgramImpl
template <typename T>
void setUniformImpl(GLint location, GLsizei count, const T *v, GLenum entryPointType);
vk::ShaderAndSerial mDefaultVertexShaderAndSerial;
vk::ShaderAndSerial mDefaultFragmentShaderAndSerial;
// State for the default uniform blocks.
struct DefaultUniformBlock final : private angle::NonCopyable
{
......@@ -182,6 +171,32 @@ class ProgramVk : public ProgramImpl
// deleted while this program is in use.
vk::BindingPointer<vk::PipelineLayout> mPipelineLayout;
vk::DescriptorSetLayoutPointerArray mDescriptorSetLayouts;
class ShaderInfo final : angle::NonCopyable
{
public:
ShaderInfo();
~ShaderInfo();
angle::Result getShaders(ContextVk *contextVk,
const std::string &vertexSource,
const std::string &fragmentSource,
const vk::ShaderAndSerial **vertexShaderAndSerialOut,
const vk::ShaderAndSerial **fragmentShaderAndSerialOut);
void destroy(VkDevice device);
bool valid() const;
private:
vk::ShaderAndSerial mVertexShaderAndSerial;
vk::ShaderAndSerial mFragmentShaderAndSerial;
};
// TODO(jmadill): Line rasterization emulation shaders. http://anglebug.com/2598
ShaderInfo mDefaultShaderInfo;
// We keep the translated linked shader sources to use with shader draw call patching.
std::string mVertexSource;
std::string mFragmentSource;
};
} // namespace rx
......
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