VideoCommon: Allow BitfieldExtract in specialized shaders

This commit is contained in:
Pokechu22 2021-07-26 11:20:04 -07:00
parent 735fd60e52
commit 555a93057c
7 changed files with 33 additions and 39 deletions

View File

@ -565,6 +565,7 @@ ShaderCode GeneratePixelShaderCode(APIType api_type, const ShaderHostConfig& hos
uid_data->genMode_numtexgens, uid_data->genMode_numindstages);
// Stuff that is shared between ubershaders and pixelgen.
WriteBitfieldExtractHeader(out, api_type, host_config);
WritePixelShaderCommonHeader(out, api_type, host_config, uid_data->bounding_box);
if (uid_data->forced_early_z && g_ActiveConfig.backend_info.bSupportsEarlyZ)

View File

@ -105,6 +105,24 @@ void WriteIsNanHeader(ShaderCode& out, APIType api_type)
}
}
void WriteBitfieldExtractHeader(ShaderCode& out, APIType api_type,
const ShaderHostConfig& host_config)
{
// ==============================================
// BitfieldExtract for APIs which don't have it
// ==============================================
if (!host_config.backend_bitfield)
{
out.Write("uint bitfieldExtract(uint val, int off, int size) {{\n"
" // This built-in function is only supported in OpenGL 4.0+ and ES 3.1+\n"
" // Microsoft's HLSL compiler automatically optimises this to a bitfield extract "
"instruction.\n"
" uint mask = uint((1 << size) - 1);\n"
" return uint(val >> off) & mask;\n"
"}}\n\n");
}
}
static void DefineOutputMember(ShaderCode& object, APIType api_type, std::string_view qualifier,
std::string_view type, std::string_view name, int var_index,
std::string_view semantic = {}, int semantic_index = -1)

View File

@ -14,6 +14,7 @@
#include "Common/BitField.h"
#include "Common/CommonTypes.h"
#include "Common/StringUtil.h"
#include "Common/TypeUtils.h"
enum class APIType;
@ -177,6 +178,8 @@ std::string GetDiskShaderCacheFileName(APIType api_type, const char* type, bool
bool include_host_config, bool include_api = true);
void WriteIsNanHeader(ShaderCode& out, APIType api_type);
void WriteBitfieldExtractHeader(ShaderCode& out, APIType api_type,
const ShaderHostConfig& host_config);
void GenerateVSOutputMembers(ShaderCode& object, APIType api_type, u32 texgens,
const ShaderHostConfig& host_config, std::string_view qualifier);
@ -195,6 +198,15 @@ void AssignVSOutputMembers(ShaderCode& object, std::string_view a, std::string_v
const char* GetInterpolationQualifier(bool msaa, bool ssaa, bool in_glsl_interface_block = false,
bool in = false);
// bitfieldExtract generator for BitField types
template <auto ptr_to_bitfield_member>
std::string BitfieldExtract(std::string_view source)
{
using BitFieldT = Common::MemberType<ptr_to_bitfield_member>;
return fmt::format("bitfieldExtract({}, {}, {})", source, static_cast<u32>(BitFieldT::StartBit()),
static_cast<u32>(BitFieldT::NumBits()));
}
// Constant variable names
#define I_COLORS "color"
#define I_KCOLORS "k"

View File

@ -9,24 +9,6 @@
namespace UberShader
{
void WriteUberShaderCommonHeader(ShaderCode& out, APIType api_type,
const ShaderHostConfig& host_config)
{
// ==============================================
// BitfieldExtract for APIs which don't have it
// ==============================================
if (!host_config.backend_bitfield)
{
out.Write("uint bitfieldExtract(uint val, int off, int size) {{\n"
" // This built-in function is only support in OpenGL 4.0+ and ES 3.1+\n"
" // Microsoft's HLSL compiler automatically optimises this to a bitfield extract "
"instruction.\n"
" uint mask = uint((1 << size) - 1);\n"
" return uint(val >> off) & mask;\n"
"}}\n\n");
}
}
void WriteLightingFunction(ShaderCode& out)
{
// ==============================================

View File

@ -3,37 +3,18 @@
#pragma once
#include <string>
#include <string_view>
#include <fmt/format.h>
#include "Common/CommonTypes.h"
#include "Common/TypeUtils.h"
class ShaderCode;
enum class APIType;
union ShaderHostConfig;
namespace UberShader
{
// Common functions across all ubershaders
void WriteUberShaderCommonHeader(ShaderCode& out, APIType api_type,
const ShaderHostConfig& host_config);
// Vertex lighting
void WriteLightingFunction(ShaderCode& out);
void WriteVertexLighting(ShaderCode& out, APIType api_type, std::string_view world_pos_var,
std::string_view normal_var, std::string_view in_color_0_var,
std::string_view in_color_1_var, std::string_view out_color_0_var,
std::string_view out_color_1_var);
// bitfieldExtract generator for BitField types
template <auto ptr_to_bitfield_member>
std::string BitfieldExtract(std::string_view source)
{
using BitFieldT = Common::MemberType<ptr_to_bitfield_member>;
return fmt::format("bitfieldExtract({}, {}, {})", source, static_cast<u32>(BitFieldT::StartBit()),
static_cast<u32>(BitFieldT::NumBits()));
}
} // namespace UberShader

View File

@ -63,8 +63,8 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
out.Write("// Pixel UberShader for {} texgens{}{}\n", numTexgen,
early_depth ? ", early-depth" : "", per_pixel_depth ? ", per-pixel depth" : "");
WriteBitfieldExtractHeader(out, api_type, host_config);
WritePixelShaderCommonHeader(out, api_type, host_config, bounding_box);
WriteUberShaderCommonHeader(out, api_type, host_config);
if (per_pixel_lighting)
WriteLightingFunction(out);

View File

@ -49,8 +49,8 @@ ShaderCode GenVertexShader(APIType api_type, const ShaderHostConfig& host_config
GenerateVSOutputMembers(out, api_type, num_texgen, host_config, "");
out.Write("}};\n\n");
WriteUberShaderCommonHeader(out, api_type, host_config);
WriteIsNanHeader(out, api_type);
WriteBitfieldExtractHeader(out, api_type, host_config);
WriteLightingFunction(out);
if (api_type == APIType::OpenGL || api_type == APIType::Vulkan)