Skip to content
Permalink
Browse files

VideoCommon/RenderBase: Use a std::string_view with CreateShaderFromS…

…ource()

Greatly simplifies the overall interface when it comes to compiling
shaders. Also allows getting rid of a std::string overload of the same
name. Now std::string and const char* both go through the same function.
  • Loading branch information...
lioncash committed May 30, 2019
1 parent 80d8173 commit e60268bd4274de510f5214d6eedafba30a253984
@@ -113,10 +113,10 @@ std::unique_ptr<AbstractFramebuffer> Renderer::CreateFramebuffer(AbstractTexture
}

std::unique_ptr<AbstractShader> Renderer::CreateShaderFromSource(ShaderStage stage,
const char* source, size_t length)
std::string_view source)
{
DXShader::BinaryData bytecode;
if (!DXShader::CompileShader(D3D::feature_level, &bytecode, stage, source, length))
if (!DXShader::CompileShader(D3D::feature_level, &bytecode, stage, source))
return nullptr;

return DXShader::CreateFromBytecode(stage, std::move(bytecode));
@@ -5,7 +5,7 @@
#pragma once

#include <d3d11.h>
#include <string>
#include <string_view>
#include "VideoBackends/D3D/D3DState.h"
#include "VideoCommon/RenderBase.h"

@@ -28,8 +28,8 @@ class Renderer : public ::Renderer
std::unique_ptr<AbstractTexture> CreateTexture(const TextureConfig& config) override;
std::unique_ptr<AbstractStagingTexture>
CreateStagingTexture(StagingTextureType type, const TextureConfig& config) override;
std::unique_ptr<AbstractShader> CreateShaderFromSource(ShaderStage stage, const char* source,
size_t length) override;
std::unique_ptr<AbstractShader> CreateShaderFromSource(ShaderStage stage,
std::string_view source) override;
std::unique_ptr<AbstractShader> CreateShaderFromBinary(ShaderStage stage, const void* data,
size_t length) override;
std::unique_ptr<NativeVertexFormat>
@@ -24,11 +24,10 @@ std::unique_ptr<DXShader> DXShader::CreateFromBytecode(ShaderStage stage, Binary
return shader;
}

std::unique_ptr<DXShader> DXShader::CreateFromSource(ShaderStage stage, const char* source,
size_t length)
std::unique_ptr<DXShader> DXShader::CreateFromSource(ShaderStage stage, std::string_view source)
{
BinaryData bytecode;
if (!CompileShader(g_dx_context->GetFeatureLevel(), &bytecode, stage, source, length))
if (!CompileShader(g_dx_context->GetFeatureLevel(), &bytecode, stage, source))
return nullptr;

return CreateFromBytecode(stage, std::move(bytecode));
@@ -3,7 +3,9 @@
// Refer to the license.txt file included.

#pragma once

#include <memory>
#include <string_view>
#include "VideoBackends/D3D12/Common.h"
#include "VideoBackends/D3DCommon/Shader.h"

@@ -18,8 +20,7 @@ class DXShader final : public D3DCommon::Shader
D3D12_SHADER_BYTECODE GetD3DByteCode() const;

static std::unique_ptr<DXShader> CreateFromBytecode(ShaderStage stage, BinaryData bytecode);
static std::unique_ptr<DXShader> CreateFromSource(ShaderStage stage, const char* source,
size_t length);
static std::unique_ptr<DXShader> CreateFromSource(ShaderStage stage, std::string_view source);

private:
DXShader(ShaderStage stage, BinaryData bytecode);
@@ -82,9 +82,9 @@ std::unique_ptr<AbstractFramebuffer> Renderer::CreateFramebuffer(AbstractTexture
}

std::unique_ptr<AbstractShader> Renderer::CreateShaderFromSource(ShaderStage stage,
const char* source, size_t length)
std::string_view source)
{
return DXShader::CreateFromSource(stage, source, length);
return DXShader::CreateFromSource(stage, source);
}

std::unique_ptr<AbstractShader> Renderer::CreateShaderFromBinary(ShaderStage stage,
@@ -3,6 +3,7 @@
// Refer to the license.txt file included.

#pragma once

#include <d3d12.h>
#include "VideoBackends/D3D12/DescriptorHeapManager.h"
#include "VideoCommon/RenderBase.h"
@@ -35,8 +36,8 @@ class Renderer final : public ::Renderer
std::unique_ptr<AbstractFramebuffer>
CreateFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment) override;

std::unique_ptr<AbstractShader> CreateShaderFromSource(ShaderStage stage, const char* source,
size_t length) override;
std::unique_ptr<AbstractShader> CreateShaderFromSource(ShaderStage stage,
std::string_view source) override;
std::unique_ptr<AbstractShader> CreateShaderFromBinary(ShaderStage stage, const void* data,
size_t length) override;
std::unique_ptr<NativeVertexFormat>
@@ -90,7 +90,7 @@ static const char* GetCompileTarget(D3D_FEATURE_LEVEL feature_level, ShaderStage
}

bool Shader::CompileShader(D3D_FEATURE_LEVEL feature_level, BinaryData* out_bytecode,
ShaderStage stage, const char* source, size_t length)
ShaderStage stage, std::string_view source)
{
static constexpr D3D_SHADER_MACRO macros[] = {{"API_D3D", "1"}, {nullptr, nullptr}};
const UINT flags = g_ActiveConfig.bEnableValidationLayer ?
@@ -100,16 +100,16 @@ bool Shader::CompileShader(D3D_FEATURE_LEVEL feature_level, BinaryData* out_byte

Microsoft::WRL::ComPtr<ID3DBlob> code;
Microsoft::WRL::ComPtr<ID3DBlob> errors;
HRESULT hr = d3d_compile(source, length, nullptr, macros, nullptr, "main", target, flags, 0,
&code, &errors);
HRESULT hr = d3d_compile(source.data(), source.size(), nullptr, macros, nullptr, "main", target,
flags, 0, &code, &errors);
if (FAILED(hr))
{
static int num_failures = 0;
std::string filename = StringFromFormat(
"%sbad_%s_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), target, num_failures++);
std::ofstream file;
File::OpenFStream(file, filename, std::ios_base::out);
file.write(source, length);
file.write(source.data(), source.size());
file << "\n";
file.write(static_cast<const char*>(errors->GetBufferPointer()), errors->GetBufferSize());
file.close();
@@ -3,7 +3,8 @@
// Refer to the license.txt file included.

#pragma once
#include <memory>

#include <string_view>
#include "VideoBackends/D3DCommon/Common.h"
#include "VideoCommon/AbstractShader.h"

@@ -19,7 +20,7 @@ class Shader : public AbstractShader
BinaryData GetBinary() const override;

static bool CompileShader(D3D_FEATURE_LEVEL feature_level, BinaryData* out_bytecode,
ShaderStage stage, const char* source, size_t length);
ShaderStage stage, std::string_view source);

static BinaryData CreateByteCode(const void* data, size_t length);

@@ -48,8 +48,8 @@ class NullShader final : public AbstractShader
~NullShader() = default;
};

std::unique_ptr<AbstractShader> Renderer::CreateShaderFromSource(ShaderStage stage,
const char* source, size_t length)
std::unique_ptr<AbstractShader>
Renderer::CreateShaderFromSource(ShaderStage stage, [[maybe_unused]] std::string_view source)
{
return std::make_unique<NullShader>(stage);
}
@@ -22,8 +22,8 @@ class Renderer : public ::Renderer
std::unique_ptr<AbstractFramebuffer>
CreateFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment) override;

std::unique_ptr<AbstractShader> CreateShaderFromSource(ShaderStage stage, const char* source,
size_t length) override;
std::unique_ptr<AbstractShader> CreateShaderFromSource(ShaderStage stage,
std::string_view source) override;
std::unique_ptr<AbstractShader> CreateShaderFromBinary(ShaderStage stage, const void* data,
size_t length) override;
std::unique_ptr<NativeVertexFormat>
@@ -45,10 +45,9 @@ OGLShader::~OGLShader()
glDeleteProgram(m_gl_compute_program_id);
}

