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) ...@@ -185,16 +185,15 @@ gl::Error ContextVk::initPipeline(const gl::DrawCallParams &drawCallParams)
// Trigger draw call shader patching and fill out the pipeline desc. // Trigger draw call shader patching and fill out the pipeline desc.
const vk::ShaderAndSerial *vertexShaderAndSerial = nullptr; const vk::ShaderAndSerial *vertexShaderAndSerial = nullptr;
const vk::ShaderAndSerial *fragmentShaderAndSerial = nullptr; const vk::ShaderAndSerial *fragmentShaderAndSerial = nullptr;
const vk::PipelineLayout *pipelineLayout = nullptr;
ANGLE_TRY(programVk->initShaders(this, drawCallParams, &vertexShaderAndSerial, ANGLE_TRY(programVk->initShaders(this, drawCallParams, &vertexShaderAndSerial,
&fragmentShaderAndSerial)); &fragmentShaderAndSerial, &pipelineLayout));
mPipelineDesc->updateShaders(vertexShaderAndSerial->getSerial(), mPipelineDesc->updateShaders(vertexShaderAndSerial->getSerial(),
fragmentShaderAndSerial->getSerial()); fragmentShaderAndSerial->getSerial());
const vk::PipelineLayout &pipelineLayout = programVk->getPipelineLayout();
ANGLE_TRY(mRenderer->getPipeline(this, *vertexShaderAndSerial, *fragmentShaderAndSerial, ANGLE_TRY(mRenderer->getPipeline(this, *vertexShaderAndSerial, *fragmentShaderAndSerial,
pipelineLayout, *mPipelineDesc, activeAttribLocationsMask, *pipelineLayout, *mPipelineDesc, activeAttribLocationsMask,
&mCurrentPipeline)); &mCurrentPipeline));
return gl::NoError(); return gl::NoError();
...@@ -262,30 +261,9 @@ gl::Error ContextVk::setupDraw(const gl::Context *context, ...@@ -262,30 +261,9 @@ gl::Error ContextVk::setupDraw(const gl::Context *context,
ASSERT(mCurrentPipeline && mCurrentPipeline->valid()); ASSERT(mCurrentPipeline && mCurrentPipeline->valid());
mCurrentPipeline->updateSerial(queueSerial); 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. // Bind the graphics descriptor sets.
// TODO(jmadill): Handle multiple command buffers. ANGLE_TRY(programVk->updateDescriptorSets(this, drawCallParams, mDriverUniformsDescriptorSet,
const auto &descriptorSets = programVk->getDescriptorSets(); *commandBufferOut));
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);
return gl::NoError(); return gl::NoError();
} }
......
...@@ -285,7 +285,8 @@ void GlslangWrapper::GetShaderSource(const gl::Context *glContext, ...@@ -285,7 +285,8 @@ void GlslangWrapper::GetShaderSource(const gl::Context *glContext,
} }
// static // static
gl::LinkResult GlslangWrapper::GetShaderCode(const gl::Caps &glCaps, angle::Result GlslangWrapper::GetShaderCode(vk::Context *context,
const gl::Caps &glCaps,
const std::string &vertexSource, const std::string &vertexSource,
const std::string &fragmentSource, const std::string &fragmentSource,
std::vector<uint32_t> *vertexCodeOut, std::vector<uint32_t> *vertexCodeOut,
...@@ -309,9 +310,10 @@ gl::LinkResult GlslangWrapper::GetShaderCode(const gl::Caps &glCaps, ...@@ -309,9 +310,10 @@ gl::LinkResult GlslangWrapper::GetShaderCode(const gl::Caps &glCaps,
vertexShader.parse(&builtInResources, 450, ECoreProfile, false, false, messages); vertexShader.parse(&builtInResources, 450, ECoreProfile, false, false, messages);
if (!vertexResult) if (!vertexResult)
{ {
return gl::InternalError() << "Internal error parsing Vulkan vertex shader:\n" ERR() << "Internal error parsing Vulkan vertex shader:\n"
<< vertexShader.getInfoLog() << "\n" << vertexShader.getInfoLog() << "\n"
<< vertexShader.getInfoDebugLog() << "\n"; << vertexShader.getInfoDebugLog() << "\n";
ANGLE_VK_CHECK(context, false, VK_ERROR_INVALID_SHADER_NV);
} }
glslang::TShader fragmentShader(EShLangFragment); glslang::TShader fragmentShader(EShLangFragment);
...@@ -321,9 +323,10 @@ gl::LinkResult GlslangWrapper::GetShaderCode(const gl::Caps &glCaps, ...@@ -321,9 +323,10 @@ gl::LinkResult GlslangWrapper::GetShaderCode(const gl::Caps &glCaps,
fragmentShader.parse(&builtInResources, 450, ECoreProfile, false, false, messages); fragmentShader.parse(&builtInResources, 450, ECoreProfile, false, false, messages);
if (!fragmentResult) if (!fragmentResult)
{ {
return gl::InternalError() << "Internal error parsing Vulkan fragment shader:\n" ERR() << "Internal error parsing Vulkan fragment shader:\n"
<< fragmentShader.getInfoLog() << "\n" << fragmentShader.getInfoLog() << "\n"
<< fragmentShader.getInfoDebugLog() << "\n"; << fragmentShader.getInfoDebugLog() << "\n";
ANGLE_VK_CHECK(context, false, VK_ERROR_INVALID_SHADER_NV);
} }
glslang::TProgram program; glslang::TProgram program;
...@@ -332,8 +335,8 @@ gl::LinkResult GlslangWrapper::GetShaderCode(const gl::Caps &glCaps, ...@@ -332,8 +335,8 @@ gl::LinkResult GlslangWrapper::GetShaderCode(const gl::Caps &glCaps,
bool linkResult = program.link(messages); bool linkResult = program.link(messages);
if (!linkResult) if (!linkResult)
{ {
return gl::InternalError() << "Internal error linking Vulkan shaders:\n" ERR() << "Internal error linking Vulkan shaders:\n" << program.getInfoLog() << "\n";
<< program.getInfoLog() << "\n"; ANGLE_VK_CHECK(context, false, VK_ERROR_INVALID_SHADER_NV);
} }
glslang::TIntermediate *vertexStage = program.getIntermediate(EShLangVertex); glslang::TIntermediate *vertexStage = program.getIntermediate(EShLangVertex);
...@@ -341,6 +344,6 @@ gl::LinkResult GlslangWrapper::GetShaderCode(const gl::Caps &glCaps, ...@@ -341,6 +344,6 @@ gl::LinkResult GlslangWrapper::GetShaderCode(const gl::Caps &glCaps,
glslang::GlslangToSpv(*vertexStage, *vertexCodeOut); glslang::GlslangToSpv(*vertexStage, *vertexCodeOut);
glslang::GlslangToSpv(*fragmentStage, *fragmentCodeOut); glslang::GlslangToSpv(*fragmentStage, *fragmentCodeOut);
return true; return angle::Result::Continue();
} }
} // namespace rx } // namespace rx
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#define LIBANGLE_RENDERER_VULKAN_GLSLANG_WRAPPER_H_ #define LIBANGLE_RENDERER_VULKAN_GLSLANG_WRAPPER_H_
#include "libANGLE/renderer/ProgramImpl.h" #include "libANGLE/renderer/ProgramImpl.h"
#include "libANGLE/renderer/vulkan/vk_utils.h"
namespace rx namespace rx
{ {
...@@ -27,7 +28,8 @@ class GlslangWrapper ...@@ -27,7 +28,8 @@ class GlslangWrapper
std::string *vertexSourceOut, std::string *vertexSourceOut,
std::string *fragmentSourceOut); std::string *fragmentSourceOut);
static gl::LinkResult GetShaderCode(const gl::Caps &glCaps, static angle::Result GetShaderCode(vk::Context *context,
const gl::Caps &glCaps,
const std::string &vertexSource, const std::string &vertexSource,
const std::string &fragmentSource, const std::string &fragmentSource,
std::vector<uint32_t> *vertexCodeOut, std::vector<uint32_t> *vertexCodeOut,
......
...@@ -26,13 +26,11 @@ namespace ...@@ -26,13 +26,11 @@ namespace
constexpr size_t kUniformBlockDynamicBufferMinSize = 256 * 128; constexpr size_t kUniformBlockDynamicBufferMinSize = 256 * 128;
void InitDefaultUniformBlock(const gl::Context *context, void InitDefaultUniformBlock(const std::vector<sh::Uniform> &uniforms,
gl::Shader *shader, gl::Shader *shader,
sh::BlockLayoutMap *blockLayoutMapOut, sh::BlockLayoutMap *blockLayoutMapOut,
size_t *blockSizeOut) size_t *blockSizeOut)
{ {
const auto &uniforms = shader->getUniforms(context);
if (uniforms.empty()) if (uniforms.empty())
{ {
*blockSizeOut = 0; *blockSizeOut = 0;
...@@ -132,37 +130,70 @@ angle::Result SyncDefaultUniformBlock(ContextVk *contextVk, ...@@ -132,37 +130,70 @@ angle::Result SyncDefaultUniformBlock(ContextVk *contextVk,
} }
} // anonymous namespace } // 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() ProgramVk::DefaultUniformBlock::DefaultUniformBlock()
: storage(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT, : storage(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
kUniformBlockDynamicBufferMinSize), kUniformBlockDynamicBufferMinSize),
uniformData(), uniformsDirty(false)
uniformsDirty(false),
uniformLayout()
{ {
} }
ProgramVk::DefaultUniformBlock::~DefaultUniformBlock() ProgramVk::DefaultUniformBlock::~DefaultUniformBlock() = default;
{
}
ProgramVk::ProgramVk(const gl::ProgramState &state) ProgramVk::ProgramVk(const gl::ProgramState &state)
: ProgramImpl(state), : ProgramImpl(state), mUniformBlocksOffsets{}, mDirtyTextures(false)
mDefaultUniformBlocks(),
mUniformBlocksOffsets(),
mUsedDescriptorSetRange(),
mDirtyTextures(true)
{ {
mUniformBlocksOffsets.fill(0);
mUsedDescriptorSetRange.invalidate(); 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); return reset(contextVk);
} }
...@@ -182,13 +213,13 @@ angle::Result ProgramVk::reset(ContextVk *contextVk) ...@@ -182,13 +213,13 @@ angle::Result ProgramVk::reset(ContextVk *contextVk)
uniformBlock.storage.release(renderer); uniformBlock.storage.release(renderer);
} }
// TODO(jmadill): Line rasterization emulation shaders. http://anglebug.com/2598
mDefaultShaderInfo.destroy(device);
Serial currentSerial = renderer->getCurrentQueueSerial(); Serial currentSerial = renderer->getCurrentQueueSerial();
renderer->releaseObject(currentSerial, &mEmptyUniformBlockStorage.memory); renderer->releaseObject(currentSerial, &mEmptyUniformBlockStorage.memory);
renderer->releaseObject(currentSerial, &mEmptyUniformBlockStorage.buffer); renderer->releaseObject(currentSerial, &mEmptyUniformBlockStorage.buffer);
mDefaultVertexShaderAndSerial.destroy(device);
mDefaultFragmentShaderAndSerial.destroy(device);
mDescriptorSets.clear(); mDescriptorSets.clear();
mUsedDescriptorSetRange.invalidate(); mUsedDescriptorSetRange.invalidate();
mDirtyTextures = false; mDirtyTextures = false;
...@@ -196,7 +227,7 @@ angle::Result ProgramVk::reset(ContextVk *contextVk) ...@@ -196,7 +227,7 @@ angle::Result ProgramVk::reset(ContextVk *contextVk)
return angle::Result::Continue(); return angle::Result::Continue();
} }
gl::LinkResult ProgramVk::load(const gl::Context *contextImpl, gl::LinkResult ProgramVk::load(const gl::Context *context,
gl::InfoLog &infoLog, gl::InfoLog &infoLog,
gl::BinaryInputStream *stream) gl::BinaryInputStream *stream)
{ {
...@@ -228,25 +259,7 @@ gl::LinkResult ProgramVk::link(const gl::Context *glContext, ...@@ -228,25 +259,7 @@ gl::LinkResult ProgramVk::link(const gl::Context *glContext,
ANGLE_TRY(reset(contextVk)); ANGLE_TRY(reset(contextVk));
std::string vertexSource; GlslangWrapper::GetShaderSource(glContext, mState, resources, &mVertexSource, &mFragmentSource);
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)));
ANGLE_TRY(initDefaultUniformBlocks(glContext)); ANGLE_TRY(initDefaultUniformBlocks(glContext));
...@@ -298,10 +311,28 @@ gl::LinkResult ProgramVk::link(const gl::Context *glContext, ...@@ -298,10 +311,28 @@ gl::LinkResult ProgramVk::link(const gl::Context *glContext,
ANGLE_TRY(renderer->getPipelineLayout(contextVk, pipelineLayoutDesc, mDescriptorSetLayouts, ANGLE_TRY(renderer->getPipelineLayout(contextVk, pipelineLayoutDesc, mDescriptorSetLayouts,
&mPipelineLayout)); &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; return true;
} }
gl::Error ProgramVk::initDefaultUniformBlocks(const gl::Context *glContext) angle::Result ProgramVk::initDefaultUniformBlocks(const gl::Context *glContext)
{ {
ContextVk *contextVk = vk::GetImpl(glContext); ContextVk *contextVk = vk::GetImpl(glContext);
RendererVk *renderer = contextVk->getRenderer(); RendererVk *renderer = contextVk->getRenderer();
...@@ -314,18 +345,18 @@ gl::Error ProgramVk::initDefaultUniformBlocks(const gl::Context *glContext) ...@@ -314,18 +345,18 @@ gl::Error ProgramVk::initDefaultUniformBlocks(const gl::Context *glContext)
for (vk::ShaderType shaderType : vk::AllShaderTypes()) for (vk::ShaderType shaderType : vk::AllShaderTypes())
{ {
gl::ShaderType glShaderType = static_cast<gl::ShaderType>(shaderType); gl::ShaderType glShaderType = static_cast<gl::ShaderType>(shaderType);
InitDefaultUniformBlock(glContext, mState.getAttachedShader(glShaderType), gl::Shader *shader = mState.getAttachedShader(glShaderType);
&layoutMap[shaderType], &requiredBufferSize[shaderType]); const std::vector<sh::Uniform> &uniforms = shader->getUniforms(glContext);
InitDefaultUniformBlock(uniforms, shader, &layoutMap[shaderType],
&requiredBufferSize[shaderType]);
} }
// Init the default block layout info. // Init the default block layout info.
const auto &locations = mState.getUniformLocations();
const auto &uniforms = mState.getUniforms(); 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; vk::ShaderMap<sh::BlockMemberInfo> layoutInfo;
const auto &location = locations[locationIndex];
if (location.used() && !location.ignored) if (location.used() && !location.ignored)
{ {
const auto &uniform = uniforms[location.index]; const auto &uniform = uniforms[location.index];
...@@ -371,7 +402,7 @@ gl::Error ProgramVk::initDefaultUniformBlocks(const gl::Context *glContext) ...@@ -371,7 +402,7 @@ gl::Error ProgramVk::initDefaultUniformBlocks(const gl::Context *glContext)
if (!mDefaultUniformBlocks[shaderType].uniformData.resize( if (!mDefaultUniformBlocks[shaderType].uniformData.resize(
requiredBufferSize[shaderType])) 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>( size_t minAlignment = static_cast<size_t>(
renderer->getPhysicalDeviceProperties().limits.minUniformBufferOffsetAlignment); renderer->getPhysicalDeviceProperties().limits.minUniformBufferOffsetAlignment);
...@@ -413,12 +444,9 @@ gl::Error ProgramVk::initDefaultUniformBlocks(const gl::Context *glContext) ...@@ -413,12 +444,9 @@ gl::Error ProgramVk::initDefaultUniformBlocks(const gl::Context *glContext)
ANGLE_TRY(AllocateBufferMemory(contextVk, flags, &mEmptyUniformBlockStorage.buffer, ANGLE_TRY(AllocateBufferMemory(contextVk, flags, &mEmptyUniformBlockStorage.buffer,
&mEmptyUniformBlockStorage.memory)); &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) GLboolean ProgramVk::validate(const gl::Caps &caps, gl::InfoLog *infoLog)
...@@ -699,18 +727,20 @@ void ProgramVk::setPathFragmentInputGen(const std::string &inputName, ...@@ -699,18 +727,20 @@ void ProgramVk::setPathFragmentInputGen(const std::string &inputName,
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
gl::Error ProgramVk::initShaders(const ContextVk *contextVk, angle::Result ProgramVk::initShaders(ContextVk *contextVk,
const gl::DrawCallParams &drawCallParams, const gl::DrawCallParams &drawCallParams,
const vk::ShaderAndSerial **vertexShaderAndSerialOut, const vk::ShaderAndSerial **vertexShaderAndSerialOut,
const vk::ShaderAndSerial **fragmentShaderAndSerialOut) 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 // TODO(jmadill): Line rasterization emulation shaders. http://anglebug.com/2598
ASSERT(mDefaultVertexShaderAndSerial.valid()); ANGLE_TRY(mDefaultShaderInfo.getShaders(contextVk, mVertexSource, mFragmentSource,
ASSERT(mDefaultFragmentShaderAndSerial.valid()); vertexShaderAndSerialOut, fragmentShaderAndSerialOut));
*vertexShaderAndSerialOut = &mDefaultVertexShaderAndSerial; ASSERT(mDefaultShaderInfo.valid());
*fragmentShaderAndSerialOut = &mDefaultFragmentShaderAndSerial;
return gl::NoError(); *pipelineLayoutOut = &mPipelineLayout.get();
return angle::Result::Continue();
} }
angle::Result ProgramVk::allocateDescriptorSet(ContextVk *contextVk, uint32_t descriptorSetIndex) angle::Result ProgramVk::allocateDescriptorSet(ContextVk *contextVk, uint32_t descriptorSetIndex)
...@@ -755,10 +785,7 @@ angle::Result ProgramVk::updateUniforms(ContextVk *contextVk) ...@@ -755,10 +785,7 @@ angle::Result ProgramVk::updateUniforms(ContextVk *contextVk)
return angle::Result::Continue(); return angle::Result::Continue();
} }
ASSERT(mUsedDescriptorSetRange.contains(0));
// Update buffer memory by immediate mapping. This immediate update only works once. // 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; bool anyNewBufferAllocated = false;
for (vk::ShaderType shaderType : vk::AllShaderTypes()) for (vk::ShaderType shaderType : vk::AllShaderTypes())
{ {
...@@ -797,9 +824,9 @@ angle::Result ProgramVk::updateDefaultUniformsDescriptorSet(ContextVk *contextVk ...@@ -797,9 +824,9 @@ angle::Result ProgramVk::updateDefaultUniformsDescriptorSet(ContextVk *contextVk
for (vk::ShaderType shaderType : vk::AllShaderTypes()) for (vk::ShaderType shaderType : vk::AllShaderTypes())
{ {
auto &uniformBlock = mDefaultUniformBlocks[shaderType]; DefaultUniformBlock &uniformBlock = mDefaultUniformBlocks[shaderType];
auto &bufferInfo = descriptorBufferInfo[shaderType]; VkDescriptorBufferInfo &bufferInfo = descriptorBufferInfo[shaderType];
auto &writeInfo = writeDescriptorInfo[shaderType]; VkWriteDescriptorSet &writeInfo = writeDescriptorInfo[shaderType];
if (!uniformBlock.uniformData.empty()) if (!uniformBlock.uniformData.empty())
{ {
...@@ -832,34 +859,6 @@ angle::Result ProgramVk::updateDefaultUniformsDescriptorSet(ContextVk *contextVk ...@@ -832,34 +859,6 @@ angle::Result ProgramVk::updateDefaultUniformsDescriptorSet(ContextVk *contextVk
return angle::Result::Continue(); 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) angle::Result ProgramVk::updateTexturesDescriptorSet(ContextVk *contextVk)
{ {
if (mState.getSamplerBindings().empty() || !mDirtyTextures) if (mState.getSamplerBindings().empty() || !mDirtyTextures)
...@@ -929,11 +928,6 @@ void ProgramVk::invalidateTextures() ...@@ -929,11 +928,6 @@ void ProgramVk::invalidateTextures()
mDirtyTextures = true; mDirtyTextures = true;
} }
const vk::PipelineLayout &ProgramVk::getPipelineLayout() const
{
return mPipelineLayout.get();
}
void ProgramVk::setDefaultUniformBlocksMinSizeForTesting(size_t minSize) void ProgramVk::setDefaultUniformBlocksMinSizeForTesting(size_t minSize)
{ {
for (DefaultUniformBlock &block : mDefaultUniformBlocks) for (DefaultUniformBlock &block : mDefaultUniformBlocks)
...@@ -941,4 +935,43 @@ void ProgramVk::setDefaultUniformBlocksMinSizeForTesting(size_t minSize) ...@@ -941,4 +935,43 @@ void ProgramVk::setDefaultUniformBlocksMinSizeForTesting(size_t minSize)
block.storage.setMinimumSizeForTesting(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 } // namespace rx
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
#include <array> #include <array>
#include "libANGLE/Constants.h"
#include "libANGLE/renderer/ProgramImpl.h" #include "libANGLE/renderer/ProgramImpl.h"
#include "libANGLE/renderer/vulkan/RendererVk.h" #include "libANGLE/renderer/vulkan/RendererVk.h"
#include "libANGLE/renderer/vulkan/vk_helpers.h" #include "libANGLE/renderer/vulkan/vk_helpers.h"
...@@ -100,29 +99,20 @@ class ProgramVk : public ProgramImpl ...@@ -100,29 +99,20 @@ class ProgramVk : public ProgramImpl
const GLfloat *coeffs) override; const GLfloat *coeffs) override;
// Also initializes the pipeline layout, descriptor set layouts, and used descriptor ranges. // Also initializes the pipeline layout, descriptor set layouts, and used descriptor ranges.
gl::Error initShaders(const ContextVk *contextVk, angle::Result initShaders(ContextVk *contextVk,
const gl::DrawCallParams &drawCallParams, const gl::DrawCallParams &drawCallParams,
const vk::ShaderAndSerial **vertexShaderAndSerialOut, const vk::ShaderAndSerial **vertexShaderAndSerialOut,
const vk::ShaderAndSerial **fragmentShaderAndSerialOut); const vk::ShaderAndSerial **fragmentShaderAndSerialOut,
const vk::PipelineLayout **pipelineLayoutOut);
angle::Result updateUniforms(ContextVk *contextVk); 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(); void invalidateTextures();
const vk::PipelineLayout &getPipelineLayout() const; angle::Result updateDescriptorSets(ContextVk *contextVk,
const gl::DrawCallParams &drawCallParams,
VkDescriptorSet driverUniformsDescriptorSet,
vk::CommandBuffer *commandBuffer);
// For testing only. // For testing only.
void setDefaultUniformBlocksMinSizeForTesting(size_t minSize); void setDefaultUniformBlocksMinSizeForTesting(size_t minSize);
...@@ -136,8 +126,10 @@ class ProgramVk : public ProgramImpl ...@@ -136,8 +126,10 @@ class ProgramVk : public ProgramImpl
angle::Result reset(ContextVk *contextVk); angle::Result reset(ContextVk *contextVk);
angle::Result allocateDescriptorSet(ContextVk *contextVk, uint32_t descriptorSetIndex); 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 updateDefaultUniformsDescriptorSet(ContextVk *contextVk);
angle::Result updateTexturesDescriptorSet(ContextVk *contextVk);
template <class T> template <class T>
void getUniformImpl(GLint location, T *v, GLenum entryPointType) const; void getUniformImpl(GLint location, T *v, GLenum entryPointType) const;
...@@ -145,9 +137,6 @@ class ProgramVk : public ProgramImpl ...@@ -145,9 +137,6 @@ class ProgramVk : public ProgramImpl
template <typename T> template <typename T>
void setUniformImpl(GLint location, GLsizei count, const T *v, GLenum entryPointType); void setUniformImpl(GLint location, GLsizei count, const T *v, GLenum entryPointType);
vk::ShaderAndSerial mDefaultVertexShaderAndSerial;
vk::ShaderAndSerial mDefaultFragmentShaderAndSerial;
// State for the default uniform blocks. // State for the default uniform blocks.
struct DefaultUniformBlock final : private angle::NonCopyable struct DefaultUniformBlock final : private angle::NonCopyable
{ {
...@@ -182,6 +171,32 @@ class ProgramVk : public ProgramImpl ...@@ -182,6 +171,32 @@ class ProgramVk : public ProgramImpl
// deleted while this program is in use. // deleted while this program is in use.
vk::BindingPointer<vk::PipelineLayout> mPipelineLayout; vk::BindingPointer<vk::PipelineLayout> mPipelineLayout;
vk::DescriptorSetLayoutPointerArray mDescriptorSetLayouts; 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 } // 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