Vulkan: Generate Correct GLSL After Changing Workarounds

During normal execution it isn't possible to switch workarounds.
However when running test cases we want to check if shaders and
other tests work when work arounds are enabled. Currently shader
patches are cached globally.

This PR moves the cached shader patch to the device level which
is rebuild every time a device needs to be reinitialized.

For OpenGL this is also an issue, but harder to solve as the concept
device doesn't exist there.

Pull Request: https://projects.blender.org/blender/blender/pulls/116042
This commit is contained in:
Jeroen Bakker
2023-12-11 16:25:41 +01:00
parent bac94fe307
commit fa2f9ef33b
3 changed files with 55 additions and 47 deletions

View File

@@ -6,19 +6,25 @@
* \ingroup gpu
*/
#include "vk_device.hh"
#include <sstream>
#include "vk_backend.hh"
#include "vk_context.hh"
#include "vk_device.hh"
#include "vk_memory.hh"
#include "vk_state_manager.hh"
#include "vk_storage_buffer.hh"
#include "vk_texture.hh"
#include "vk_vertex_buffer.hh"
#include "GPU_capabilities.h"
#include "BLI_math_matrix_types.hh"
#include "GHOST_C-api.h"
extern "C" char datatoc_glsl_shader_defines_glsl[];
namespace blender::gpu {
void VKDevice::deinit()
@@ -48,6 +54,7 @@ void VKDevice::deinit()
vk_queue_family_ = 0;
vk_queue_ = VK_NULL_HANDLE;
vk_physical_device_properties_ = {};
glsl_patch_.clear();
}
bool VKDevice::is_initialized() const
@@ -79,6 +86,7 @@ void VKDevice::init(void *ghost_context)
debug::object_label(device_get(), "LogicalDevice");
debug::object_label(queue_get(), "GenericQueue");
init_glsl_patch();
}
void VKDevice::init_debug_callbacks()
@@ -161,6 +169,45 @@ void VKDevice::init_dummy_color_attachment()
dummy_color_attachment_ = std::make_optional(std::reference_wrapper(vk_texture));
}
void VKDevice::init_glsl_patch()
{
std::stringstream ss;
ss << "#version 450\n";
if (GPU_shader_draw_parameters_support()) {
ss << "#extension GL_ARB_shader_draw_parameters : enable\n";
ss << "#define GPU_ARB_shader_draw_parameters\n";
ss << "#define gpu_BaseInstance (gl_BaseInstanceARB)\n";
}
ss << "#define gl_VertexID gl_VertexIndex\n";
ss << "#define gpu_InstanceIndex (gl_InstanceIndex)\n";
ss << "#define GPU_ARB_texture_cube_map_array\n";
ss << "#define gl_InstanceID (gpu_InstanceIndex - gpu_BaseInstance)\n";
/* TODO(fclem): This creates a validation error and should be already part of Vulkan 1.2. */
ss << "#extension GL_ARB_shader_viewport_layer_array: enable\n";
if (!workarounds_.shader_output_layer) {
ss << "#define gpu_Layer gl_Layer\n";
}
if (!workarounds_.shader_output_viewport_index) {
ss << "#define gpu_ViewportIndex gl_ViewportIndex\n";
}
ss << "#define DFDX_SIGN 1.0\n";
ss << "#define DFDY_SIGN 1.0\n";
/* GLSL Backend Lib. */
ss << datatoc_glsl_shader_defines_glsl;
glsl_patch_ = ss.str();
}
const char *VKDevice::glsl_patch_get() const
{
BLI_assert(!glsl_patch_.empty());
return glsl_patch_.c_str();
}
/* -------------------------------------------------------------------- */
/** \name Platform/driver/device information
* \{ */

View File

@@ -104,6 +104,8 @@ class VKDevice : public NonCopyable {
Vector<VkFramebuffer> discarded_frame_buffers_;
Vector<VkImageView> discarded_image_views_;
std::string glsl_patch_;
public:
VkPhysicalDevice physical_device_get() const
{
@@ -196,6 +198,9 @@ class VKDevice : public NonCopyable {
return workarounds_;
}
const char *glsl_patch_get() const;
void init_glsl_patch();
/* -------------------------------------------------------------------- */
/** \name Resource management
* \{ */

View File

@@ -24,8 +24,6 @@
using namespace blender::gpu::shader;
extern "C" char datatoc_glsl_shader_defines_glsl[];
namespace blender::gpu {
/* -------------------------------------------------------------------- */
@@ -487,49 +485,6 @@ static const std::string to_stage_name(shaderc_shader_kind stage)
return std::string("unknown stage");
}
static char *glsl_patch_get()
{
static char patch[2048] = "\0";
if (patch[0] != '\0') {
return patch;
}
const VKWorkarounds &workarounds = VKBackend::get().device_get().workarounds_get();
size_t slen = 0;
/* Version need to go first. */
STR_CONCAT(patch, slen, "#version 450\n");
if (GPU_shader_draw_parameters_support()) {
STR_CONCAT(patch, slen, "#extension GL_ARB_shader_draw_parameters : enable\n");
STR_CONCAT(patch, slen, "#define GPU_ARB_shader_draw_parameters\n");
STR_CONCAT(patch, slen, "#define gpu_BaseInstance (gl_BaseInstanceARB)\n");
}
STR_CONCAT(patch, slen, "#define gl_VertexID gl_VertexIndex\n");
STR_CONCAT(patch, slen, "#define gpu_InstanceIndex (gl_InstanceIndex)\n");
STR_CONCAT(patch, slen, "#define GPU_ARB_texture_cube_map_array\n");
STR_CONCAT(patch, slen, "#define gl_InstanceID (gpu_InstanceIndex - gpu_BaseInstance)\n");
/* TODO(fclem): This creates a validation error and should be already part of Vulkan 1.2. */
STR_CONCAT(patch, slen, "#extension GL_ARB_shader_viewport_layer_array: enable\n");
if (!workarounds.shader_output_layer) {
STR_CONCAT(patch, slen, "#define gpu_Layer gl_Layer\n");
}
if (!workarounds.shader_output_viewport_index) {
STR_CONCAT(patch, slen, "#define gpu_ViewportIndex gl_ViewportIndex\n");
}
STR_CONCAT(patch, slen, "#define DFDX_SIGN 1.0\n");
STR_CONCAT(patch, slen, "#define DFDY_SIGN 1.0\n");
/* GLSL Backend Lib. */
STR_CONCAT(patch, slen, datatoc_glsl_shader_defines_glsl);
BLI_assert(slen < sizeof(patch));
return patch;
}
static std::string combine_sources(Span<const char *> sources)
{
char *sources_combined = BLI_string_join_arrayN((const char **)sources.data(), sources.size());
@@ -641,7 +596,8 @@ void VKShader::build_shader_module(MutableSpan<const char *> sources,
shaderc_fragment_shader,
shaderc_compute_shader),
"Only forced ShaderC shader kinds are supported.");
sources[0] = glsl_patch_get();
const VKDevice &device = VKBackend::get().device_get();
sources[0] = device.glsl_patch_get();
Vector<uint32_t> spirv_module = compile_glsl_to_spirv(sources, stage);
build_shader_module(spirv_module, r_shader_module);
}