std::unique_ptr<OGLShader> OGLShader::CreateFromSource(ShaderStage stage, const char* source,
size_t length)
std::unique_ptr<OGLShader> OGLShader::CreateFromSource(ShaderStage stage, std::string_view source)
{
std::string source_str(source, length);
std::string source_str(source);
if (stage != ShaderStage::Compute)
{
GLenum shader_type = GetGLShaderTypeForStage(stage);
@@ -6,6 +6,7 @@

#include <cstddef>
#include <memory>
#include <string_view>

#include "Common/CommonTypes.h"
#include "Common/GL/GLUtil.h"
@@ -26,8 +27,7 @@ class OGLShader final : public AbstractShader
GLuint GetGLComputeProgramID() const { return m_gl_compute_program_id; }
const std::string& GetSource() const { return m_source; }

static std::unique_ptr<OGLShader> CreateFromSource(ShaderStage stage, const char* source,
size_t length);
static std::unique_ptr<OGLShader> CreateFromSource(ShaderStage stage, std::string_view source);

private:
u64 m_id;
@@ -832,9 +832,9 @@ std::unique_ptr<AbstractFramebuffer> Renderer::CreateFramebuffer(AbstractTexture
}

std::unique_ptr<AbstractShader> Renderer::CreateShaderFromSource(ShaderStage stage,
const char* source, size_t length)
std::string_view source)
{
return OGLShader::CreateFromSource(stage, source, length);
return OGLShader::CreateFromSource(stage, source);
}

std::unique_ptr<AbstractShader> Renderer::CreateShaderFromBinary(ShaderStage stage,
@@ -95,8 +95,8 @@ class Renderer : public ::Renderer
std::unique_ptr<AbstractTexture> CreateTexture(const TextureConfig& config) override;
std::unique_ptr<AbstractStagingTexture>
CreateStagingTexture(StagingTextureType type, const TextureConfig& config) override;
std::unique_ptr<AbstractShader> CreateShaderFromSource(ShaderStage stage, const char* source,
size_t length) override;
std::unique_ptr<AbstractShader> CreateShaderFromSource(ShaderStage stage,
std::string_view source) override;
std::unique_ptr<AbstractShader> CreateShaderFromBinary(ShaderStage stage, const void* data,
size_t length) override;
std::unique_ptr<NativeVertexFormat>
@@ -68,7 +68,7 @@ class SWShader final : public AbstractShader
};

std::unique_ptr<AbstractShader>
SWRenderer::CreateShaderFromSource(ShaderStage stage, const char* source, size_t length)
SWRenderer::CreateShaderFromSource(ShaderStage stage, [[maybe_unused]] std::string_view source)
{
return std::make_unique<SWShader>(stage);
}
@@ -27,8 +27,8 @@ class SWRenderer final : public Renderer
std::unique_ptr<AbstractFramebuffer>
CreateFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment) override;

