summaryrefslogtreecommitdiff
path: root/Source/Core/VideoBackends/Vulkan/ShaderCompiler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Core/VideoBackends/Vulkan/ShaderCompiler.cpp')
-rw-r--r--Source/Core/VideoBackends/Vulkan/ShaderCompiler.cpp78
1 files changed, 74 insertions, 4 deletions
diff --git a/Source/Core/VideoBackends/Vulkan/ShaderCompiler.cpp b/Source/Core/VideoBackends/Vulkan/ShaderCompiler.cpp
index 75bf99a3ba..1846ebbbcd 100644
--- a/Source/Core/VideoBackends/Vulkan/ShaderCompiler.cpp
+++ b/Source/Core/VideoBackends/Vulkan/ShaderCompiler.cpp
@@ -3,6 +3,7 @@
// Refer to the license.txt file included.
#include "VideoBackends/Vulkan/ShaderCompiler.h"
+#include "VideoBackends/Vulkan/VulkanContext.h"
#include <cstddef>
#include <cstdlib>
@@ -37,6 +38,11 @@ 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);
+// Copy GLSL source code to a SPIRVCodeVector, for use with VK_NV_glsl_shader.
+static void CopyGLSLToSPVVector(SPIRVCodeVector* out_code, 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
@@ -219,6 +225,42 @@ bool CompileShaderToSPV(SPIRVCodeVector* out_code, EShLanguage stage, const char
return true;
}
+void CopyGLSLToSPVVector(SPIRVCodeVector* out_code, const char* stage_filename,
+ const char* source_code, size_t source_code_length, const char* header,
+ size_t header_length)
+{
+ std::string full_source_code;
+ if (header_length > 0)
+ {
+ full_source_code.reserve(header_length + source_code_length);
+ full_source_code.append(header, header_length);
+ full_source_code.append(source_code, source_code_length);
+ }
+ else
+ {
+ full_source_code.append(source_code, source_code_length);
+ }
+
+ if (g_ActiveConfig.iLog & CONF_SAVESHADERS)
+ {
+ static int counter = 0;
+ std::string filename = StringFromFormat("%s%s_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(),
+ stage_filename, counter++);
+
+ std::ofstream stream;
+ File::OpenFStream(stream, filename, std::ios_base::out);
+ if (stream.good())
+ stream << full_source_code << std::endl;
+ }
+
+ size_t padding = full_source_code.size() % 4;
+ if (padding != 0)
+ full_source_code.append(4 - padding, '\n');
+
+ out_code->resize(full_source_code.size() / 4);
+ std::memcpy(out_code->data(), full_source_code.c_str(), full_source_code.size());
+}
+
bool InitializeGlslang()
{
static bool glslang_initialized = false;
@@ -338,29 +380,57 @@ const TBuiltInResource* GetCompilerResourceLimits()
}
bool CompileVertexShader(SPIRVCodeVector* out_code, const char* source_code,
- size_t source_code_length, bool prepend_header)
+ size_t source_code_length)
{
+ if (g_vulkan_context->SupportsNVGLSLExtension())
+ {
+ CopyGLSLToSPVVector(out_code, "vs", source_code, source_code_length, SHADER_HEADER,
+ sizeof(SHADER_HEADER) - 1);
+ return true;
+ }
+
return CompileShaderToSPV(out_code, EShLangVertex, "vs", source_code, source_code_length,
SHADER_HEADER, sizeof(SHADER_HEADER) - 1);
}
bool CompileGeometryShader(SPIRVCodeVector* out_code, const char* source_code,
- size_t source_code_length, bool prepend_header)
+ size_t source_code_length)
{
+ if (g_vulkan_context->SupportsNVGLSLExtension())
+ {
+ CopyGLSLToSPVVector(out_code, "gs", source_code, source_code_length, SHADER_HEADER,
+ sizeof(SHADER_HEADER) - 1);
+ return true;
+ }
+
return CompileShaderToSPV(out_code, EShLangGeometry, "gs", source_code, source_code_length,
SHADER_HEADER, sizeof(SHADER_HEADER) - 1);
}
bool CompileFragmentShader(SPIRVCodeVector* out_code, const char* source_code,
- size_t source_code_length, bool prepend_header)
+ size_t source_code_length)
{
+ if (g_vulkan_context->SupportsNVGLSLExtension())
+ {
+ CopyGLSLToSPVVector(out_code, "ps", source_code, source_code_length, SHADER_HEADER,
+ sizeof(SHADER_HEADER) - 1);
+ return true;
+ }
+
return CompileShaderToSPV(out_code, EShLangFragment, "ps", source_code, source_code_length,
SHADER_HEADER, sizeof(SHADER_HEADER) - 1);
}
bool CompileComputeShader(SPIRVCodeVector* out_code, const char* source_code,
- size_t source_code_length, bool prepend_header)
+ size_t source_code_length)
{
+ if (g_vulkan_context->SupportsNVGLSLExtension())
+ {
+ CopyGLSLToSPVVector(out_code, "cs", source_code, source_code_length, COMPUTE_SHADER_HEADER,
+ sizeof(COMPUTE_SHADER_HEADER) - 1);
+ return true;
+ }
+
return CompileShaderToSPV(out_code, EShLangCompute, "cs", source_code, source_code_length,
COMPUTE_SHADER_HEADER, sizeof(COMPUTE_SHADER_HEADER) - 1);
}