| Index: gpu/vulkan/vulkan_shader_module.cc
|
| diff --git a/gpu/vulkan/vulkan_shader_module.cc b/gpu/vulkan/vulkan_shader_module.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..4b13667e9599630f9f3780bd21a5d439eee0df85
|
| --- /dev/null
|
| +++ b/gpu/vulkan/vulkan_shader_module.cc
|
| @@ -0,0 +1,154 @@
|
| +// Copyright (c) 2016 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "gpu/vulkan/vulkan_shader_module.h"
|
| +
|
| +#include <memory>
|
| +#include <shaderc/shaderc.h>
|
| +#include <sstream>
|
| +
|
| +#include "base/logging.h"
|
| +#include "base/memory/ptr_util.h"
|
| +#include "gpu/vulkan/vulkan_device_queue.h"
|
| +
|
| +namespace {
|
| +
|
| +class ShaderCCompiler {
|
| + public:
|
| + class CompilationResult {
|
| + public:
|
| + explicit CompilationResult(shaderc_compilation_result_t compilation_result)
|
| + : compilation_result_(compilation_result) {}
|
| +
|
| + ~CompilationResult() { shaderc_result_release(compilation_result_); }
|
| +
|
| + bool IsValid() const {
|
| + return shaderc_compilation_status_success ==
|
| + shaderc_result_get_compilation_status(compilation_result_);
|
| + }
|
| +
|
| + std::string GetErrors() const {
|
| + return shaderc_result_get_error_message(compilation_result_);
|
| + }
|
| +
|
| + std::string GetResult() const {
|
| + return std::string(shaderc_result_get_bytes(compilation_result_),
|
| + shaderc_result_get_length(compilation_result_));
|
| + }
|
| +
|
| + private:
|
| + shaderc_compilation_result_t compilation_result_;
|
| + };
|
| +
|
| + ShaderCCompiler()
|
| + : compiler_(shaderc_compiler_initialize()),
|
| + compiler_options_(shaderc_compile_options_initialize()) {}
|
| +
|
| + ~ShaderCCompiler() { shaderc_compiler_release(compiler_); }
|
| +
|
| + void AddMacroDef(const std::string& name, const std::string& value) {
|
| + shaderc_compile_options_add_macro_definition(compiler_options_,
|
| + name.c_str(), name.length(),
|
| + value.c_str(), value.length());
|
| + }
|
| +
|
| + std::unique_ptr<ShaderCCompiler::CompilationResult> CompileShaderModule(
|
| + gpu::VulkanShaderModule::ShaderType shader_type,
|
| + const std::string& name,
|
| + const std::string& entry_point,
|
| + const std::string& source) {
|
| + return base::MakeUnique<ShaderCCompiler::CompilationResult>(
|
| + shaderc_compile_into_spv(
|
| + compiler_, source.c_str(), source.length(),
|
| + (shader_type == gpu::VulkanShaderModule::ShaderType::VERTEX
|
| + ? shaderc_glsl_vertex_shader
|
| + : shaderc_glsl_fragment_shader),
|
| + name.c_str(), entry_point.c_str(), compiler_options_));
|
| + }
|
| +
|
| + private:
|
| + shaderc_compiler_t compiler_;
|
| + shaderc_compile_options_t compiler_options_;
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +namespace gpu {
|
| +
|
| +VulkanShaderModule::VulkanShaderModule(VulkanDeviceQueue* device_queue)
|
| + : device_queue_(device_queue) {
|
| + DCHECK(device_queue_);
|
| +}
|
| +
|
| +VulkanShaderModule::~VulkanShaderModule() {
|
| + DCHECK_EQ(static_cast<VkShaderModule>(VK_NULL_HANDLE), handle_);
|
| +}
|
| +
|
| +bool VulkanShaderModule::InitializeGLSL(ShaderType type,
|
| + std::string name,
|
| + std::string entry_point,
|
| + std::string source) {
|
| + ShaderCCompiler shaderc_compiler;
|
| + std::unique_ptr<ShaderCCompiler::CompilationResult> compilation_result(
|
| + shaderc_compiler.CompileShaderModule(type, name, entry_point, source));
|
| +
|
| + if (!compilation_result->IsValid()) {
|
| + error_messages_ = compilation_result->GetErrors();
|
| + return false;
|
| + }
|
| +
|
| + return InitializeSPIRV(type, std::move(name), std::move(entry_point),
|
| + compilation_result->GetResult());
|
| +}
|
| +
|
| +bool VulkanShaderModule::InitializeSPIRV(ShaderType type,
|
| + std::string name,
|
| + std::string entry_point,
|
| + std::string source) {
|
| + DCHECK_EQ(static_cast<VkShaderModule>(VK_NULL_HANDLE), handle_);
|
| + shader_type_ = type;
|
| + name_ = std::move(name);
|
| + entry_point_ = std::move(entry_point);
|
| +
|
| + // Make sure source is a multiple of 4.
|
| + const int padding = 4 - (source.length() % 4);
|
| + if (padding < 4) {
|
| + for (int i = 0; i < padding; ++i) {
|
| + source += ' ';
|
| + }
|
| + }
|
| +
|
| + VkShaderModuleCreateInfo shader_module_create_info = {};
|
| + shader_module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
| + shader_module_create_info.pCode =
|
| + reinterpret_cast<const uint32_t*>(source.c_str());
|
| + shader_module_create_info.codeSize = source.length() / 4;
|
| +
|
| + VkShaderModule shader_module = VK_NULL_HANDLE;
|
| + VkResult result =
|
| + vkCreateShaderModule(device_queue_->GetVulkanDevice(),
|
| + &shader_module_create_info, nullptr, &shader_module);
|
| + if (VK_SUCCESS != result) {
|
| + std::stringstream ss;
|
| + ss << "vkCreateShaderModule() failed: " << result;
|
| + error_messages_ = ss.str();
|
| + DLOG(ERROR) << error_messages_;
|
| + return false;
|
| + }
|
| +
|
| + handle_ = shader_module;
|
| + return true;
|
| +}
|
| +
|
| +void VulkanShaderModule::Destroy() {
|
| + if (handle_ != VK_NULL_HANDLE) {
|
| + vkDestroyShaderModule(device_queue_->GetVulkanDevice(), handle_, nullptr);
|
| + handle_ = VK_NULL_HANDLE;
|
| + }
|
| +
|
| + entry_point_.clear();
|
| + error_messages_.clear();
|
| +}
|
| +
|
| +} // namespace gpu
|
|
|