std::unique_ptr<AbstractShader> CreateShaderFromSource(ShaderStage stage, const char* source,
size_t length) override;
std::unique_ptr<AbstractShader> CreateShaderFromSource(ShaderStage stage,
std::string_view source) override;
std::unique_ptr<AbstractShader> CreateShaderFromBinary(ShaderStage stage, const void* data,
size_t length) override;
std::unique_ptr<NativeVertexFormat>
@@ -95,9 +95,9 @@ std::unique_ptr<AbstractStagingTexture> Renderer::CreateStagingTexture(StagingTe
}

std::unique_ptr<AbstractShader> Renderer::CreateShaderFromSource(ShaderStage stage,
const char* source, size_t length)
std::string_view source)
{
return VKShader::CreateFromSource(stage, source, length);
return VKShader::CreateFromSource(stage, source);
}

std::unique_ptr<AbstractShader> Renderer::CreateShaderFromBinary(ShaderStage stage,
@@ -42,8 +42,8 @@ class Renderer : public ::Renderer
std::unique_ptr<AbstractFramebuffer>
CreateFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment) override;

std::unique_ptr<AbstractShader> CreateShaderFromSource(ShaderStage stage, const char* source,
size_t length) override;
std::unique_ptr<AbstractShader> CreateShaderFromSource(ShaderStage stage,
std::string_view source) override;
std::unique_ptr<AbstractShader> CreateShaderFromBinary(ShaderStage stage, const void* data,
size_t length) override;
std::unique_ptr<NativeVertexFormat>
@@ -35,11 +35,6 @@ bool InitializeGlslang();
// Resource limits used when compiling shaders
static const TBuiltInResource* GetCompilerResourceLimits();

// Compile a shader to SPIR-V via glslang
static bool CompileShaderToSPV(SPIRVCodeVector* out_code, EShLanguage stage,
const char* stage_filename, const char* source_code,
size_t source_code_length, const char* header, size_t header_length);

// Regarding the UBO bind points, we subtract one from the binding index because
// the OpenGL backend requires UBO #0 for non-block uniforms (at least on NV).
// This allows us to share the same shaders but use bind point #0 in the Vulkan
@@ -114,8 +109,7 @@ static const char SUBGROUP_HELPER_HEADER[] = R"(
)";

