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
......
......@@ -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