Vulkan: Implement shader compilation.
This hooks up the Vulkan GLSL, decorated with locations, to glslang,
and then pipes the SPIRV back to the Program implementation for later
use when making pipelines to run draw calls.
The program compilation tests work now, but don't really test
anything other than not generating Vulkan validation layer errors
during compilation and shader object generation.
BUG=angleproject:1576
Change-Id: I625e42219f4b4d1433dd3109b94e1a2f666ba4bd
Reviewed-on: https://chromium-review.googlesource.com/408519
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/renderer/vulkan/ProgramVk.cpp b/src/libANGLE/renderer/vulkan/ProgramVk.cpp
index aa178ef..92868c8 100644
--- a/src/libANGLE/renderer/vulkan/ProgramVk.cpp
+++ b/src/libANGLE/renderer/vulkan/ProgramVk.cpp
@@ -10,6 +10,9 @@
#include "libANGLE/renderer/vulkan/ProgramVk.h"
#include "common/debug.h"
+#include "libANGLE/renderer/vulkan/ContextVk.h"
+#include "libANGLE/renderer/vulkan/GlslangWrapper.h"
+#include "libANGLE/renderer/vulkan/RendererVk.h"
namespace rx
{
@@ -41,12 +44,56 @@
UNIMPLEMENTED();
}
-LinkResult ProgramVk::link(const gl::ContextState &data,
+LinkResult ProgramVk::link(ContextImpl *contextImpl,
const gl::VaryingPacking &packing,
gl::InfoLog &infoLog)
{
- UNIMPLEMENTED();
- return gl::Error(GL_INVALID_OPERATION);
+ ContextVk *context = GetAs<ContextVk>(contextImpl);
+ RendererVk *renderer = context->getRenderer();
+ GlslangWrapper *glslangWrapper = renderer->getGlslangWrapper();
+
+ const std::string &vertexSource = mState.getAttachedVertexShader()->getTranslatedSource();
+ const std::string &fragmentSource = mState.getAttachedFragmentShader()->getTranslatedSource();
+
+ std::vector<uint32_t> vertexCode;
+ std::vector<uint32_t> fragmentCode;
+ bool linkSuccess = false;
+ ANGLE_TRY_RESULT(
+ glslangWrapper->linkProgram(vertexSource, fragmentSource, &vertexCode, &fragmentCode),
+ linkSuccess);
+ if (!linkSuccess)
+ {
+ return false;
+ }
+
+ vk::ShaderModule vertexModule(renderer->getDevice());
+ vk::ShaderModule fragmentModule(renderer->getDevice());
+
+ {
+ VkShaderModuleCreateInfo vertexShaderInfo;
+ vertexShaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
+ vertexShaderInfo.pNext = nullptr;
+ vertexShaderInfo.flags = 0;
+ vertexShaderInfo.codeSize = vertexCode.size() * sizeof(uint32_t);
+ vertexShaderInfo.pCode = vertexCode.data();
+ ANGLE_TRY(vertexModule.init(vertexShaderInfo));
+ }
+
+ {
+ VkShaderModuleCreateInfo fragmentShaderInfo;
+ fragmentShaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
+ fragmentShaderInfo.pNext = nullptr;
+ fragmentShaderInfo.flags = 0;
+ fragmentShaderInfo.codeSize = fragmentCode.size() * sizeof(uint32_t);
+ fragmentShaderInfo.pCode = fragmentCode.data();
+
+ ANGLE_TRY(fragmentModule.init(fragmentShaderInfo));
+ }
+
+ mLinkedVertexModule = std::move(vertexModule);
+ mLinkedFragmentModule = std::move(fragmentModule);
+
+ return true;
}
GLboolean ProgramVk::validate(const gl::Caps &caps, gl::InfoLog *infoLog)
@@ -213,4 +260,16 @@
UNIMPLEMENTED();
}
+const vk::ShaderModule &ProgramVk::getLinkedVertexModule() const
+{
+ ASSERT(mLinkedVertexModule.getHandle() != VK_NULL_HANDLE);
+ return mLinkedVertexModule;
+}
+
+const vk::ShaderModule &ProgramVk::getLinkedFragmentModule() const
+{
+ ASSERT(mLinkedFragmentModule.getHandle() != VK_NULL_HANDLE);
+ return mLinkedFragmentModule;
+}
+
} // namespace rx