VideoVulkan/ShaderCompiler: Use a std::optional instead of bool+out variable

Now that we utilize C++17, we can simply return an optional containing
the code instead of using an out variable and a boolean result,
essentially combining them into one.

This provides a much more straightforward interface.
This commit is contained in:
Lioncash 2019-05-30 03:52:05 -04:00
parent e60268bd42
commit d6a60050ff
3 changed files with 30 additions and 30 deletions

View File

@ -108,11 +108,11 @@ static const char SUBGROUP_HELPER_HEADER[] = R"(
#define SUBGROUP_MAX(value) value = subgroupMax(value) #define SUBGROUP_MAX(value) value = subgroupMax(value)
)"; )";
bool CompileShaderToSPV(SPIRVCodeVector* out_code, EShLanguage stage, const char* stage_filename, std::optional<SPIRVCodeVector> CompileShaderToSPV(EShLanguage stage, const char* stage_filename,
std::string_view source, std::string_view header) std::string_view source, std::string_view header)
{ {
if (!InitializeGlslang()) if (!InitializeGlslang())
return false; return std::nullopt;
std::unique_ptr<glslang::TShader> shader = std::make_unique<glslang::TShader>(stage); std::unique_ptr<glslang::TShader> shader = std::make_unique<glslang::TShader>(stage);
std::unique_ptr<glslang::TProgram> program; std::unique_ptr<glslang::TProgram> program;
@ -172,7 +172,7 @@ bool CompileShaderToSPV(SPIRVCodeVector* out_code, EShLanguage stage, const char
includer)) includer))
{ {
DumpBadShader("Failed to parse shader"); DumpBadShader("Failed to parse shader");
return false; return std::nullopt;
} }
// Even though there's only a single shader, we still need to link it to generate SPV // Even though there's only a single shader, we still need to link it to generate SPV
@ -181,18 +181,19 @@ bool CompileShaderToSPV(SPIRVCodeVector* out_code, EShLanguage stage, const char
if (!program->link(messages)) if (!program->link(messages))
{ {
DumpBadShader("Failed to link program"); DumpBadShader("Failed to link program");
return false; return std::nullopt;
} }
glslang::TIntermediate* intermediate = program->getIntermediate(stage); glslang::TIntermediate* intermediate = program->getIntermediate(stage);
if (!intermediate) if (!intermediate)
{ {
DumpBadShader("Failed to generate SPIR-V"); DumpBadShader("Failed to generate SPIR-V");
return false; return std::nullopt;
} }
SPIRVCodeVector out_code;
spv::SpvBuildLogger logger; spv::SpvBuildLogger logger;
glslang::GlslangToSpv(*intermediate, *out_code, &logger); glslang::GlslangToSpv(*intermediate, out_code, &logger);
// Write out messages // Write out messages
// Temporary: skip if it contains "Warning, version 450 is not yet complete; most version-specific // Temporary: skip if it contains "Warning, version 450 is not yet complete; most version-specific
@ -230,11 +231,11 @@ bool CompileShaderToSPV(SPIRVCodeVector* out_code, EShLanguage stage, const char
stream << "SPIR-V conversion messages: " << std::endl; stream << "SPIR-V conversion messages: " << std::endl;
stream << spv_messages; stream << spv_messages;
stream << "SPIR-V:" << std::endl; stream << "SPIR-V:" << std::endl;
spv::Disassemble(stream, *out_code); spv::Disassemble(stream, out_code);
} }
} }
return true; return out_code;
} }
bool InitializeGlslang() bool InitializeGlslang()
@ -356,24 +357,24 @@ const TBuiltInResource* GetCompilerResourceLimits()
return &limits; return &limits;
} }
bool CompileVertexShader(SPIRVCodeVector* out_code, std::string_view source_code) std::optional<SPIRVCodeVector> CompileVertexShader(std::string_view source_code)
{ {
return CompileShaderToSPV(out_code, EShLangVertex, "vs", source_code, SHADER_HEADER); return CompileShaderToSPV(EShLangVertex, "vs", source_code, SHADER_HEADER);
} }
bool CompileGeometryShader(SPIRVCodeVector* out_code, std::string_view source_code) std::optional<SPIRVCodeVector> CompileGeometryShader(std::string_view source_code)
{ {
return CompileShaderToSPV(out_code, EShLangGeometry, "gs", source_code, SHADER_HEADER); return CompileShaderToSPV(EShLangGeometry, "gs", source_code, SHADER_HEADER);
} }
bool CompileFragmentShader(SPIRVCodeVector* out_code, std::string_view source_code) std::optional<SPIRVCodeVector> CompileFragmentShader(std::string_view source_code)
{ {
return CompileShaderToSPV(out_code, EShLangFragment, "ps", source_code, SHADER_HEADER); return CompileShaderToSPV(EShLangFragment, "ps", source_code, SHADER_HEADER);
} }
bool CompileComputeShader(SPIRVCodeVector* out_code, std::string_view source_code) std::optional<SPIRVCodeVector> CompileComputeShader(std::string_view source_code)
{ {
return CompileShaderToSPV(out_code, EShLangCompute, "cs", source_code, COMPUTE_SHADER_HEADER); return CompileShaderToSPV(EShLangCompute, "cs", source_code, COMPUTE_SHADER_HEADER);
} }
} // namespace ShaderCompiler } // namespace ShaderCompiler

