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 |