Chromium Code Reviews| 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..3797648a396578a97ee9ce284b4525cd643b4636 |
| --- /dev/null |
| +++ b/gpu/vulkan/vulkan_shader_module.cc |
| @@ -0,0 +1,155 @@ |
| +// 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 "gpu/vulkan/vulkan_device_queue.h" |
| + |
| +class ShaderCCompiler { |
|
piman
2016/05/16 23:35:31
Move this into an anonymous namespace, to avoid po
David Yen
2016/05/17 18:13:57
Done.
|
| + 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 std::unique_ptr<ShaderCCompiler::CompilationResult>( |
|
piman
2016/05/16 23:35:31
nit: you can use base::MakeUnique<CompilationResul
David Yen
2016/05/17 18:13:57
Done.
|
| + new 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 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, |
| + const std::string& name, |
| + const std::string& entry_point, |
| + const 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, name, entry_point, |
| + compilation_result->GetResult()); |
| +} |
| + |
| +bool VulkanShaderModule::InitializeSPIRV(ShaderType type, |
| + const std::string& name, |
| + const std::string& entry_point, |
| + const std::string& source) { |
| + DCHECK_EQ(static_cast<VkShaderModule>(VK_NULL_HANDLE), handle_); |
| + shader_type_ = type; |
| + name_ = name; |
| + entry_point_ = entry_point; |
| + |
| + std::string aligned_source; |
| + |
| + VkShaderModuleCreateInfo shader_module_create_info = {}; |
| + shader_module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; |
| + const int source_mod = source.length() % 4; |
| + if (source_mod != 0) { |
| + aligned_source = entry_point; |
|
piman
2016/05/16 23:35:31
Did you mean aligned_source = source?
David Yen
2016/05/17 18:13:57
Oops, done.
|
| + for (int i = 0; i < (4 - source_mod); ++i) { |
| + aligned_source += ' '; |
| + } |
| + shader_module_create_info.pCode = |
| + reinterpret_cast<const uint32_t*>(aligned_source.c_str()); |
| + shader_module_create_info.codeSize = aligned_source.length() / 4; |
| + } else { |
| + 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; |
| + } |
| + |
| + shader_type_ = ShaderType::INVALID; |
| + entry_point_.clear(); |
| + error_messages_.clear(); |
| +} |
| + |
| +} // namespace gpu |