Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "gpu/vulkan/vulkan_shader_module.h" | |
| 6 | |
| 7 #include <memory> | |
| 8 #include <shaderc/shaderc.h> | |
| 9 #include <sstream> | |
| 10 | |
| 11 #include "base/logging.h" | |
| 12 #include "base/memory/ptr_util.h" | |
| 13 #include "gpu/vulkan/vulkan_device_queue.h" | |
| 14 | |
| 15 namespace { | |
| 16 | |
| 17 class ShaderCCompiler { | |
| 18 public: | |
| 19 class CompilationResult { | |
| 20 public: | |
| 21 explicit CompilationResult(shaderc_compilation_result_t compilation_result) | |
| 22 : compilation_result_(compilation_result) {} | |
| 23 | |
| 24 ~CompilationResult() { shaderc_result_release(compilation_result_); } | |
| 25 | |
| 26 bool IsValid() const { | |
| 27 return shaderc_compilation_status_success == | |
| 28 shaderc_result_get_compilation_status(compilation_result_); | |
| 29 } | |
| 30 | |
| 31 std::string GetErrors() const { | |
| 32 return shaderc_result_get_error_message(compilation_result_); | |
| 33 } | |
| 34 | |
| 35 std::string GetResult() const { | |
| 36 return std::string(shaderc_result_get_bytes(compilation_result_), | |
| 37 shaderc_result_get_length(compilation_result_)); | |
| 38 } | |
| 39 | |
| 40 private: | |
| 41 shaderc_compilation_result_t compilation_result_; | |
| 42 }; | |
| 43 | |
| 44 ShaderCCompiler() | |
| 45 : compiler_(shaderc_compiler_initialize()), | |
| 46 compiler_options_(shaderc_compile_options_initialize()) {} | |
| 47 | |
| 48 ~ShaderCCompiler() { shaderc_compiler_release(compiler_); } | |
| 49 | |
| 50 void AddMacroDef(const std::string& name, const std::string& value) { | |
| 51 shaderc_compile_options_add_macro_definition(compiler_options_, | |
| 52 name.c_str(), name.length(), | |
| 53 value.c_str(), value.length()); | |
| 54 } | |
| 55 | |
| 56 std::unique_ptr<ShaderCCompiler::CompilationResult> CompileShaderModule( | |
| 57 gpu::VulkanShaderModule::ShaderType shader_type, | |
| 58 const std::string& name, | |
| 59 const std::string& entry_point, | |
| 60 const std::string& source) { | |
| 61 return base::MakeUnique<ShaderCCompiler::CompilationResult>( | |
| 62 shaderc_compile_into_spv( | |
| 63 compiler_, source.c_str(), source.length(), | |
| 64 (shader_type == gpu::VulkanShaderModule::ShaderType::VERTEX | |
| 65 ? shaderc_glsl_vertex_shader | |
| 66 : shaderc_glsl_fragment_shader), | |
| 67 name.c_str(), entry_point.c_str(), compiler_options_)); | |
| 68 } | |
| 69 | |
| 70 private: | |
| 71 shaderc_compiler_t compiler_; | |
| 72 shaderc_compile_options_t compiler_options_; | |
| 73 }; | |
| 74 | |
| 75 } // namespace | |
| 76 | |
| 77 namespace gpu { | |
| 78 | |
| 79 VulkanShaderModule::VulkanShaderModule(VulkanDeviceQueue* device_queue) | |
| 80 : device_queue_(device_queue) { | |
| 81 DCHECK(device_queue_); | |
| 82 } | |
| 83 | |
| 84 VulkanShaderModule::~VulkanShaderModule() { | |
| 85 DCHECK_EQ(static_cast<VkShaderModule>(VK_NULL_HANDLE), handle_); | |
| 86 } | |
| 87 | |
| 88 bool VulkanShaderModule::InitializeGLSL(ShaderType type, | |
| 89 std::string name, | |
| 90 std::string entry_point, | |
| 91 std::string source) { | |
| 92 ShaderCCompiler shaderc_compiler; | |
| 93 std::unique_ptr<ShaderCCompiler::CompilationResult> compilation_result( | |
| 94 shaderc_compiler.CompileShaderModule(type, name, entry_point, source)); | |
| 95 | |
| 96 if (!compilation_result->IsValid()) { | |
| 97 error_messages_ = compilation_result->GetErrors(); | |
| 98 return false; | |
| 99 } | |
| 100 | |
| 101 return InitializeSPIRV(type, std::move(name), std::move(entry_point), | |
| 102 compilation_result->GetResult()); | |
| 103 } | |
| 104 | |
| 105 bool VulkanShaderModule::InitializeSPIRV(ShaderType type, | |
| 106 std::string name, | |
| 107 std::string entry_point, | |
| 108 std::string source) { | |
| 109 DCHECK_EQ(static_cast<VkShaderModule>(VK_NULL_HANDLE), handle_); | |
| 110 shader_type_ = type; | |
| 111 name_ = std::move(name); | |
| 112 entry_point_ = std::move(entry_point); | |
| 113 | |
| 114 std::string aligned_source; | |
| 115 | |
| 116 VkShaderModuleCreateInfo shader_module_create_info = {}; | |
| 117 shader_module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; | |
| 118 | |
| 119 // Make sure source is a multiple of 4. | |
| 120 const int source_mod = source.length() % 4; | |
| 121 for (int i = 0; i < (4 - source_mod); ++i) { | |
|
piman
2016/05/17 18:53:59
nit: actually if source.length() is already a mult
David Yen
2016/05/17 19:36:31
That wouldn't work for 0 length sources though, I'
David Yen
2016/05/17 20:05:04
Although... if we really wanted to be branchless I
| |
| 122 source += ' '; | |
| 123 } | |
| 124 | |
| 125 shader_module_create_info.pCode = | |
| 126 reinterpret_cast<const uint32_t*>(source.c_str()); | |
| 127 shader_module_create_info.codeSize = source.length() / 4; | |
| 128 | |
| 129 VkShaderModule shader_module = VK_NULL_HANDLE; | |
| 130 VkResult result = | |
| 131 vkCreateShaderModule(device_queue_->GetVulkanDevice(), | |
| 132 &shader_module_create_info, nullptr, &shader_module); | |
| 133 if (VK_SUCCESS != result) { | |
| 134 std::stringstream ss; | |
| 135 ss << "vkCreateShaderModule() failed: " << result; | |
| 136 error_messages_ = ss.str(); | |
| 137 DLOG(ERROR) << error_messages_; | |
| 138 return false; | |
| 139 } | |
| 140 | |
| 141 handle_ = shader_module; | |
| 142 return true; | |
| 143 } | |
| 144 | |
| 145 void VulkanShaderModule::Destroy() { | |
| 146 if (handle_ != VK_NULL_HANDLE) { | |
| 147 vkDestroyShaderModule(device_queue_->GetVulkanDevice(), handle_, nullptr); | |
| 148 handle_ = VK_NULL_HANDLE; | |
| 149 } | |
| 150 | |
| 151 entry_point_.clear(); | |
| 152 error_messages_.clear(); | |
| 153 } | |
| 154 | |
| 155 } // namespace gpu | |
| OLD | NEW |