ShaderGen: Implement pixel ubershaders
This commit is contained in:
parent
07591e7d5c
commit
7d78cf0f6f
|
@ -78,6 +78,8 @@ void VideoBackend::InitBackendInfo()
|
|||
g_Config.backend_info.bSupportsInternalResolutionFrameDumps = false;
|
||||
g_Config.backend_info.bSupportsGPUTextureDecoding = false;
|
||||
g_Config.backend_info.bSupportsST3CTextures = false;
|
||||
g_Config.backend_info.bSupportsBitfield = false;
|
||||
g_Config.backend_info.bSupportsDynamicSamplerIndexing = false;
|
||||
|
||||
IDXGIFactory* factory;
|
||||
IDXGIAdapter* ad;
|
||||
|
|
|
@ -447,6 +447,12 @@ Renderer::Renderer()
|
|||
// Clip distance support is useless without a method to clamp the depth range
|
||||
g_Config.backend_info.bSupportsDepthClamp = GLExtensions::Supports("GL_ARB_depth_clamp");
|
||||
|
||||
// Desktop OpenGL supports bitfield manulipation and dynamic sampler indexing if it supports
|
||||
// shader5. OpenGL ES 3.1 supports it implicitly without an extension
|
||||
g_Config.backend_info.bSupportsBitfield = GLExtensions::Supports("GL_ARB_gpu_shader5");
|
||||
g_Config.backend_info.bSupportsDynamicSamplerIndexing =
|
||||
GLExtensions::Supports("GL_ARB_gpu_shader5");
|
||||
|
||||
g_ogl_config.bSupportsGLSLCache = GLExtensions::Supports("GL_ARB_get_program_binary");
|
||||
g_ogl_config.bSupportsGLPinnedMemory = GLExtensions::Supports("GL_AMD_pinned_memory");
|
||||
g_ogl_config.bSupportsGLSync = GLExtensions::Supports("GL_ARB_sync");
|
||||
|
@ -515,6 +521,8 @@ Renderer::Renderer()
|
|||
g_ogl_config.bSupportsMSAA = true;
|
||||
g_ogl_config.bSupportsTextureStorage = true;
|
||||
g_ogl_config.bSupports2DTextureStorageMultisample = true;
|
||||
g_Config.backend_info.bSupportsBitfield = true;
|
||||
g_Config.backend_info.bSupportsDynamicSamplerIndexing = g_ogl_config.bSupportsAEP;
|
||||
if (g_ActiveConfig.iStereoMode > 0 && g_ActiveConfig.iMultisamples > 1 &&
|
||||
!g_ogl_config.bSupports3DTextureStorageMultisample)
|
||||
{
|
||||
|
@ -542,6 +550,8 @@ Renderer::Renderer()
|
|||
g_ogl_config.bSupportsTextureStorage = true;
|
||||
g_ogl_config.bSupports2DTextureStorageMultisample = true;
|
||||
g_ogl_config.bSupports3DTextureStorageMultisample = true;
|
||||
g_Config.backend_info.bSupportsBitfield = true;
|
||||
g_Config.backend_info.bSupportsDynamicSamplerIndexing = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -236,6 +236,8 @@ void VulkanContext::PopulateBackendInfo(VideoConfig* config)
|
|||
config->backend_info.bSupportsMultithreading = true; // Assumed support.
|
||||
config->backend_info.bSupportsComputeShaders = true; // Assumed support.
|
||||
config->backend_info.bSupportsGPUTextureDecoding = true; // Assumed support.
|
||||
config->backend_info.bSupportsBitfield = true; // Assumed support.
|
||||
config->backend_info.bSupportsDynamicSamplerIndexing = true; // Assumed support.
|
||||
config->backend_info.bSupportsInternalResolutionFrameDumps = true; // Assumed support.
|
||||
config->backend_info.bSupportsPostProcessing = true; // Assumed support.
|
||||
config->backend_info.bSupportsDualSourceBlend = false; // Dependent on features.
|
||||
|
|
|
@ -93,6 +93,9 @@ static void BPWritten(const BPCmd& bp)
|
|||
(u32)bpmem.genMode.cullmode, (u32)bpmem.genMode.numindstages,
|
||||
(u32)bpmem.genMode.zfreeze);
|
||||
|
||||
if (bp.changes)
|
||||
PixelShaderManager::SetGenModeChanged();
|
||||
|
||||
// Only call SetGenerationMode when cull mode changes.
|
||||
if (bp.changes & 0xC000)
|
||||
SetGenerationMode();
|
||||
|
@ -155,13 +158,20 @@ static void BPWritten(const BPCmd& bp)
|
|||
// Set Color Mask
|
||||
if (bp.changes & 0x18) // colorupdate | alphaupdate
|
||||
SetColorMask();
|
||||
|
||||
// Dither
|
||||
if (bp.changes & 0x04)
|
||||
PixelShaderManager::SetBlendModeChanged();
|
||||
}
|
||||
return;
|
||||
case BPMEM_CONSTANTALPHA: // Set Destination Alpha
|
||||
PRIM_LOG("constalpha: alp=%d, en=%d", bpmem.dstalpha.alpha.Value(),
|
||||
bpmem.dstalpha.enable.Value());
|
||||
if (bp.changes & 0xFF)
|
||||
PixelShaderManager::SetDestAlpha();
|
||||
if (bp.changes)
|
||||
{
|
||||
PixelShaderManager::SetAlpha();
|
||||
PixelShaderManager::SetDestAlphaChanged();
|
||||
}
|
||||
if (bp.changes & 0x100)
|
||||
SetBlendMode();
|
||||
return;
|
||||
|
@ -238,6 +248,7 @@ static void BPWritten(const BPCmd& bp)
|
|||
// the number of lines copied is determined by the y scale * source efb height
|
||||
|
||||
BoundingBox::active = false;
|
||||
PixelShaderManager::SetBoundingBoxActive(false);
|
||||
|
||||
float yScale;
|
||||
if (PE_copy.scale_invert)
|
||||
|
@ -318,6 +329,7 @@ static void BPWritten(const BPCmd& bp)
|
|||
PixelShaderManager::SetAlpha();
|
||||
if (bp.changes)
|
||||
{
|
||||
PixelShaderManager::SetAlphaTestChanged();
|
||||
g_renderer->SetColorMask();
|
||||
SetBlendMode();
|
||||
}
|
||||
|
@ -332,7 +344,7 @@ static void BPWritten(const BPCmd& bp)
|
|||
if (bp.changes & 3)
|
||||
PixelShaderManager::SetZTextureTypeChanged();
|
||||
if (bp.changes & 12)
|
||||
VertexShaderManager::SetViewportChanged();
|
||||
PixelShaderManager::SetZTextureOpChanged();
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
const char* pzop[] = {"DISABLE", "ADD", "REPLACE", "?"};
|
||||
const char* pztype[] = {"Z8", "Z16", "Z24", "?"};
|
||||
|
@ -390,6 +402,7 @@ static void BPWritten(const BPCmd& bp)
|
|||
{
|
||||
u8 offset = bp.address & 2;
|
||||
BoundingBox::active = true;
|
||||
PixelShaderManager::SetBoundingBoxActive(true);
|
||||
|
||||
if (g_ActiveConfig.backend_info.bSupportsBBox && g_ActiveConfig.bBBoxEnable)
|
||||
{
|
||||
|
@ -426,6 +439,11 @@ static void BPWritten(const BPCmd& bp)
|
|||
* 3 BC0 - Ind. Tex Stage 0 NTexCoord
|
||||
* 0 BI0 - Ind. Tex Stage 0 NTexMap */
|
||||
case BPMEM_IREF:
|
||||
{
|
||||
if (bp.changes)
|
||||
PixelShaderManager::SetTevIndirectChanged();
|
||||
return;
|
||||
}
|
||||
|
||||
case BPMEM_TEV_KSEL: // Texture Environment Swap Mode Table 0
|
||||
case BPMEM_TEV_KSEL + 1: // Texture Environment Swap Mode Table 1
|
||||
|
@ -435,6 +453,8 @@ static void BPWritten(const BPCmd& bp)
|
|||
case BPMEM_TEV_KSEL + 5: // Texture Environment Swap Mode Table 5
|
||||
case BPMEM_TEV_KSEL + 6: // Texture Environment Swap Mode Table 6
|
||||
case BPMEM_TEV_KSEL + 7: // Texture Environment Swap Mode Table 7
|
||||
PixelShaderManager::SetTevKSel(bp.address - BPMEM_TEV_KSEL, bp.newvalue);
|
||||
return;
|
||||
|
||||
/* This Register can be used to limit to which bits of BP registers is
|
||||
* actually written to. The mask is only valid for the next BP write,
|
||||
|
@ -567,6 +587,7 @@ static void BPWritten(const BPCmd& bp)
|
|||
// -------------------------
|
||||
case BPMEM_TREF:
|
||||
case BPMEM_TREF + 4:
|
||||
PixelShaderManager::SetTevOrder(bp.address - BPMEM_TREF, bp.newvalue);
|
||||
return;
|
||||
// ----------------------
|
||||
// Set wrap size
|
||||
|
@ -630,15 +651,18 @@ static void BPWritten(const BPCmd& bp)
|
|||
// --------------
|
||||
// Indirect Tev
|
||||
// --------------
|
||||
case BPMEM_IND_CMD: // Indirect 0-15
|
||||
case BPMEM_IND_CMD:
|
||||
PixelShaderManager::SetTevIndirectChanged();
|
||||
return;
|
||||
// --------------------------------------------------
|
||||
// Set Color/Alpha of a Tev
|
||||
// BPMEM_TEV_COLOR_ENV - Dest, Shift, Clamp, Sub, Bias, Sel A, Sel B, Sel C, Sel D
|
||||
// BPMEM_TEV_ALPHA_ENV - Dest, Shift, Clamp, Sub, Bias, Sel A, Sel B, Sel C, Sel D, T Swap, R Swap
|
||||
// --------------------------------------------------
|
||||
case BPMEM_TEV_COLOR_ENV: // Texture Environment Color/Alpha 0-7
|
||||
case BPMEM_TEV_COLOR_ENV + 16: // Texture Environment Color/Alpha 8-15
|
||||
case BPMEM_TEV_COLOR_ENV: // Texture Environment 1
|
||||
case BPMEM_TEV_COLOR_ENV + 16:
|
||||
PixelShaderManager::SetTevCombiner((bp.address - BPMEM_TEV_COLOR_ENV) >> 1,
|
||||
(bp.address - BPMEM_TEV_COLOR_ENV) & 1, bp.newvalue);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -32,6 +32,8 @@ set(SRCS
|
|||
RenderState.cpp
|
||||
ShaderGenCommon.cpp
|
||||
Statistics.cpp
|
||||
UberShaderCommon.cpp
|
||||
UberShaderPixel.cpp
|
||||
TextureCacheBase.cpp
|
||||
TextureConfig.cpp
|
||||
TextureConversionShader.cpp
|
||||
|
|
|
@ -24,7 +24,22 @@ struct PixelShaderConstants
|
|||
int4 fogi;
|
||||
float4 fogf[2];
|
||||
float4 zslope;
|
||||
float4 efbscale;
|
||||
float efbscale[2];
|
||||
|
||||
// Constants from here onwards are only used in ubershaders.
|
||||
u32 genmode; // .z
|
||||
u32 alphaTest; // .w
|
||||
u32 fogParam3; // .x
|
||||
u32 fogRangeBase; // .y
|
||||
u32 dstalpha; // .z
|
||||
u32 ztex_op; // .w
|
||||
u32 early_ztest; // .x (bool)
|
||||
u32 rgba6_format; // .y (bool)
|
||||
u32 dither; // .z (bool)
|
||||
u32 bounding_box; // .w (bool)
|
||||
uint4 pack1[16]; // .xy - combiners, .z - tevind, .w - iref
|
||||
uint4 pack2[8]; // .x - tevorder, .y - tevksel
|
||||
int4 konst[32]; // .rgba
|
||||
};
|
||||
|
||||
struct VertexShaderConstants
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "VideoCommon/CommandProcessor.h"
|
||||
#include "VideoCommon/Fifo.h"
|
||||
#include "VideoCommon/PixelEngine.h"
|
||||
#include "VideoCommon/PixelShaderManager.h"
|
||||
|
||||
namespace PixelEngine
|
||||
{
|
||||
|
@ -231,6 +232,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
|||
{
|
||||
mmio->Register(base | (PE_BBOX_LEFT + 2 * i), MMIO::ComplexRead<u16>([i](u32) {
|
||||
BoundingBox::active = false;
|
||||
PixelShaderManager::SetBoundingBoxActive(false);
|
||||
return g_video_backend->Video_GetBoundingBox(i);
|
||||
}),
|
||||
MMIO::InvalidWrite<u16>());
|
||||
|
|
|
@ -394,8 +394,26 @@ void WritePixelShaderCommonHeader(ShaderCode& out, APIType ApiType, bool boundin
|
|||
"\tint4 " I_FOGI ";\n"
|
||||
"\tfloat4 " I_FOGF "[2];\n"
|
||||
"\tfloat4 " I_ZSLOPE ";\n"
|
||||
"\tfloat4 " I_EFBSCALE ";\n"
|
||||
"};\n");
|
||||
"\tfloat2 " I_EFBSCALE ";\n"
|
||||
"\tuint bpmem_genmode;\n"
|
||||
"\tuint bpmem_alphaTest;\n"
|
||||
"\tuint bpmem_fogParam3;\n"
|
||||
"\tuint bpmem_fogRangeBase;\n"
|
||||
"\tuint bpmem_dstalpha;\n"
|
||||
"\tuint bpmem_ztex_op;\n"
|
||||
"\tbool bpmem_early_ztest;\n"
|
||||
"\tbool bpmem_rgba6_format;\n"
|
||||
"\tbool bpmem_dither;\n"
|
||||
"\tbool bpmem_bounding_box;\n"
|
||||
"\tuint4 bpmem_pack1[16];\n" // .xy - combiners, .z - tevind
|
||||
"\tuint4 bpmem_pack2[8];\n" // .x - tevorder, .y - tevksel
|
||||
"\tint4 konstLookup[32];\n"
|
||||
"};\n\n");
|
||||
out.Write("#define bpmem_combiners(i) (bpmem_pack1[(i)].xy)\n"
|
||||
"#define bpmem_tevind(i) (bpmem_pack1[(i)].z)\n"
|
||||
"#define bpmem_iref(i) (bpmem_pack1[(i)].w)\n"
|
||||
"#define bpmem_tevorder(i) (bpmem_pack2[(i)].x)\n"
|
||||
"#define bpmem_tevksel(i) (bpmem_pack2[(i)].y)\n\n");
|
||||
|
||||
if (bounding_box)
|
||||
{
|
||||
|
@ -449,7 +467,7 @@ ShaderCode GeneratePixelShaderCode(APIType ApiType, const ShaderHostConfig& host
|
|||
if (ApiType == APIType::OpenGL || ApiType == APIType::Vulkan)
|
||||
out.Write("UBO_BINDING(std140, 2) uniform VSBlock {\n");
|
||||
else
|
||||
out.Write("cbuffer VSBlock : register(b2) {\n");
|
||||
out.Write("cbuffer VSBlock : register(b1) {\n");
|
||||
|
||||
out.Write(s_shader_uniforms);
|
||||
out.Write("};\n");
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
|
||||
bool PixelShaderManager::s_bFogRangeAdjustChanged;
|
||||
bool PixelShaderManager::s_bViewPortChanged;
|
||||
bool PixelShaderManager::s_bIndirectDirty;
|
||||
bool PixelShaderManager::s_bDestAlphaDirty;
|
||||
|
||||
PixelShaderConstants PixelShaderManager::constants;
|
||||
bool PixelShaderManager::dirty;
|
||||
|
@ -40,6 +42,38 @@ void PixelShaderManager::Init()
|
|||
SetTexCoordChanged(6);
|
||||
SetTexCoordChanged(7);
|
||||
|
||||
// fixed Konstants
|
||||
for (int component = 0; component < 4; component++)
|
||||
{
|
||||
constants.konst[0][component] = 255; // 1
|
||||
constants.konst[1][component] = 223; // 7/8
|
||||
constants.konst[2][component] = 191; // 3/4
|
||||
constants.konst[3][component] = 159; // 5/8
|
||||
constants.konst[4][component] = 128; // 1/2
|
||||
constants.konst[5][component] = 96; // 3/8
|
||||
constants.konst[6][component] = 64; // 1/4
|
||||
constants.konst[7][component] = 32; // 1/8
|
||||
|
||||
// Invalid Konstants (reads as zero on hardware)
|
||||
constants.konst[8][component] = 0;
|
||||
constants.konst[9][component] = 0;
|
||||
constants.konst[10][component] = 0;
|
||||
constants.konst[11][component] = 0;
|
||||
|
||||
// Annoyingly, alpha reads zero values for the .rgb colors (offically
|
||||
// defined as invalid)
|
||||
// If it wasn't for this, we could just use one of the first 3 colunms
|
||||
// instead of
|
||||
// wasting an entire 4th column just for alpha.
|
||||
if (component == 3)
|
||||
{
|
||||
constants.konst[12][component] = 0;
|
||||
constants.konst[13][component] = 0;
|
||||
constants.konst[14][component] = 0;
|
||||
constants.konst[15][component] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
|
@ -99,6 +133,59 @@ void PixelShaderManager::SetConstants()
|
|||
dirty = true;
|
||||
s_bViewPortChanged = false;
|
||||
}
|
||||
|
||||
if (s_bIndirectDirty)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
constants.pack1[i][3] = 0;
|
||||
|
||||
for (u32 i = 0; i < (bpmem.genMode.numtevstages + 1); ++i)
|
||||
{
|
||||
u32 stage = bpmem.tevind[i].bt;
|
||||
if (stage < bpmem.genMode.numindstages)
|
||||
{
|
||||
// We set some extra bits so the ubershader can quickly check if these
|
||||
// features are in use.
|
||||
if (bpmem.tevind[i].IsActive())
|
||||
constants.pack1[stage][3] =
|
||||
bpmem.tevindref.getTexCoord(stage) | bpmem.tevindref.getTexMap(stage) << 8 | 1 << 16;
|
||||
// Note: a tevind of zero just happens to be a passthrough, so no need
|
||||
// to set an extra bit.
|
||||
constants.pack1[i][2] =
|
||||
bpmem.tevind[i].hex; // TODO: This match shadergen, but videosw will
|
||||
// always wrap.
|
||||
|
||||
// The ubershader uses tevind != 0 as a condition whether to calculate texcoords,
|
||||
// even when texture is disabled, instead of the stage < bpmem.genMode.numindstages.
|
||||
// We set an unused bit here to indicate that the stage is active, even if it
|
||||
// is just a pass-through.
|
||||
constants.pack1[i][2] |= 0x80000000;
|
||||
}
|
||||
else
|
||||
{
|
||||
constants.pack1[i][2] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
dirty = true;
|
||||
s_bIndirectDirty = false;
|
||||
}
|
||||
|
||||
if (s_bDestAlphaDirty)
|
||||
{
|
||||
// Destination alpha is only enabled if alpha writes are enabled. Force entire uniform to zero
|
||||
// when disabled.
|
||||
u32 dstalpha = bpmem.blendmode.alphaupdate && bpmem.dstalpha.enable &&
|
||||
bpmem.zcontrol.pixel_format == PEControl::RGBA6_Z24 ?
|
||||
bpmem.dstalpha.hex :
|
||||
0;
|
||||
|
||||
if (constants.dstalpha != dstalpha)
|
||||
{
|
||||
constants.dstalpha = dstalpha;
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PixelShaderManager::SetTevColor(int index, int component, s32 value)
|
||||
|
@ -116,20 +203,78 @@ void PixelShaderManager::SetTevKonstColor(int index, int component, s32 value)
|
|||
c[component] = value;
|
||||
dirty = true;
|
||||
|
||||
// Konst for ubershaders. We build the whole array on cpu so the gpu can do a single indirect
|
||||
// access.
|
||||
if (component != 3) // Alpha doesn't included in the .rgb konsts
|
||||
constants.konst[index + 12][component] = value;
|
||||
|
||||
// .rrrr .gggg .bbbb .aaaa konsts
|
||||
constants.konst[index + 16 + component * 4][0] = value;
|
||||
constants.konst[index + 16 + component * 4][1] = value;
|
||||
constants.konst[index + 16 + component * 4][2] = value;
|
||||
constants.konst[index + 16 + component * 4][3] = value;
|
||||
|
||||
PRIM_LOG("tev konst color%d: %d %d %d %d", index, c[0], c[1], c[2], c[3]);
|
||||
}
|
||||
|
||||
void PixelShaderManager::SetTevOrder(int index, u32 order)
|
||||
{
|
||||
if (constants.pack2[index][0] != order)
|
||||
{
|
||||
constants.pack2[index][0] = order;
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void PixelShaderManager::SetTevKSel(int index, u32 ksel)
|
||||
{
|
||||
if (constants.pack2[index][1] != ksel)
|
||||
{
|
||||
constants.pack2[index][1] = ksel;
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void PixelShaderManager::SetTevCombiner(int index, int alpha, u32 combiner)
|
||||
{
|
||||
if (constants.pack1[index][alpha] != combiner)
|
||||
{
|
||||
constants.pack1[index][alpha] = combiner;
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void PixelShaderManager::SetTevIndirectChanged()
|
||||
{
|
||||
s_bIndirectDirty = true;
|
||||
}
|
||||
|
||||
void PixelShaderManager::SetAlpha()
|
||||
{
|
||||
constants.alpha[0] = bpmem.alpha_test.ref0;
|
||||
constants.alpha[1] = bpmem.alpha_test.ref1;
|
||||
constants.alpha[3] = static_cast<s32>(bpmem.dstalpha.alpha);
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
void PixelShaderManager::SetDestAlpha()
|
||||
void PixelShaderManager::SetAlphaTestChanged()
|
||||
{
|
||||
constants.alpha[3] = bpmem.dstalpha.alpha;
|
||||
dirty = true;
|
||||
// Force alphaTest Uniform to zero if it will always pass.
|
||||
// (set an extra bit to distinguish from "never && never")
|
||||
// TODO: we could optimize this further and check the actual constants,
|
||||
// i.e. "a <= 0" and "a >= 255" will always pass.
|
||||
u32 alpha_test =
|
||||
bpmem.alpha_test.TestResult() != AlphaTest::PASS ? bpmem.alpha_test.hex | 1 << 31 : 0;
|
||||
if (constants.alphaTest != alpha_test)
|
||||
{
|
||||
constants.alphaTest = alpha_test;
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void PixelShaderManager::SetDestAlphaChanged()
|
||||
{
|
||||
s_bDestAlphaDirty = true;
|
||||
}
|
||||
|
||||
void PixelShaderManager::SetTexDims(int texmapid, u32 width, u32 height)
|
||||
|
@ -235,6 +380,12 @@ void PixelShaderManager::SetZTextureTypeChanged()
|
|||
dirty = true;
|
||||
}
|
||||
|
||||
void PixelShaderManager::SetZTextureOpChanged()
|
||||
{
|
||||
constants.ztex_op = bpmem.ztex2.op;
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
void PixelShaderManager::SetTexCoordChanged(u8 texmapid)
|
||||
{
|
||||
TCoordInfo& tc = bpmem.texcoords[texmapid];
|
||||
|
@ -262,6 +413,7 @@ void PixelShaderManager::SetFogParamChanged()
|
|||
constants.fogi[1] = bpmem.fog.b_magnitude;
|
||||
constants.fogf[1][2] = bpmem.fog.c_proj_fsel.GetC();
|
||||
constants.fogi[3] = bpmem.fog.b_shift;
|
||||
constants.fogParam3 = bpmem.fog.c_proj_fsel.hex;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -269,6 +421,7 @@ void PixelShaderManager::SetFogParamChanged()
|
|||
constants.fogi[1] = 1;
|
||||
constants.fogf[1][2] = 0.f;
|
||||
constants.fogi[3] = 1;
|
||||
constants.fogParam3 = 0;
|
||||
}
|
||||
dirty = true;
|
||||
}
|
||||
|
@ -279,12 +432,68 @@ void PixelShaderManager::SetFogRangeAdjustChanged()
|
|||
return;
|
||||
|
||||
s_bFogRangeAdjustChanged = true;
|
||||
|
||||
if (constants.fogRangeBase != bpmem.fogRange.Base.hex)
|
||||
{
|
||||
constants.fogRangeBase = bpmem.fogRange.Base.hex;
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void PixelShaderManager::SetGenModeChanged()
|
||||
{
|
||||
constants.genmode = bpmem.genMode.hex;
|
||||
s_bIndirectDirty = true;
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
void PixelShaderManager::SetZControlChanged()
|
||||
{
|
||||
u32 early_ztest = bpmem.zcontrol.early_ztest ? 1 : 0;
|
||||
u32 rgba6_format =
|
||||
(bpmem.zcontrol.pixel_format == PEControl::RGBA6_Z24 && !g_ActiveConfig.bForceTrueColor) ? 1 :
|
||||
0;
|
||||
u32 dither = rgba6_format && bpmem.blendmode.dither;
|
||||
if (constants.early_ztest != early_ztest || constants.rgba6_format != rgba6_format ||
|
||||
constants.dither != dither)
|
||||
{
|
||||
constants.early_ztest = early_ztest;
|
||||
constants.rgba6_format = rgba6_format;
|
||||
constants.dither = dither;
|
||||
dirty = true;
|
||||
}
|
||||
s_bDestAlphaDirty = true;
|
||||
}
|
||||
|
||||
void PixelShaderManager::SetBlendModeChanged()
|
||||
{
|
||||
u32 dither = constants.rgba6_format && bpmem.blendmode.dither;
|
||||
if (constants.dither != dither)
|
||||
{
|
||||
constants.dither = dither;
|
||||
dirty = true;
|
||||
}
|
||||
s_bDestAlphaDirty = true;
|
||||
}
|
||||
|
||||
void PixelShaderManager::SetBoundingBoxActive(bool active)
|
||||
{
|
||||
const bool enable =
|
||||
active && g_ActiveConfig.bBBoxEnable && g_ActiveConfig.BBoxUseFragmentShaderImplementation();
|
||||
|
||||
if (enable == (constants.bounding_box != 0))
|
||||
return;
|
||||
|
||||
constants.bounding_box = active;
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
void PixelShaderManager::DoState(PointerWrap& p)
|
||||
{
|
||||
p.Do(s_bFogRangeAdjustChanged);
|
||||
p.Do(s_bViewPortChanged);
|
||||
p.Do(s_bIndirectDirty);
|
||||
p.Do(s_bDestAlphaDirty);
|
||||
|
||||
p.Do(constants);
|
||||
|
||||
|
|
|
@ -24,24 +24,36 @@ public:
|
|||
// so make sure to call them after memory is committed
|
||||
static void SetTevColor(int index, int component, s32 value);
|
||||
static void SetTevKonstColor(int index, int component, s32 value);
|
||||
static void SetTevOrder(int index, u32 order);
|
||||
static void SetTevKSel(int index, u32 ksel);
|
||||
static void SetTevCombiner(int index, int alpha, u32 combiner);
|
||||
static void SetAlpha();
|
||||
static void SetDestAlpha();
|
||||
static void SetAlphaTestChanged();
|
||||
static void SetDestAlphaChanged();
|
||||
static void SetTexDims(int texmapid, u32 width, u32 height);
|
||||
static void SetZTextureBias();
|
||||
static void SetViewportChanged();
|
||||
static void SetEfbScaleChanged(float scalex, float scaley);
|
||||
static void SetZSlope(float dfdx, float dfdy, float f0);
|
||||
static void SetIndMatrixChanged(int matrixidx);
|
||||
static void SetTevIndirectChanged();
|
||||
static void SetZTextureTypeChanged();
|
||||
static void SetZTextureOpChanged();
|
||||
static void SetIndTexScaleChanged(bool high);
|
||||
static void SetTexCoordChanged(u8 texmapid);
|
||||
static void SetFogColorChanged();
|
||||
static void SetFogParamChanged();
|
||||
static void SetFogRangeAdjustChanged();
|
||||
static void SetGenModeChanged();
|
||||
static void SetZControlChanged();
|
||||
static void SetBlendModeChanged();
|
||||
static void SetBoundingBoxActive(bool active);
|
||||
|
||||
static PixelShaderConstants constants;
|
||||
static bool dirty;
|
||||
|
||||
static bool s_bFogRangeAdjustChanged;
|
||||
static bool s_bViewPortChanged;
|
||||
static bool s_bIndirectDirty;
|
||||
static bool s_bDestAlphaDirty;
|
||||
};
|
||||
|
|
|
@ -29,6 +29,9 @@ ShaderHostConfig ShaderHostConfig::GetCurrent()
|
|||
bits.backend_atomics = g_ActiveConfig.backend_info.bSupportsFragmentStoresAndAtomics;
|
||||
bits.backend_depth_clamp = g_ActiveConfig.backend_info.bSupportsDepthClamp;
|
||||
bits.backend_reversed_depth_range = g_ActiveConfig.backend_info.bSupportsReversedDepthRange;
|
||||
bits.backend_bitfield = g_ActiveConfig.backend_info.bSupportsBitfield;
|
||||
bits.backend_dynamic_sampler_indexing =
|
||||
g_ActiveConfig.backend_info.bSupportsDynamicSamplerIndexing;
|
||||
return bits;
|
||||
}
|
||||
|
||||
|
@ -65,7 +68,7 @@ std::string GetDiskShaderCacheFileName(APIType api_type, const char* type, bool
|
|||
|
||||
if (include_host_config)
|
||||
{
|
||||
// We're using 18 bits, so 5 hex characters.
|
||||
// We're using 20 bits, so 5 hex characters.
|
||||
ShaderHostConfig host_config = ShaderHostConfig::GetCurrent();
|
||||
filename += StringFromFormat("-%05X", host_config.bits);
|
||||
}
|
||||
|
|
|
@ -176,7 +176,9 @@ union ShaderHostConfig
|
|||
u32 backend_atomics : 1;
|
||||
u32 backend_depth_clamp : 1;
|
||||
u32 backend_reversed_depth_range : 1;
|
||||
u32 pad : 14;
|
||||
u32 backend_bitfield : 1;
|
||||
u32 backend_dynamic_sampler_indexing : 1;
|
||||
u32 pad : 12;
|
||||
};
|
||||
|
||||
static ShaderHostConfig GetCurrent();
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "VideoCommon/UberShaderCommon.h"
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "VideoCommon/ShaderGenCommon.h"
|
||||
#include "VideoCommon/VideoCommon.h"
|
||||
|
||||
namespace UberShader
|
||||
{
|
||||
// Common functions across all ubershaders
|
||||
void WriteUberShaderCommonHeader(ShaderCode& out, APIType api_type,
|
||||
const ShaderHostConfig& host_config);
|
||||
|
||||
// bitfieldExtract generator for BitField types
|
||||
template <typename T>
|
||||
std::string BitfieldExtract(const std::string& source, T type)
|
||||
{
|
||||
return StringFromFormat("bitfieldExtract(%s, %u, %u)", source.c_str(),
|
||||
static_cast<u32>(type.StartBit()), static_cast<u32>(type.NumBits()));
|
||||
}
|
||||
|
||||
} // namespace UberShader
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,31 @@
|
|||
// Copyright 2015 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include "VideoCommon/PixelShaderGen.h"
|
||||
|
||||
namespace UberShader
|
||||
{
|
||||
#pragma pack(1)
|
||||
struct pixel_ubershader_uid_data
|
||||
{
|
||||
u32 num_texgens : 4;
|
||||
u32 early_depth : 1;
|
||||
u32 per_pixel_depth : 1;
|
||||
|
||||
u32 NumValues() const { return sizeof(pixel_ubershader_uid_data); }
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
typedef ShaderUid<pixel_ubershader_uid_data> PixelShaderUid;
|
||||
|
||||
PixelShaderUid GetPixelShaderUid();
|
||||
|
||||
ShaderCode GenPixelShader(APIType ApiType, const ShaderHostConfig& host_config,
|
||||
const pixel_ubershader_uid_data* uid_data);
|
||||
|
||||
void EnumeratePixelShaderUids(const std::function<void(const PixelShaderUid&)>& callback);
|
||||
}
|
|
@ -67,6 +67,8 @@
|
|||
<ClCompile Include="RenderState.cpp" />
|
||||
<ClCompile Include="LightingShaderGen.cpp" />
|
||||
<ClCompile Include="ShaderGenCommon.cpp" />
|
||||
<ClCompile Include="UberShaderCommon.cpp" />
|
||||
<ClCompile Include="UberShaderPixel.cpp" />
|
||||
<ClCompile Include="Statistics.cpp" />
|
||||
<ClCompile Include="GeometryShaderGen.cpp" />
|
||||
<ClCompile Include="GeometryShaderManager.cpp" />
|
||||
|
@ -109,6 +111,8 @@
|
|||
<ClInclude Include="Fifo.h" />
|
||||
<ClInclude Include="FPSCounter.h" />
|
||||
<ClInclude Include="FramebufferManagerBase.h" />
|
||||
<ClInclude Include="UberShaderCommon.h" />
|
||||
<ClInclude Include="UberShaderPixel.h" />
|
||||
<ClInclude Include="HiresTextures.h" />
|
||||
<ClInclude Include="ImageWrite.h" />
|
||||
<ClInclude Include="IndexGenerator.h" />
|
||||
|
@ -174,4 +178,4 @@
|
|||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
@ -179,6 +179,12 @@
|
|||
<ClCompile Include="AsyncShaderCompiler.cpp">
|
||||
<Filter>Util</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="UberShaderPixel.cpp">
|
||||
<Filter>Shader Generators</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="UberShaderCommon.cpp">
|
||||
<Filter>Shader Generators</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="CommandProcessor.h" />
|
||||
|
@ -338,6 +344,12 @@
|
|||
<ClInclude Include="AsyncShaderCompiler.h">
|
||||
<Filter>Util</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="UberShaderPixel.h">
|
||||
<Filter>Shader Generators</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="UberShaderCommon.h">
|
||||
<Filter>Shader Generators</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="CMakeLists.txt" />
|
||||
|
|
|
@ -204,6 +204,8 @@ struct VideoConfig final
|
|||
bool bSupportsInternalResolutionFrameDumps;
|
||||
bool bSupportsGPUTextureDecoding;
|
||||
bool bSupportsST3CTextures;
|
||||
bool bSupportsBitfield; // Needed by UberShaders, so must stay in VideoCommon
|
||||
bool bSupportsDynamicSamplerIndexing; // Needed by UberShaders, so must stay in VideoCommon
|
||||
} backend_info;
|
||||
|
||||
// Utility
|
||||
|
|
Loading…
Reference in New Issue