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();
} }
...@@ -980,7 +958,7 @@ void ContextVk::handleError(VkResult errorCode, const char *file, unsigned int l ...@@ -980,7 +958,7 @@ void ContextVk::handleError(VkResult errorCode, const char *file, unsigned int l
gl::Error ContextVk::updateActiveTextures(const gl::Context *context) gl::Error ContextVk::updateActiveTextures(const gl::Context *context)
{ {
const auto &completeTextures = mState.getState().getCompleteTextureCache(); const auto &completeTextures = mState.getState().getCompleteTextureCache();
const gl::Program *program = mState.getState().getProgram(); const gl::Program *program = mState.getState().getProgram();
mActiveTextures.fill(nullptr); mActiveTextures.fill(nullptr);
......
...@@ -285,11 +285,12 @@ void GlslangWrapper::GetShaderSource(const gl::Context *glContext, ...@@ -285,11 +285,12 @@ 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 std::string &vertexSource, const gl::Caps &glCaps,
const std::string &fragmentSource, const std::string &vertexSource,
std::vector<uint32_t> *vertexCodeOut, const std::string &fragmentSource,
std::vector<uint32_t> *fragmentCodeOut) std::vector<uint32_t> *vertexCodeOut,
std::vector<uint32_t> *fragmentCodeOut)
{ {
std::array<const char *, 2> strings = {{vertexSource.c_str(), fragmentSource.c_str()}}; std::array<const char *, 2> strings = {{vertexSource.c_str(), fragmentSource.c_str()}};
std::array<int, 2> lengths = { std::array<int, 2> lengths = {
...@@ -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,11 +28,12 @@ class GlslangWrapper ...@@ -27,11 +28,12 @@ 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 std::string &vertexSource, const gl::Caps &glCaps,
const std::string &fragmentSource, const std::string &vertexSource,
std::vector<uint32_t> *vertexCodeOut, const std::string &fragmentSource,
std::vector<uint32_t> *fragmentCodeOut); std::vector<uint32_t> *vertexCodeOut,
std::vector<uint32_t> *fragmentCodeOut);
}; };
} // 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