bool CompileShaderToSPV(SPIRVCodeVector* out_code, EShLanguage stage, const char* stage_filename,
const char* source_code, size_t source_code_length, const char* header,
size_t header_length)
std::string_view source, std::string_view header)
{
if (!InitializeGlslang())
return false;
@@ -129,16 +123,16 @@ bool CompileShaderToSPV(SPIRVCodeVector* out_code, EShLanguage stage, const char
int default_version = 450;

std::string full_source_code;
const char* pass_source_code = source_code;
int pass_source_code_length = static_cast<int>(source_code_length);
if (header_length > 0)
const char* pass_source_code = source.data();
int pass_source_code_length = static_cast<int>(source.size());
if (!header.empty())
{
constexpr size_t subgroup_helper_header_length = ArraySize(SUBGROUP_HELPER_HEADER) - 1;
full_source_code.reserve(header_length + subgroup_helper_header_length + source_code_length);
full_source_code.append(header, header_length);
full_source_code.reserve(header.size() + subgroup_helper_header_length + source.size());
full_source_code.append(header);
if (g_vulkan_context->SupportsShaderSubgroupOperations())
full_source_code.append(SUBGROUP_HELPER_HEADER, subgroup_helper_header_length);
full_source_code.append(source_code, source_code_length);
full_source_code.append(source);
pass_source_code = full_source_code.c_str();
pass_source_code_length = static_cast<int>(full_source_code.length());
}
@@ -362,32 +356,24 @@ const TBuiltInResource* GetCompilerResourceLimits()
return &limits;
}

bool CompileVertexShader(SPIRVCodeVector* out_code, const char* source_code,
size_t source_code_length)
bool CompileVertexShader(SPIRVCodeVector* out_code, std::string_view source_code)
{
return CompileShaderToSPV(out_code, EShLangVertex, "vs", source_code, source_code_length,
SHADER_HEADER, sizeof(SHADER_HEADER) - 1);
return CompileShaderToSPV(out_code, EShLangVertex, "vs", source_code, SHADER_HEADER);
}

bool CompileGeometryShader(SPIRVCodeVector* out_code, const char* source_code,
size_t source_code_length)
bool CompileGeometryShader(SPIRVCodeVector* out_code, std::string_view source_code)
{
return CompileShaderToSPV(out_code, EShLangGeometry, "gs", source_code, source_code_length,
SHADER_HEADER, sizeof(SHADER_HEADER) - 1);
return CompileShaderToSPV(out_code, EShLangGeometry, "gs", source_code, SHADER_HEADER);
}

bool CompileFragmentShader(SPIRVCodeVector* out_code, const char* source_code,
size_t source_code_length)
bool CompileFragmentShader(SPIRVCodeVector* out_code, std::string_view source_code)
{
return CompileShaderToSPV(out_code, EShLangFragment, "ps", source_code, source_code_length,
SHADER_HEADER, sizeof(SHADER_HEADER) - 1);
return CompileShaderToSPV(out_code, EShLangFragment, "ps", source_code, SHADER_HEADER);
}

bool CompileComputeShader(SPIRVCodeVector* out_code, const char* source_code,
size_t source_code_length)
bool CompileComputeShader(SPIRVCodeVector* out_code, std::string_view source_code)
{
return CompileShaderToSPV(out_code, EShLangCompute, "cs", source_code, source_code_length,
COMPUTE_SHADER_HEADER, sizeof(COMPUTE_SHADER_HEADER) - 1);
return CompileShaderToSPV(out_code, EShLangCompute, "cs", source_code, COMPUTE_SHADER_HEADER);
}

} // namespace ShaderCompiler
@@ -5,6 +5,7 @@
#pragma once

#include <cstddef>
#include <string_view>
#include <vector>

#include "Common/CommonTypes.h"
@@ -18,20 +19,16 @@ using SPIRVCodeType = u32;
using SPIRVCodeVector = std::vector<SPIRVCodeType>;

// Compile a vertex shader to SPIR-V.
bool CompileVertexShader(SPIRVCodeVector* out_code, const char* source_code,
size_t source_code_length);
bool CompileVertexShader(SPIRVCodeVector* out_code, std::string_view source_code);

// Compile a geometry shader to SPIR-V.
bool CompileGeometryShader(SPIRVCodeVector* out_code, const char* source_code,
size_t source_code_length);
bool CompileGeometryShader(SPIRVCodeVector* out_code, std::string_view source_code);

// Compile a fragment shader to SPIR-V.
bool CompileFragmentShader(SPIRVCodeVector* out_code, const char* source_code,
size_t source_code_length);
bool CompileFragmentShader(SPIRVCodeVector* out_code, std::string_view source_code);

// Compile a compute shader to SPIR-V.
bool CompileComputeShader(SPIRVCodeVector* out_code, const char* source_code,
size_t source_code_length);
bool CompileComputeShader(SPIRVCodeVector* out_code, std::string_view source_code);

} // namespace ShaderCompiler
} // namespace Vulkan

0 comments on commit e60268b

Please sign in to comment.
You can’t perform that action at this time.