View File

@ -5,6 +5,7 @@
#pragma once #pragma once
#include <cstddef> #include <cstddef>
#include <optional>
#include <string_view> #include <string_view>
#include <vector> #include <vector>
@ -19,16 +20,16 @@ using SPIRVCodeType = u32;
using SPIRVCodeVector = std::vector<SPIRVCodeType>; using SPIRVCodeVector = std::vector<SPIRVCodeType>;
// Compile a vertex shader to SPIR-V. // Compile a vertex shader to SPIR-V.
bool CompileVertexShader(SPIRVCodeVector* out_code, std::string_view source_code); std::optional<SPIRVCodeVector> CompileVertexShader(std::string_view source_code);
// Compile a geometry shader to SPIR-V. // Compile a geometry shader to SPIR-V.
bool CompileGeometryShader(SPIRVCodeVector* out_code, std::string_view source_code); std::optional<SPIRVCodeVector> CompileGeometryShader(std::string_view source_code);
// Compile a fragment shader to SPIR-V. // Compile a fragment shader to SPIR-V.
bool CompileFragmentShader(SPIRVCodeVector* out_code, std::string_view source_code); std::optional<SPIRVCodeVector> CompileFragmentShader(std::string_view source_code);
// Compile a compute shader to SPIR-V. // Compile a compute shader to SPIR-V.
bool CompileComputeShader(SPIRVCodeVector* out_code, std::string_view source_code); std::optional<SPIRVCodeVector> CompileComputeShader(std::string_view source_code);
} // namespace ShaderCompiler } // namespace ShaderCompiler
} // namespace Vulkan } // namespace Vulkan

View File

@ -88,31 +88,29 @@ static std::unique_ptr<VKShader> CreateShaderObject(ShaderStage stage,
std::unique_ptr<VKShader> VKShader::CreateFromSource(ShaderStage stage, std::string_view source) std::unique_ptr<VKShader> VKShader::CreateFromSource(ShaderStage stage, std::string_view source)
{ {
ShaderCompiler::SPIRVCodeVector spv; std::optional<ShaderCompiler::SPIRVCodeVector> spv;
bool result;
switch (stage) switch (stage)
{ {
case ShaderStage::Vertex: case ShaderStage::Vertex:
result = ShaderCompiler::CompileVertexShader(&spv, source); spv = ShaderCompiler::CompileVertexShader(source);
break; break;
case ShaderStage::Geometry: case ShaderStage::Geometry:
result = ShaderCompiler::CompileGeometryShader(&spv, source); spv = ShaderCompiler::CompileGeometryShader(source);
break; break;
case ShaderStage::Pixel: case ShaderStage::Pixel:
result = ShaderCompiler::CompileFragmentShader(&spv, source); spv = ShaderCompiler::CompileFragmentShader(source);
break; break;
case ShaderStage::Compute: case ShaderStage::Compute:
result = ShaderCompiler::CompileComputeShader(&spv, source); spv = ShaderCompiler::CompileComputeShader(source);
break; break;
default: default:
result = false;
break; break;
} }
if (!result) if (!spv)
return nullptr; return nullptr;
return CreateShaderObject(stage, std::move(spv)); return CreateShaderObject(stage, std::move(*spv));
} }
std::unique_ptr<VKShader> VKShader::CreateFromBinary(ShaderStage stage, const void* data, std::unique_ptr<VKShader> VKShader::CreateFromBinary(ShaderStage stage, const void* data,