diff --git a/Data/Sys/Load/GraphicMods/All Games Blurred Bloom/all.txt b/Data/Sys/Load/GraphicMods/All Games Blurred Bloom/all.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/Data/Sys/Load/GraphicMods/All Games Blurred Bloom/blur.ps.glsl b/Data/Sys/Load/GraphicMods/All Games Blurred Bloom/blur.ps.glsl new file mode 100644 index 000000000000..3ad5cb585668 --- /dev/null +++ b/Data/Sys/Load/GraphicMods/All Games Blurred Bloom/blur.ps.glsl @@ -0,0 +1,45 @@ +void process_fragment(in DolphinFragmentInput frag_input, out DolphinFragmentOutput frag_output) +{ + int layer = int(frag_input.tex0.z); + int r = int(efb_scale) * int(SPREAD_MULTIPLIER); + int coord; + int length; + int2 initial_coords = int2(frag_input.tex0.xy * source_resolution.xy); + vec4 brightness = float4(1.0, 1.0, 1.0, 1.0); + if (HORIZONTAL) + { + length = int(source_resolution.x); + coord = initial_coords.x; + brightness = BRIGHTNESS_MULTIPLIER * brightness; + } + else + { + length = int(source_resolution.y); + coord = initial_coords.y; + } + + int offset; + vec4 count = vec4(0.0,0.0,0.0,0.0); + vec4 col = vec4(0.0,0.0,0.0,0.0); + for (offset = -r; offset <= r; offset++) + { + int pos = coord + offset; + if (pos <= length && pos >= 0) + { + int3 sample_coords; + if (HORIZONTAL) + { + sample_coords = int3(int2(pos, initial_coords.y), layer); + } + else + { + sample_coords = int3(int2(initial_coords.x, pos), layer); + } + + col += texelFetch(samp0, sample_coords, 0); + count += vec4(1.0,1.0,1.0,1.0); + } + } + frag_output.main = col / count * brightness; + +} diff --git a/Data/Sys/Load/GraphicMods/All Games Blurred Bloom/blur.rastershader b/Data/Sys/Load/GraphicMods/All Games Blurred Bloom/blur.rastershader new file mode 100644 index 000000000000..6c66f0b81ed0 --- /dev/null +++ b/Data/Sys/Load/GraphicMods/All Games Blurred Bloom/blur.rastershader @@ -0,0 +1,23 @@ +{ + "properties":[ + { + "code_name": "HORIZONTAL", + "default": true, + "description": "Whether to apply the blur horizontally or vertically", + "type": "bool" + }, + { + "code_name": "SPREAD_MULTIPLIER", + "default": 1.0, + "description": "How much to spread the blur", + "type": "float" + }, + { + "code_name": "BRIGHTNESS_MULTIPLIER", + "default": 1.0, + "description": "How bright the blur is", + "type": "float" + } + ], + "samplers":[] +} diff --git a/Data/Sys/Load/GraphicMods/All Games Blurred Bloom/blur.vs.glsl b/Data/Sys/Load/GraphicMods/All Games Blurred Bloom/blur.vs.glsl new file mode 100644 index 000000000000..68d5c367789e --- /dev/null +++ b/Data/Sys/Load/GraphicMods/All Games Blurred Bloom/blur.vs.glsl @@ -0,0 +1,4 @@ +void process_vertex(in DolphinVertexInput vertex_input, out DolphinVertexOutput vertex_output) +{ + dolphin_process_emulated_vertex(vertex_input, vertex_output); +} diff --git a/Data/Sys/Load/GraphicMods/All Games Blurred Bloom/blur_horizontal.rastermaterial b/Data/Sys/Load/GraphicMods/All Games Blurred Bloom/blur_horizontal.rastermaterial new file mode 100644 index 000000000000..a2b869a21416 --- /dev/null +++ b/Data/Sys/Load/GraphicMods/All Games Blurred Bloom/blur_horizontal.rastermaterial @@ -0,0 +1,19 @@ +{ + "next_material_asset":"dolphin_bloom_blur_vertical", + "properties":[ + { + "type": "bool", + "value": true + }, + { + "type": "float", + "value": 1.0 + }, + { + "type": "float", + "value": 1.0 + } + ], + "textures":[], + "shader_asset": "dolphin_bloom_blur" +} diff --git a/Data/Sys/Load/GraphicMods/All Games Blurred Bloom/blur_vertical.rastermaterial b/Data/Sys/Load/GraphicMods/All Games Blurred Bloom/blur_vertical.rastermaterial new file mode 100644 index 000000000000..044d0a33f8e6 --- /dev/null +++ b/Data/Sys/Load/GraphicMods/All Games Blurred Bloom/blur_vertical.rastermaterial @@ -0,0 +1,19 @@ +{ + "next_material_asset":"", + "properties":[ + { + "type": "bool", + "value": false + }, + { + "type": "float", + "value": 1.0 + }, + { + "type": "float", + "value": 1.0 + } + ], + "textures":[], + "shader_asset": "dolphin_bloom_blur" +} diff --git a/Data/Sys/Load/GraphicMods/All Games Blurred Bloom/metadata.json b/Data/Sys/Load/GraphicMods/All Games Blurred Bloom/metadata.json new file mode 100644 index 000000000000..dad8bffcf873 --- /dev/null +++ b/Data/Sys/Load/GraphicMods/All Games Blurred Bloom/metadata.json @@ -0,0 +1,41 @@ +{ + "meta": + { + "title": "Bloom Blurred", + "author": "Dolphin Team", + "description": "Blurs the bloom." + }, + "features": + [ + { + "group": "Bloom", + "action": "custom_pipeline", + "action_data": + { + "material_asset": "dolphin_bloom_blur_horizontal" + } + } + ], + "assets": [ + { + "data": { + "metadata": "blur.rastershader", + "pixel_shader": "blur.ps.glsl", + "vertex_shader": "blur.vs.glsl" + }, + "name": "dolphin_bloom_blur" + }, + { + "data": { + "metadata": "blur_horizontal.rastermaterial" + }, + "name": "dolphin_bloom_blur_horizontal" + }, + { + "data": { + "metadata": "blur_vertical.rastermaterial" + }, + "name": "dolphin_bloom_blur_vertical" + } + ] +} diff --git a/Data/Sys/Load/GraphicMods/All Games Blurred DOF/all.txt b/Data/Sys/Load/GraphicMods/All Games Blurred DOF/all.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/Data/Sys/Load/GraphicMods/All Games Blurred DOF/blur.ps.glsl b/Data/Sys/Load/GraphicMods/All Games Blurred DOF/blur.ps.glsl new file mode 100644 index 000000000000..3ad5cb585668 --- /dev/null +++ b/Data/Sys/Load/GraphicMods/All Games Blurred DOF/blur.ps.glsl @@ -0,0 +1,45 @@ +void process_fragment(in DolphinFragmentInput frag_input, out DolphinFragmentOutput frag_output) +{ + int layer = int(frag_input.tex0.z); + int r = int(efb_scale) * int(SPREAD_MULTIPLIER); + int coord; + int length; + int2 initial_coords = int2(frag_input.tex0.xy * source_resolution.xy); + vec4 brightness = float4(1.0, 1.0, 1.0, 1.0); + if (HORIZONTAL) + { + length = int(source_resolution.x); + coord = initial_coords.x; + brightness = BRIGHTNESS_MULTIPLIER * brightness; + } + else + { + length = int(source_resolution.y); + coord = initial_coords.y; + } + + int offset; + vec4 count = vec4(0.0,0.0,0.0,0.0); + vec4 col = vec4(0.0,0.0,0.0,0.0); + for (offset = -r; offset <= r; offset++) + { + int pos = coord + offset; + if (pos <= length && pos >= 0) + { + int3 sample_coords; + if (HORIZONTAL) + { + sample_coords = int3(int2(pos, initial_coords.y), layer); + } + else + { + sample_coords = int3(int2(initial_coords.x, pos), layer); + } + + col += texelFetch(samp0, sample_coords, 0); + count += vec4(1.0,1.0,1.0,1.0); + } + } + frag_output.main = col / count * brightness; + +} diff --git a/Data/Sys/Load/GraphicMods/All Games Blurred DOF/blur.rastershader b/Data/Sys/Load/GraphicMods/All Games Blurred DOF/blur.rastershader new file mode 100644 index 000000000000..6c66f0b81ed0 --- /dev/null +++ b/Data/Sys/Load/GraphicMods/All Games Blurred DOF/blur.rastershader @@ -0,0 +1,23 @@ +{ + "properties":[ + { + "code_name": "HORIZONTAL", + "default": true, + "description": "Whether to apply the blur horizontally or vertically", + "type": "bool" + }, + { + "code_name": "SPREAD_MULTIPLIER", + "default": 1.0, + "description": "How much to spread the blur", + "type": "float" + }, + { + "code_name": "BRIGHTNESS_MULTIPLIER", + "default": 1.0, + "description": "How bright the blur is", + "type": "float" + } + ], + "samplers":[] +} diff --git a/Data/Sys/Load/GraphicMods/All Games Blurred DOF/blur.vs.glsl b/Data/Sys/Load/GraphicMods/All Games Blurred DOF/blur.vs.glsl new file mode 100644 index 000000000000..68d5c367789e --- /dev/null +++ b/Data/Sys/Load/GraphicMods/All Games Blurred DOF/blur.vs.glsl @@ -0,0 +1,4 @@ +void process_vertex(in DolphinVertexInput vertex_input, out DolphinVertexOutput vertex_output) +{ + dolphin_process_emulated_vertex(vertex_input, vertex_output); +} diff --git a/Data/Sys/Load/GraphicMods/All Games Blurred DOF/blur_horizontal.rastermaterial b/Data/Sys/Load/GraphicMods/All Games Blurred DOF/blur_horizontal.rastermaterial new file mode 100644 index 000000000000..ca9887f08241 --- /dev/null +++ b/Data/Sys/Load/GraphicMods/All Games Blurred DOF/blur_horizontal.rastermaterial @@ -0,0 +1,19 @@ +{ + "next_material_asset":"dolphin_dof_blur_vertical", + "properties":[ + { + "type": "bool", + "value": true + }, + { + "type": "float", + "value": 1.0 + }, + { + "type": "float", + "value": 1.0 + } + ], + "textures":[], + "shader_asset": "dolphin_dof_blur" +} diff --git a/Data/Sys/Load/GraphicMods/All Games Blurred DOF/blur_vertical.rastermaterial b/Data/Sys/Load/GraphicMods/All Games Blurred DOF/blur_vertical.rastermaterial new file mode 100644 index 000000000000..3934d7994f70 --- /dev/null +++ b/Data/Sys/Load/GraphicMods/All Games Blurred DOF/blur_vertical.rastermaterial @@ -0,0 +1,19 @@ +{ + "next_material_asset":"", + "properties":[ + { + "type": "bool", + "value": false + }, + { + "type": "float", + "value": 1.0 + }, + { + "type": "float", + "value": 1.0 + } + ], + "textures":[], + "shader_asset": "dolphin_dof_blur" +} diff --git a/Data/Sys/Load/GraphicMods/All Games Blurred DOF/metadata.json b/Data/Sys/Load/GraphicMods/All Games Blurred DOF/metadata.json new file mode 100644 index 000000000000..f111683c7618 --- /dev/null +++ b/Data/Sys/Load/GraphicMods/All Games Blurred DOF/metadata.json @@ -0,0 +1,41 @@ +{ + "meta": + { + "title": "DOF Blurred", + "author": "Dolphin Team", + "description": "Blurs the DOF (depth of field)." + }, + "features": + [ + { + "group": "DOF", + "action": "custom_pipeline", + "action_data": + { + "material_asset": "dolphin_dof_blur_horizontal" + } + } + ], + "assets": [ + { + "data": { + "metadata": "blur.rastershader", + "pixel_shader": "blur.ps.glsl", + "vertex_shader": "blur.vs.glsl" + }, + "name": "dolphin_dof_blur" + }, + { + "data": { + "metadata": "blur_horizontal.rastermaterial" + }, + "name": "dolphin_dof_blur_horizontal" + }, + { + "data": { + "metadata": "blur_vertical.rastermaterial" + }, + "name": "dolphin_dof_blur_vertical" + } + ] +} diff --git a/Data/Sys/Load/GraphicMods/Conduit 2/SC2.txt b/Data/Sys/Load/GraphicMods/Conduit 2/SC2.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/Data/Sys/Load/GraphicMods/Conduit 2/metadata.json b/Data/Sys/Load/GraphicMods/Conduit 2/metadata.json new file mode 100644 index 000000000000..06a2e2a24e33 --- /dev/null +++ b/Data/Sys/Load/GraphicMods/Conduit 2/metadata.json @@ -0,0 +1,31 @@ +{ + "meta": + { + "title": "Bloom Texture Definitions", + "author": "iwubcode" + }, + "groups": + [ + { + "name": "Bloom", + "targets": [ + { + "type": "efb", + "texture_filename": "efb1_n000022_40x28_6" + }, + { + "type": "efb", + "texture_filename": "efb1_n000021_80x56_6" + }, + { + "type": "efb", + "texture_filename": "efb1_n000020_160x112_6" + }, + { + "type": "efb", + "texture_filename": "efb1_n000025_320x224_6" + } + ] + } + ] +} diff --git a/Data/Sys/Load/GraphicMods/De Blob 2/SDB.txt b/Data/Sys/Load/GraphicMods/De Blob 2/SDB.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/Data/Sys/Load/GraphicMods/De Blob 2/metadata.json b/Data/Sys/Load/GraphicMods/De Blob 2/metadata.json new file mode 100644 index 000000000000..697d28c730e0 --- /dev/null +++ b/Data/Sys/Load/GraphicMods/De Blob 2/metadata.json @@ -0,0 +1,31 @@ +{ + "meta": + { + "title": "Bloom Texture Definitions", + "author": "iwubcode" + }, + "groups": + [ + { + "name": "Bloom", + "targets": [ + { + "type": "efb", + "texture_filename": "efb1_n000134_20x14_6" + }, + { + "type": "efb", + "texture_filename": "efb1_n000022_40x28_6" + }, + { + "type": "efb", + "texture_filename": "efb1_n000131_80x56_6" + }, + { + "type": "efb", + "texture_filename": "efb1_n000130_160x112_6" + } + ] + } + ] +} diff --git a/Data/Sys/Load/GraphicMods/De Blob/R6B.txt b/Data/Sys/Load/GraphicMods/De Blob/R6B.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/Data/Sys/Load/GraphicMods/De Blob/metadata.json b/Data/Sys/Load/GraphicMods/De Blob/metadata.json new file mode 100644 index 000000000000..697d28c730e0 --- /dev/null +++ b/Data/Sys/Load/GraphicMods/De Blob/metadata.json @@ -0,0 +1,31 @@ +{ + "meta": + { + "title": "Bloom Texture Definitions", + "author": "iwubcode" + }, + "groups": + [ + { + "name": "Bloom", + "targets": [ + { + "type": "efb", + "texture_filename": "efb1_n000134_20x14_6" + }, + { + "type": "efb", + "texture_filename": "efb1_n000022_40x28_6" + }, + { + "type": "efb", + "texture_filename": "efb1_n000131_80x56_6" + }, + { + "type": "efb", + "texture_filename": "efb1_n000130_160x112_6" + } + ] + } + ] +} diff --git a/Data/Sys/Load/GraphicMods/Epic Mickey 2/SER.txt b/Data/Sys/Load/GraphicMods/Epic Mickey 2/SER.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/Data/Sys/Load/GraphicMods/Epic Mickey 2/metadata.json b/Data/Sys/Load/GraphicMods/Epic Mickey 2/metadata.json new file mode 100644 index 000000000000..2859a3638e42 --- /dev/null +++ b/Data/Sys/Load/GraphicMods/Epic Mickey 2/metadata.json @@ -0,0 +1,19 @@ +{ + "meta": + { + "title": "Bloom Texture Definitions", + "author": "iwubcode" + }, + "groups": + [ + { + "name": "Bloom", + "targets": [ + { + "type": "efb", + "texture_filename": "efb1_n000038_160x120_6" + } + ] + } + ] +} diff --git a/Data/Sys/Load/GraphicMods/Epic Mickey/SEM.txt b/Data/Sys/Load/GraphicMods/Epic Mickey/SEM.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/Data/Sys/Load/GraphicMods/Epic Mickey/metadata.json b/Data/Sys/Load/GraphicMods/Epic Mickey/metadata.json new file mode 100644 index 000000000000..2859a3638e42 --- /dev/null +++ b/Data/Sys/Load/GraphicMods/Epic Mickey/metadata.json @@ -0,0 +1,19 @@ +{ + "meta": + { + "title": "Bloom Texture Definitions", + "author": "iwubcode" + }, + "groups": + [ + { + "name": "Bloom", + "targets": [ + { + "type": "efb", + "texture_filename": "efb1_n000038_160x120_6" + } + ] + } + ] +} diff --git a/Data/Sys/Load/GraphicMods/Go Vacation/SGV.txt b/Data/Sys/Load/GraphicMods/Go Vacation/SGV.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/Data/Sys/Load/GraphicMods/Go Vacation/metadata.json b/Data/Sys/Load/GraphicMods/Go Vacation/metadata.json new file mode 100644 index 000000000000..8ff30e05f3ac --- /dev/null +++ b/Data/Sys/Load/GraphicMods/Go Vacation/metadata.json @@ -0,0 +1,19 @@ +{ + "meta": + { + "title": "Bloom Texture Definitions", + "author": "iwubcode" + }, + "groups": + [ + { + "name": "Bloom", + "targets": [ + { + "type": "efb", + "texture_filename": "efb1_n000167_80x58_6" + } + ] + } + ] +} diff --git a/Data/Sys/Load/GraphicMods/Lego Batman/RLB.txt b/Data/Sys/Load/GraphicMods/Lego Batman/RLB.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/Data/Sys/Load/GraphicMods/Lego Batman/metadata.json b/Data/Sys/Load/GraphicMods/Lego Batman/metadata.json new file mode 100644 index 000000000000..79064099c4ef --- /dev/null +++ b/Data/Sys/Load/GraphicMods/Lego Batman/metadata.json @@ -0,0 +1,19 @@ +{ + "meta": + { + "title": "Bloom Texture Definitions", + "author": "iwubcode" + }, + "groups": + [ + { + "name": "Bloom", + "targets": [ + { + "type": "efb", + "texture_filename": "efb1_n000043_80x56_6" + } + ] + } + ] +} diff --git a/Data/Sys/Load/GraphicMods/Lord of the Rings Aragorns Quest/R8J.txt b/Data/Sys/Load/GraphicMods/Lord of the Rings Aragorns Quest/R8J.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/Data/Sys/Load/GraphicMods/Lord of the Rings Aragorns Quest/metadata.json b/Data/Sys/Load/GraphicMods/Lord of the Rings Aragorns Quest/metadata.json new file mode 100644 index 000000000000..6209265acb2f --- /dev/null +++ b/Data/Sys/Load/GraphicMods/Lord of the Rings Aragorns Quest/metadata.json @@ -0,0 +1,19 @@ +{ + "meta": + { + "title": "Bloom Texture Definitions", + "author": "iwubcode" + }, + "groups": + [ + { + "name": "Bloom", + "targets": [ + { + "type": "efb", + "texture_filename": "efb1_n000013_80x60_6" + } + ] + } + ] +} diff --git a/Data/Sys/Load/GraphicMods/LostWinds - Winter of the Melodias/WLO.txt b/Data/Sys/Load/GraphicMods/LostWinds - Winter of the Melodias/WLO.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/Data/Sys/Load/GraphicMods/LostWinds - Winter of the Melodias/metadata.json b/Data/Sys/Load/GraphicMods/LostWinds - Winter of the Melodias/metadata.json new file mode 100644 index 000000000000..5aa3459abf62 --- /dev/null +++ b/Data/Sys/Load/GraphicMods/LostWinds - Winter of the Melodias/metadata.json @@ -0,0 +1,19 @@ +{ + "meta": + { + "title": "Bloom Texture Definitions", + "author": "iwubcode" + }, + "groups": + [ + { + "name": "Bloom", + "targets": [ + { + "type": "efb", + "texture_filename": "efb1_n000015_320x224_6" + } + ] + } + ] +} diff --git a/Data/Sys/Load/GraphicMods/LostWinds/WLW.txt b/Data/Sys/Load/GraphicMods/LostWinds/WLW.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/Data/Sys/Load/GraphicMods/LostWinds/metadata.json b/Data/Sys/Load/GraphicMods/LostWinds/metadata.json new file mode 100644 index 000000000000..5aa3459abf62 --- /dev/null +++ b/Data/Sys/Load/GraphicMods/LostWinds/metadata.json @@ -0,0 +1,19 @@ +{ + "meta": + { + "title": "Bloom Texture Definitions", + "author": "iwubcode" + }, + "groups": + [ + { + "name": "Bloom", + "targets": [ + { + "type": "efb", + "texture_filename": "efb1_n000015_320x224_6" + } + ] + } + ] +} diff --git a/Data/Sys/Load/GraphicMods/Metroid Other M/R3O.txt b/Data/Sys/Load/GraphicMods/Metroid Other M/R3O.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/Data/Sys/Load/GraphicMods/Metroid Other M/metadata.json b/Data/Sys/Load/GraphicMods/Metroid Other M/metadata.json new file mode 100644 index 000000000000..7da2cdc7d6b9 --- /dev/null +++ b/Data/Sys/Load/GraphicMods/Metroid Other M/metadata.json @@ -0,0 +1,23 @@ +{ + "meta": + { + "title": "Bloom Texture Definitions", + "author": "iwubcode" + }, + "groups": + [ + { + "name": "Bloom", + "targets": [ + { + "type": "efb", + "texture_filename": "efb1_n000069_80x60_4" + }, + { + "type": "efb", + "texture_filename": "efb1_n000068_160x120_4" + } + ] + } + ] +} diff --git a/Data/Sys/Load/GraphicMods/Metroid Prime Trilogy/R3M.txt b/Data/Sys/Load/GraphicMods/Metroid Prime Trilogy/R3M.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/Data/Sys/Load/GraphicMods/Metroid Prime Trilogy/metadata.json b/Data/Sys/Load/GraphicMods/Metroid Prime Trilogy/metadata.json new file mode 100644 index 000000000000..9b7e4ad47f7a --- /dev/null +++ b/Data/Sys/Load/GraphicMods/Metroid Prime Trilogy/metadata.json @@ -0,0 +1,23 @@ +{ + "meta": + { + "title": "Bloom Texture Definitions", + "author": "autofire372" + }, + "groups": + [ + { + "name": "Bloom", + "targets": [ + { + "type": "efb", + "texture_filename": "efb1_n000023_320x224_4" + }, + { + "type": "efb", + "texture_filename": "efb1_n000024_320x224_4" + } + ] + } + ] +} diff --git a/Data/Sys/Load/GraphicMods/Overlord Dark Legend/ROA.txt b/Data/Sys/Load/GraphicMods/Overlord Dark Legend/ROA.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/Data/Sys/Load/GraphicMods/Overlord Dark Legend/metadata.json b/Data/Sys/Load/GraphicMods/Overlord Dark Legend/metadata.json new file mode 100644 index 000000000000..001bf4dc623c --- /dev/null +++ b/Data/Sys/Load/GraphicMods/Overlord Dark Legend/metadata.json @@ -0,0 +1,19 @@ +{ + "meta": + { + "title": "Bloom Texture Definitions", + "author": "Stalin15" + }, + "groups": + [ + { + "name": "Bloom", + "targets": [ + { + "type": "efb", + "texture_filename": "efb1_n000010_80x60_6" + } + ] + } + ] +} diff --git a/Data/Sys/Load/GraphicMods/Sonic Colors/metadata.json b/Data/Sys/Load/GraphicMods/Sonic Colors/metadata.json index 9be5ac94ea52..23e15e703fd6 100644 --- a/Data/Sys/Load/GraphicMods/Sonic Colors/metadata.json +++ b/Data/Sys/Load/GraphicMods/Sonic Colors/metadata.json @@ -13,39 +13,19 @@ "type": "efb", "texture_filename": "efb1_n000007_160x120_6" }, - { - "type": "efb", - "texture_filename": "efb1_n000008_160x120_6" - }, { "type": "efb", "texture_filename": "efb1_n000009_80x60_6" }, - { - "type": "efb", - "texture_filename": "efb1_n000010_80x60_6" - }, { "type": "efb", "texture_filename": "efb1_n000011_40x30_6" }, - { - "type": "efb", - "texture_filename": "efb1_n000012_40x30_6" - }, { "type": "efb", "texture_filename": "efb1_n000013_20x15_6" - }, - { - "type": "efb", - "texture_filename": "efb1_n000014_20x15_6" - }, - { - "type": "efb", - "texture_filename": "efb1_n000015_160x120_6" } ] } ] -} \ No newline at end of file +} diff --git a/Data/Sys/Load/GraphicMods/Sonic Unleashed/RSV.txt b/Data/Sys/Load/GraphicMods/Sonic Unleashed/RSV.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/Data/Sys/Load/GraphicMods/Sonic Unleashed/metadata.json b/Data/Sys/Load/GraphicMods/Sonic Unleashed/metadata.json new file mode 100644 index 000000000000..ebb68825bea5 --- /dev/null +++ b/Data/Sys/Load/GraphicMods/Sonic Unleashed/metadata.json @@ -0,0 +1,23 @@ +{ + "meta": + { + "title": "Bloom Texture Definitions", + "author": "Dr. Azathoth" + }, + "groups": + [ + { + "name": "Bloom", + "targets": [ + { + "type": "efb", + "texture_filename": "efb1_320x240_6" + }, + { + "type": "efb", + "texture_filename": "efb1_640x480_1" + } + ] + } + ] +} diff --git a/Data/Sys/Load/GraphicMods/Spectrobes Origins/RXX.txt b/Data/Sys/Load/GraphicMods/Spectrobes Origins/RXX.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/Data/Sys/Load/GraphicMods/Spectrobes Origins/metadata.json b/Data/Sys/Load/GraphicMods/Spectrobes Origins/metadata.json new file mode 100644 index 000000000000..1c0f8449d10d --- /dev/null +++ b/Data/Sys/Load/GraphicMods/Spectrobes Origins/metadata.json @@ -0,0 +1,19 @@ +{ + "meta": + { + "title": "Bloom Texture Definitions", + "author": "iwubcode" + }, + "groups": + [ + { + "name": "Bloom", + "targets": [ + { + "type": "efb", + "texture_filename": "efb1_n000690_80x56_6" + } + ] + } + ] +} diff --git a/Data/Sys/Load/GraphicMods/Spyborgs/RSW.txt b/Data/Sys/Load/GraphicMods/Spyborgs/RSW.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/Data/Sys/Load/GraphicMods/Spyborgs/metadata.json b/Data/Sys/Load/GraphicMods/Spyborgs/metadata.json new file mode 100644 index 000000000000..e14989e54a68 --- /dev/null +++ b/Data/Sys/Load/GraphicMods/Spyborgs/metadata.json @@ -0,0 +1,23 @@ +{ + "meta": + { + "title": "Bloom Texture Definitions", + "author": "iwubcode" + }, + "groups": + [ + { + "name": "Bloom", + "targets": [ + { + "type": "efb", + "texture_filename": "efb1_n000102_80x66_6" + }, + { + "type": "efb", + "texture_filename": "efb1_n000025_320x232_6" + } + ] + } + ] +} diff --git a/Data/Sys/Load/GraphicMods/Takt of Magic/ROS.txt b/Data/Sys/Load/GraphicMods/Takt of Magic/ROS.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/Data/Sys/Load/GraphicMods/Takt of Magic/metadata.json b/Data/Sys/Load/GraphicMods/Takt of Magic/metadata.json new file mode 100644 index 000000000000..239960ddb124 --- /dev/null +++ b/Data/Sys/Load/GraphicMods/Takt of Magic/metadata.json @@ -0,0 +1,19 @@ +{ + "meta": + { + "title": "Bloom Texture Definitions", + "author": "iwubcode" + }, + "groups": + [ + { + "name": "Bloom", + "targets": [ + { + "type": "efb", + "texture_filename": "efb1_n000038_80x60_4" + } + ] + } + ] +} diff --git a/Data/Sys/Load/GraphicMods/Zangeki no Reginleiv/RZN.txt b/Data/Sys/Load/GraphicMods/Zangeki no Reginleiv/RZN.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/Data/Sys/Load/GraphicMods/Zangeki no Reginleiv/metadata.json b/Data/Sys/Load/GraphicMods/Zangeki no Reginleiv/metadata.json new file mode 100644 index 000000000000..ce0f1d1a8b0a --- /dev/null +++ b/Data/Sys/Load/GraphicMods/Zangeki no Reginleiv/metadata.json @@ -0,0 +1,19 @@ +{ + "meta": + { + "title": "Bloom Texture Definitions", + "author": "iwubcode" + }, + "groups": + [ + { + "name": "Bloom", + "targets": [ + { + "type": "efb", + "texture_filename": "efb1_n000102_80x66_6" + } + ] + } + ] +} diff --git a/Source/Core/VideoCommon/GraphicsModSystem/Runtime/Actions/CustomPipelineAction.cpp b/Source/Core/VideoCommon/GraphicsModSystem/Runtime/Actions/CustomPipelineAction.cpp index 7366ad7ff7cf..60cc4c9f80dd 100644 --- a/Source/Core/VideoCommon/GraphicsModSystem/Runtime/Actions/CustomPipelineAction.cpp +++ b/Source/Core/VideoCommon/GraphicsModSystem/Runtime/Actions/CustomPipelineAction.cpp @@ -3,22 +3,11 @@ #include "VideoCommon/GraphicsModSystem/Runtime/Actions/CustomPipelineAction.h" -#include -#include -#include - -#include - -#include "Common/FileUtil.h" +#include "Common/JsonUtil.h" #include "Common/Logging/Log.h" -#include "Common/StringUtil.h" -#include "Common/VariantUtil.h" #include "Core/System.h" -#include "VideoCommon/AbstractGfx.h" -#include "VideoCommon/Assets/DirectFilesystemAssetLibrary.h" -#include "VideoCommon/ShaderGenCommon.h" -#include "VideoCommon/TextureCacheBase.h" +#include "VideoCommon/Resources/CustomResourceManager.h" std::unique_ptr CustomPipelineAction::Create(std::shared_ptr library) @@ -30,58 +19,17 @@ std::unique_ptr CustomPipelineAction::Create(const picojson::value& json_data, std::shared_ptr library) { - std::vector pipeline_passes; + const auto material_asset = + ReadStringFromJson(json_data.get(), "material_asset"); - const auto& passes_json = json_data.get("passes"); - if (passes_json.is()) + if (!material_asset) { - for (const auto& passes_json_val : passes_json.get()) - { - CustomPipelineAction::PipelinePassPassDescription pipeline_pass; - if (!passes_json_val.is()) - { - ERROR_LOG_FMT(VIDEO, - "Failed to load custom pipeline action, 'passes' has an array value that " - "is not an object!"); - return nullptr; - } - - auto pass = passes_json_val.get(); - if (!pass.contains("pixel_material_asset")) - { - ERROR_LOG_FMT(VIDEO, - "Failed to load custom pipeline action, 'passes' value missing required " - "field 'pixel_material_asset'"); - return nullptr; - } - - auto pixel_material_asset_json = pass["pixel_material_asset"]; - if (!pixel_material_asset_json.is()) - { - ERROR_LOG_FMT(VIDEO, "Failed to load custom pipeline action, 'passes' field " - "'pixel_material_asset' is not a string!"); - return nullptr; - } - pipeline_pass.m_pixel_material_asset = pixel_material_asset_json.to_str(); - pipeline_passes.push_back(std::move(pipeline_pass)); - } - } - - if (pipeline_passes.empty()) - { - ERROR_LOG_FMT(VIDEO, "Failed to load custom pipeline action, must specify at least one pass"); + ERROR_LOG_FMT(VIDEO, + "Failed to load custom pipeline action, 'material_asset' does not have a value"); return nullptr; } - if (pipeline_passes.size() > 1) - { - ERROR_LOG_FMT( - VIDEO, - "Failed to load custom pipeline action, multiple passes are not currently supported"); - return nullptr; - } - - return std::make_unique(std::move(library), std::move(pipeline_passes)); + return std::make_unique(std::move(library), std::move(*material_asset)); } CustomPipelineAction::CustomPipelineAction(std::shared_ptr library) @@ -89,14 +37,29 @@ CustomPipelineAction::CustomPipelineAction(std::shared_ptr library, - std::vector pass_descriptions) - : m_library(std::move(library)), m_passes_config(std::move(pass_descriptions)) +CustomPipelineAction::CustomPipelineAction(std::shared_ptr library, + std::string material_asset) + : m_library(std::move(library)), m_material_asset(std::move(material_asset)) { - m_pipeline_passes.resize(m_passes_config.size()); } void CustomPipelineAction::OnDrawStarted(GraphicsModActionData::DrawStarted*) { + // TODO +} + +void CustomPipelineAction::AfterEFB(GraphicsModActionData::PostEFB* post_efb) +{ + if (!post_efb) [[unlikely]] + return; + + if (!post_efb->material) [[unlikely]] + return; + + if (m_material_asset.empty()) + return; + + auto& resource_manager = Core::System::GetInstance().GetCustomResourceManager(); + *post_efb->material = + resource_manager.GetPostProcessingMaterialFromAsset(m_material_asset, m_library); } diff --git a/Source/Core/VideoCommon/GraphicsModSystem/Runtime/Actions/CustomPipelineAction.h b/Source/Core/VideoCommon/GraphicsModSystem/Runtime/Actions/CustomPipelineAction.h index 99026b99cea9..d03ccd4a6e57 100644 --- a/Source/Core/VideoCommon/GraphicsModSystem/Runtime/Actions/CustomPipelineAction.h +++ b/Source/Core/VideoCommon/GraphicsModSystem/Runtime/Actions/CustomPipelineAction.h @@ -6,22 +6,15 @@ #include #include #include -#include #include #include "VideoCommon/Assets/CustomAssetLibrary.h" -#include "VideoCommon/GraphicsModSystem/Runtime/CustomPipeline.h" #include "VideoCommon/GraphicsModSystem/Runtime/GraphicsModAction.h" class CustomPipelineAction final : public GraphicsModAction { public: - struct PipelinePassPassDescription - { - std::string m_pixel_material_asset; - }; - static constexpr std::string_view factory_name = "custom_pipeline"; static std::unique_ptr Create(const picojson::value& json_data, @@ -30,11 +23,11 @@ class CustomPipelineAction final : public GraphicsModAction Create(std::shared_ptr library); explicit CustomPipelineAction(std::shared_ptr library); CustomPipelineAction(std::shared_ptr library, - std::vector pass_descriptions); + std::string material_asset); void OnDrawStarted(GraphicsModActionData::DrawStarted*) override; + void AfterEFB(GraphicsModActionData::PostEFB*) override; private: std::shared_ptr m_library; - std::vector m_passes_config; - std::vector m_pipeline_passes; + std::string m_material_asset; }; diff --git a/Source/Core/VideoCommon/GraphicsModSystem/Runtime/Actions/PrintAction.cpp b/Source/Core/VideoCommon/GraphicsModSystem/Runtime/Actions/PrintAction.cpp index 1bd288512cac..ca50a9a43039 100644 --- a/Source/Core/VideoCommon/GraphicsModSystem/Runtime/Actions/PrintAction.cpp +++ b/Source/Core/VideoCommon/GraphicsModSystem/Runtime/Actions/PrintAction.cpp @@ -10,7 +10,7 @@ void PrintAction::OnDrawStarted(GraphicsModActionData::DrawStarted*) INFO_LOG_FMT(VIDEO, "OnDrawStarted Called"); } -void PrintAction::OnEFB(GraphicsModActionData::EFB* efb) +void PrintAction::BeforeEFB(GraphicsModActionData::PreEFB* efb) { if (!efb) [[unlikely]] return; diff --git a/Source/Core/VideoCommon/GraphicsModSystem/Runtime/Actions/PrintAction.h b/Source/Core/VideoCommon/GraphicsModSystem/Runtime/Actions/PrintAction.h index 82a21c152ff8..55bd694a6ea5 100644 --- a/Source/Core/VideoCommon/GraphicsModSystem/Runtime/Actions/PrintAction.h +++ b/Source/Core/VideoCommon/GraphicsModSystem/Runtime/Actions/PrintAction.h @@ -12,7 +12,7 @@ class PrintAction final : public GraphicsModAction public: static constexpr std::string_view factory_name = "print"; void OnDrawStarted(GraphicsModActionData::DrawStarted*) override; - void OnEFB(GraphicsModActionData::EFB*) override; + void BeforeEFB(GraphicsModActionData::PreEFB*) override; void OnProjection(GraphicsModActionData::Projection*) override; void OnProjectionAndTexture(GraphicsModActionData::Projection*) override; void OnTextureLoad(GraphicsModActionData::TextureLoad*) override; diff --git a/Source/Core/VideoCommon/GraphicsModSystem/Runtime/Actions/ScaleAction.cpp b/Source/Core/VideoCommon/GraphicsModSystem/Runtime/Actions/ScaleAction.cpp index 305cd8b7374c..6db08b8351aa 100644 --- a/Source/Core/VideoCommon/GraphicsModSystem/Runtime/Actions/ScaleAction.cpp +++ b/Source/Core/VideoCommon/GraphicsModSystem/Runtime/Actions/ScaleAction.cpp @@ -30,7 +30,7 @@ ScaleAction::ScaleAction(Common::Vec3 scale) : m_scale(scale) { } -void ScaleAction::OnEFB(GraphicsModActionData::EFB* efb) +void ScaleAction::BeforeEFB(GraphicsModActionData::PreEFB* efb) { if (!efb) [[unlikely]] return; diff --git a/Source/Core/VideoCommon/GraphicsModSystem/Runtime/Actions/ScaleAction.h b/Source/Core/VideoCommon/GraphicsModSystem/Runtime/Actions/ScaleAction.h index 4673ed2d1864..2ed9d7139370 100644 --- a/Source/Core/VideoCommon/GraphicsModSystem/Runtime/Actions/ScaleAction.h +++ b/Source/Core/VideoCommon/GraphicsModSystem/Runtime/Actions/ScaleAction.h @@ -16,7 +16,7 @@ class ScaleAction final : public GraphicsModAction static constexpr std::string_view factory_name = "scale"; static std::unique_ptr Create(const picojson::value& json_data); explicit ScaleAction(Common::Vec3 scale); - void OnEFB(GraphicsModActionData::EFB*) override; + void BeforeEFB(GraphicsModActionData::PreEFB*) override; void OnProjection(GraphicsModActionData::Projection*) override; void OnProjectionAndTexture(GraphicsModActionData::Projection*) override; diff --git a/Source/Core/VideoCommon/GraphicsModSystem/Runtime/Actions/SkipAction.cpp b/Source/Core/VideoCommon/GraphicsModSystem/Runtime/Actions/SkipAction.cpp index b693fef4f78a..3473826fc5c8 100644 --- a/Source/Core/VideoCommon/GraphicsModSystem/Runtime/Actions/SkipAction.cpp +++ b/Source/Core/VideoCommon/GraphicsModSystem/Runtime/Actions/SkipAction.cpp @@ -14,7 +14,7 @@ void SkipAction::OnDrawStarted(GraphicsModActionData::DrawStarted* draw_started) *draw_started->skip = true; } -void SkipAction::OnEFB(GraphicsModActionData::EFB* efb) +void SkipAction::BeforeEFB(GraphicsModActionData::PreEFB* efb) { if (!efb) [[unlikely]] return; diff --git a/Source/Core/VideoCommon/GraphicsModSystem/Runtime/Actions/SkipAction.h b/Source/Core/VideoCommon/GraphicsModSystem/Runtime/Actions/SkipAction.h index 8cda643c5ab5..df397802ae49 100644 --- a/Source/Core/VideoCommon/GraphicsModSystem/Runtime/Actions/SkipAction.h +++ b/Source/Core/VideoCommon/GraphicsModSystem/Runtime/Actions/SkipAction.h @@ -10,5 +10,5 @@ class SkipAction final : public GraphicsModAction public: static constexpr std::string_view factory_name = "skip"; void OnDrawStarted(GraphicsModActionData::DrawStarted*) override; - void OnEFB(GraphicsModActionData::EFB*) override; + void BeforeEFB(GraphicsModActionData::PreEFB*) override; }; diff --git a/Source/Core/VideoCommon/GraphicsModSystem/Runtime/GraphicsModAction.h b/Source/Core/VideoCommon/GraphicsModSystem/Runtime/GraphicsModAction.h index 04a371a73e42..5719d550fea1 100644 --- a/Source/Core/VideoCommon/GraphicsModSystem/Runtime/GraphicsModAction.h +++ b/Source/Core/VideoCommon/GraphicsModSystem/Runtime/GraphicsModAction.h @@ -16,8 +16,9 @@ class GraphicsModAction GraphicsModAction& operator=(GraphicsModAction&&) = default; virtual void OnDrawStarted(GraphicsModActionData::DrawStarted*) {} - virtual void OnEFB(GraphicsModActionData::EFB*) {} - virtual void OnXFB() {} + virtual void BeforeEFB(GraphicsModActionData::PreEFB*) {} + virtual void AfterEFB(GraphicsModActionData::PostEFB*) {} + virtual void BeforeXFB() {} virtual void OnProjection(GraphicsModActionData::Projection*) {} virtual void OnProjectionAndTexture(GraphicsModActionData::Projection*) {} virtual void OnTextureLoad(GraphicsModActionData::TextureLoad*) {} diff --git a/Source/Core/VideoCommon/GraphicsModSystem/Runtime/GraphicsModActionData.h b/Source/Core/VideoCommon/GraphicsModSystem/Runtime/GraphicsModActionData.h index f7c12fe6e511..9b5b6e3541bf 100644 --- a/Source/Core/VideoCommon/GraphicsModSystem/Runtime/GraphicsModActionData.h +++ b/Source/Core/VideoCommon/GraphicsModSystem/Runtime/GraphicsModActionData.h @@ -14,6 +14,7 @@ #include "Common/SmallVector.h" #include "VideoCommon/Assets/TextureAsset.h" #include "VideoCommon/PixelShaderGen.h" +#include "VideoCommon/Resources/MaterialResource.h" namespace GraphicsModActionData { @@ -25,7 +26,7 @@ struct DrawStarted std::span* material_uniform_buffer; }; -struct EFB +struct PreEFB { u32 texture_width; u32 texture_height; @@ -34,6 +35,11 @@ struct EFB u32* scaled_height; }; +struct PostEFB +{ + VideoCommon::MaterialResource** material; +}; + struct Projection { Common::Matrix44* matrix; diff --git a/Source/Core/VideoCommon/GraphicsModSystem/Runtime/GraphicsModManager.cpp b/Source/Core/VideoCommon/GraphicsModSystem/Runtime/GraphicsModManager.cpp index 3caaa999fd70..848fae2ededf 100644 --- a/Source/Core/VideoCommon/GraphicsModSystem/Runtime/GraphicsModManager.cpp +++ b/Source/Core/VideoCommon/GraphicsModSystem/Runtime/GraphicsModManager.cpp @@ -7,6 +7,7 @@ #include #include +#include "Common/FileUtil.h" #include "Common/Logging/Log.h" #include "Common/StringUtil.h" #include "Common/VariantUtil.h" @@ -17,6 +18,7 @@ #include "VideoCommon/GraphicsModSystem/Config/GraphicsMod.h" #include "VideoCommon/GraphicsModSystem/Config/GraphicsModAsset.h" #include "VideoCommon/GraphicsModSystem/Config/GraphicsModGroup.h" +#include "VideoCommon/GraphicsModSystem/Constants.h" #include "VideoCommon/GraphicsModSystem/Runtime/GraphicsModActionFactory.h" #include "VideoCommon/TextureInfo.h" #include "VideoCommon/VideoConfig.h" @@ -36,11 +38,17 @@ class GraphicsModManager::DecoratedAction final : public GraphicsModAction return; m_action_impl->OnDrawStarted(draw_started); } - void OnEFB(GraphicsModActionData::EFB* efb) override + void BeforeEFB(GraphicsModActionData::PreEFB* efb) override { if (!m_mod.m_enabled) return; - m_action_impl->OnEFB(efb); + m_action_impl->BeforeEFB(efb); + } + void AfterEFB(GraphicsModActionData::PostEFB* efb) override + { + if (!m_mod.m_enabled) + return; + m_action_impl->AfterEFB(efb); } void OnProjection(GraphicsModActionData::Projection* projection) override { @@ -191,6 +199,8 @@ void GraphicsModManager::Load(const GraphicsModGroupConfig& config) const auto& mods = config.GetMods(); auto filesystem_library = std::make_shared(); + filesystem_library->Watch(File::GetSysDirectory() + DOLPHIN_SYSTEM_GRAPHICS_MOD_DIR); + filesystem_library->Watch(File::GetUserPath(D_GRAPHICSMOD_IDX)); std::map> group_to_targets; for (const auto& mod : mods) diff --git a/Source/Core/VideoCommon/Resources/CustomResourceManager.cpp b/Source/Core/VideoCommon/Resources/CustomResourceManager.cpp index ffb16b055a43..1c571dc2a823 100644 --- a/Source/Core/VideoCommon/Resources/CustomResourceManager.cpp +++ b/Source/Core/VideoCommon/Resources/CustomResourceManager.cpp @@ -43,7 +43,8 @@ void CustomResourceManager::Shutdown() void CustomResourceManager::Reset() { - m_material_resources.clear(); + m_draw_material_resources.clear(); + m_postprocessing_material_resources.clear(); m_shader_resources.clear(); m_texture_data_resources.clear(); m_texture_sampler_resources.clear(); @@ -102,11 +103,11 @@ TextureDataResource* CustomResourceManager::GetTextureDataFromAsset( return resource.get(); } -MaterialResource* CustomResourceManager::GetMaterialFromAsset( +MaterialResource* CustomResourceManager::GetDrawMaterialFromAsset( const CustomAssetLibrary::AssetID& asset_id, const GXPipelineUid& pipeline_uid, std::shared_ptr library) { - auto& resource = m_material_resources[asset_id][PipelineToHash(pipeline_uid)]; + auto& resource = m_draw_material_resources[asset_id][PipelineToHash(pipeline_uid)]; if (resource == nullptr) { resource = std::make_unique( @@ -116,17 +117,31 @@ MaterialResource* CustomResourceManager::GetMaterialFromAsset( return resource.get(); } -ShaderResource* -CustomResourceManager::GetShaderFromAsset(const CustomAssetLibrary::AssetID& asset_id, - std::size_t shader_key, const GXPipelineUid& pipeline_uid, - const std::string& preprocessor_settings, - std::shared_ptr library) +MaterialResource* CustomResourceManager::GetPostProcessingMaterialFromAsset( + const CustomAssetLibrary::AssetID& asset_id, + std::shared_ptr library) +{ + auto& resource = m_postprocessing_material_resources[asset_id]; + if (resource == nullptr) + { + resource = + std::make_unique(CreateResourceContext(asset_id, std::move(library))); + } + resource->Process(); + return resource.get(); +} + +ShaderResource* CustomResourceManager::GetShaderFromAsset( + const CustomAssetLibrary::AssetID& asset_id, std::size_t shader_key, + std::optional pipeline_uid, const std::string& preprocessor_settings, + std::shared_ptr library) { auto& resource = m_shader_resources[asset_id][shader_key]; if (resource == nullptr) { resource = std::make_unique(CreateResourceContext(asset_id, std::move(library)), - pipeline_uid, preprocessor_settings, m_host_config); + std::move(pipeline_uid), preprocessor_settings, + m_host_config); } resource->Process(); return resource.get(); diff --git a/Source/Core/VideoCommon/Resources/CustomResourceManager.h b/Source/Core/VideoCommon/Resources/CustomResourceManager.h index 04eaa4694254..fcced2cdc2a1 100644 --- a/Source/Core/VideoCommon/Resources/CustomResourceManager.h +++ b/Source/Core/VideoCommon/Resources/CustomResourceManager.h @@ -37,14 +37,20 @@ class CustomResourceManager TextureDataResource* GetTextureDataFromAsset(const CustomAssetLibrary::AssetID& asset_id, std::shared_ptr library); - MaterialResource* GetMaterialFromAsset(const CustomAssetLibrary::AssetID& asset_id, - const GXPipelineUid& pipeline_uid, - std::shared_ptr library); + MaterialResource* + GetDrawMaterialFromAsset(const CustomAssetLibrary::AssetID& asset_id, + const GXPipelineUid& pipeline_uid, + std::shared_ptr library); + MaterialResource* + GetPostProcessingMaterialFromAsset(const CustomAssetLibrary::AssetID& asset_id, + std::shared_ptr library); ShaderResource* GetShaderFromAsset(const CustomAssetLibrary::AssetID& asset_id, - std::size_t shader_key, const GXPipelineUid& pipeline_uid, + std::size_t shader_key, + std::optional pipeline_uid, const std::string& preprocessor_settings, std::shared_ptr library); + TextureAndSamplerResource* GetTextureAndSamplerFromAsset(const CustomAssetLibrary::AssetID& asset_id, std::shared_ptr library); @@ -59,7 +65,7 @@ class CustomResourceManager std::unique_ptr m_async_shader_compiler; using PipelineIdToMaterial = std::map>; - std::map m_material_resources; + std::map m_draw_material_resources; using ShaderKeyToShader = std::map>; std::map m_shader_resources; @@ -70,6 +76,9 @@ class CustomResourceManager std::map> m_texture_sampler_resources; + std::map> + m_postprocessing_material_resources; + ShaderHostConfig m_host_config; Common::EventHook m_xfb_event; diff --git a/Source/Core/VideoCommon/Resources/MaterialResource.cpp b/Source/Core/VideoCommon/Resources/MaterialResource.cpp index 657647ffb98b..e0afce502259 100644 --- a/Source/Core/VideoCommon/Resources/MaterialResource.cpp +++ b/Source/Core/VideoCommon/Resources/MaterialResource.cpp @@ -52,6 +52,13 @@ SamplerState CalculateSamplerAnisotropy(const SamplerState& initial_sampler) namespace VideoCommon { +MaterialResource::MaterialResource(Resource::ResourceContext resource_context) + : Resource(std::move(resource_context)) +{ + m_material_asset = m_resource_context.asset_cache->CreateAsset( + m_resource_context.primary_asset_id, m_resource_context.asset_library, this); +} + MaterialResource::MaterialResource(Resource::ResourceContext resource_context, const GXPipelineUid& pipeline_uid) : Resource(std::move(resource_context)), m_uid(pipeline_uid) @@ -59,8 +66,8 @@ MaterialResource::MaterialResource(Resource::ResourceContext resource_context, m_material_asset = m_resource_context.asset_cache->CreateAsset( m_resource_context.primary_asset_id, m_resource_context.asset_library, this); m_uid_vertex_format_copy = - g_gfx->CreateNativeVertexFormat(m_uid.vertex_format->GetVertexDeclaration()); - m_uid.vertex_format = m_uid_vertex_format_copy.get(); + g_gfx->CreateNativeVertexFormat(m_uid->vertex_format->GetVertexDeclaration()); + m_uid->vertex_format = m_uid_vertex_format_copy.get(); } void MaterialResource::ResetData() @@ -96,7 +103,7 @@ Resource::TaskComplete MaterialResource::CollectPrimaryData() } CreateTextureData(m_load_data.get()); - SetShaderKey(m_load_data.get(), &m_uid); + SetShaderKey(m_load_data.get(), m_uid ? &*m_uid : nullptr); return Resource::TaskComplete::Yes; } @@ -138,8 +145,18 @@ Resource::TaskComplete MaterialResource::CollectDependencyData() if (m_load_data->m_material_data->next_material_asset != "") { - m_load_data->m_next_material = m_resource_context.resource_manager->GetMaterialFromAsset( - m_load_data->m_material_data->next_material_asset, m_uid, m_resource_context.asset_library); + if (m_uid) + { + m_load_data->m_next_material = m_resource_context.resource_manager->GetDrawMaterialFromAsset( + m_load_data->m_material_data->next_material_asset, *m_uid, + m_resource_context.asset_library); + } + else + { + m_load_data->m_next_material = + m_resource_context.resource_manager->GetPostProcessingMaterialFromAsset( + m_load_data->m_material_data->next_material_asset, m_resource_context.asset_library); + } m_load_data->m_next_material->AddReference(this); const auto data_processed = m_load_data->m_next_material->IsDataProcessed(); if (data_processed == TaskComplete::Error) @@ -220,33 +237,66 @@ Resource::TaskComplete MaterialResource::ProcessData() config.pixel_shader = m_shader_resource_data->GetPixelShader(); config.geometry_shader = m_shader_resource_data->GetGeometryShader(); - const auto actual_uid = ApplyDriverBugs(*m_uid); - - if (m_material_resource_data->m_material_data->blending_state) - config.blending_state = *m_material_resource_data->m_material_data->blending_state; + if (m_uid) + { + // Draw based pipeline + const auto actual_uid = ApplyDriverBugs(*m_uid); + + if (m_material_resource_data->m_material_data->blending_state) + config.blending_state = *m_material_resource_data->m_material_data->blending_state; + else + config.blending_state = actual_uid.blending_state; + + if (m_material_resource_data->m_material_data->depth_state) + config.depth_state = *m_material_resource_data->m_material_data->depth_state; + else + config.depth_state = actual_uid.depth_state; + + config.framebuffer_state = std::move(m_frame_buffer_state); + config.framebuffer_state.additional_color_attachment_count = 0; + + config.rasterization_state = actual_uid.rasterization_state; + if (m_material_resource_data->m_material_data->cull_mode) + { + config.rasterization_state.cull_mode = + *m_material_resource_data->m_material_data->cull_mode; + } + + config.vertex_format = actual_uid.vertex_format; + config.usage = AbstractPipelineUsage::GX; + } else - config.blending_state = actual_uid.blending_state; + { + // Post processing based pipeline - if (m_material_resource_data->m_material_data->depth_state) - config.depth_state = *m_material_resource_data->m_material_data->depth_state; - else - config.depth_state = actual_uid.depth_state; + // Many of these properties don't make sense to replace but we expose them for draw + // based materials, might as well allow them to be used if the user wants - config.framebuffer_state = std::move(m_frame_buffer_state); - config.framebuffer_state.additional_color_attachment_count = 0; + if (m_material_resource_data->m_material_data->blending_state) + config.blending_state = *m_material_resource_data->m_material_data->blending_state; + else + config.blending_state = RenderState::GetNoBlendingBlendState(); - config.rasterization_state = actual_uid.rasterization_state; - if (m_material_resource_data->m_material_data->cull_mode) - { - config.rasterization_state.cull_mode = - *m_material_resource_data->m_material_data->cull_mode; - } + if (m_material_resource_data->m_material_data->depth_state) + config.depth_state = *m_material_resource_data->m_material_data->depth_state; + else + config.depth_state = RenderState::GetNoDepthTestingDepthState(); - config.vertex_format = actual_uid.vertex_format; - config.usage = AbstractPipelineUsage::GX; + config.framebuffer_state = RenderState::GetRGBA8FramebufferState(); - m_material_resource_data->m_pipeline = g_gfx->CreatePipeline(config); + config.rasterization_state = + RenderState::GetNoCullRasterizationState(PrimitiveType::Triangles); + if (m_material_resource_data->m_material_data->cull_mode) + { + config.rasterization_state.cull_mode = + *m_material_resource_data->m_material_data->cull_mode; + } + config.vertex_format = nullptr; + config.usage = AbstractPipelineUsage::Utility; + } + + m_material_resource_data->m_pipeline = g_gfx->CreatePipeline(config); if (m_material_resource_data->m_pipeline) { WriteUniforms(m_material_resource_data.get()); @@ -266,7 +316,7 @@ Resource::TaskComplete MaterialResource::ProcessData() if (!m_processing_load_data) { auto wi = m_resource_context.shader_compiler->CreateWorkItem( - m_load_data, std::move(shader_data), &m_uid, + m_load_data, std::move(shader_data), m_uid ? &*m_uid : nullptr, g_framebuffer_manager->GetEFBFramebufferState()); // We don't need priority, that is already handled by the resource system @@ -358,7 +408,8 @@ void MaterialResource::SetShaderKey(Data* data, GXPipelineUid* uid) XXH3_INITSTATE(&shader_key_hash); XXH3_64bits_reset_withSeed(&shader_key_hash, static_cast(1)); - UpdateHashWithPipeline(*uid, &shader_key_hash); + if (uid) + UpdateHashWithPipeline(*uid, &shader_key_hash); XXH3_64bits_update(&shader_key_hash, data->m_preprocessor_settings.c_str(), data->m_preprocessor_settings.size()); diff --git a/Source/Core/VideoCommon/Resources/MaterialResource.h b/Source/Core/VideoCommon/Resources/MaterialResource.h index 4842f000ea49..310a99961eb0 100644 --- a/Source/Core/VideoCommon/Resources/MaterialResource.h +++ b/Source/Core/VideoCommon/Resources/MaterialResource.h @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -27,6 +28,7 @@ namespace VideoCommon class MaterialResource final : public Resource { public: + explicit MaterialResource(Resource::ResourceContext resource_context); MaterialResource(Resource::ResourceContext resource_context, const GXPipelineUid& pipeline_uid); struct TextureLikeReference @@ -93,7 +95,7 @@ class MaterialResource final : public Resource // Note: asset cache owns the asset, we access as a reference MaterialAsset* m_material_asset = nullptr; - GXPipelineUid m_uid; + std::optional m_uid; std::unique_ptr m_uid_vertex_format_copy; }; } // namespace VideoCommon diff --git a/Source/Core/VideoCommon/Resources/ShaderResource.cpp b/Source/Core/VideoCommon/Resources/ShaderResource.cpp index 47600f2c6abd..6b3b4e0a68d3 100644 --- a/Source/Core/VideoCommon/Resources/ShaderResource.cpp +++ b/Source/Core/VideoCommon/Resources/ShaderResource.cpp @@ -10,6 +10,7 @@ #include "VideoCommon/AbstractGfx.h" #include "VideoCommon/Assets/CustomAssetCache.h" #include "VideoCommon/AsyncShaderCompiler.h" +#include "VideoCommon/FramebufferShaderGen.h" #include "VideoCommon/GeometryShaderGen.h" #include "VideoCommon/PipelineUtils.h" #include "VideoCommon/PixelShaderGen.h" @@ -20,20 +21,223 @@ namespace VideoCommon { namespace { -std::unique_ptr -CompileGeometryShader(const GeometryShaderUid& uid, APIType api_type, ShaderHostConfig host_config) +// TODO: the uniform buffer is combined due to the utility path only having a single +// set of constants, this isn't ideal (both for the end user, where it's more readable +// to see 'custom_uniforms' before variables and from Dolphin because the +// standard uniforms have to be packed with the custom ones +void GeneratePostProcessUniformOutput(ShaderCode& shader_source, std::string_view block_name, + std::string_view uniforms) +{ + shader_source.Write("UBO_BINDING(std140, 1) uniform {} {{\n", block_name); + shader_source.Write("\tvec4 source_resolution;\n"); + shader_source.Write("\tvec4 target_resolution;\n"); + shader_source.Write("\tvec4 window_resolution;\n"); + shader_source.Write("\tvec4 source_region;\n"); + shader_source.Write("\tint source_layer;\n"); + shader_source.Write("\tint source_layer_pad1;\n"); + shader_source.Write("\tint source_layer_pad2;\n"); + shader_source.Write("\tint source_layer_pad3;\n"); + shader_source.Write("\tuint time;\n"); + shader_source.Write("\tuint time_pad1;\n"); + shader_source.Write("\tuint time_pad2;\n"); + shader_source.Write("\tuint time_pad3;\n"); + shader_source.Write("\tint graphics_api;\n"); + shader_source.Write("\tint graphics_api_pad1;\n"); + shader_source.Write("\tint graphics_api_pad2;\n"); + shader_source.Write("\tint graphics_api_pad3;\n"); + shader_source.Write("\tuint efb_scale;\n"); + shader_source.Write("\tuint efb_scale_pad1;\n"); + shader_source.Write("\tuint efb_scale_pad2;\n"); + shader_source.Write("\tuint efb_scale_pad3;\n"); + if (!uniforms.empty()) + { + shader_source.Write("{}", uniforms); + } + shader_source.Write("}};\n"); +} + +// TODO: move this to a more standard post processing file +// once post processing has been cleaned up +void GeneratePostProcessingVertexShader(ShaderCode& shader_source, + const CustomVertexContents& custom_contents) +{ + // Note: if blocks are the same, they need to match for the OpenGL backend + GeneratePostProcessUniformOutput(shader_source, "PSBlock", custom_contents.uniforms); + + // Define some defines that are shared with custom draw shaders, + // so that a common shader code could possibly be used in both + shader_source.Write("#define HAS_COLOR_0 0\n"); + shader_source.Write("#define HAS_COLOR_1 0\n"); + shader_source.Write("#define HAS_NORMAL 0\n"); + shader_source.Write("#define HAS_BINORMAL 0\n"); + shader_source.Write("#define HAS_TANGENT 0\n"); + shader_source.Write("#define HAS_TEXTURE_COORD_0 1\n"); + for (u32 i = 1; i < 8; i++) + { + shader_source.Write("#define HAS_TEXTURE_COORD_{} 0\n", i); + } + + // Write the common structs, might want to consider + // moving these to another location? + shader_source.Write("struct DolphinVertexInput\n"); + shader_source.Write("{{\n"); + shader_source.Write("\tvec4 position;\n"); + shader_source.Write("\tvec3 texture_coord_0;\n"); + shader_source.Write("}};\n\n"); + + shader_source.Write("struct DolphinVertexOutput\n"); + shader_source.Write("{{\n"); + shader_source.Write("\tvec4 position;\n"); + shader_source.Write("\tvec3 texture_coord_0;\n"); + shader_source.Write("}};\n\n"); + + constexpr std::string_view emulated_vertex_definition = + "void dolphin_process_emulated_vertex(in DolphinVertexInput vertex_input, out " + "DolphinVertexOutput vertex_output)"; + shader_source.Write("{}\n", emulated_vertex_definition); + shader_source.Write("{{\n"); + shader_source.Write("\tvertex_output.position = vertex_input.position;\n"); + shader_source.Write("\tvertex_output.texture_coord_0 = vertex_input.texture_coord_0;\n"); + shader_source.Write("}}\n"); + + if (custom_contents.shader.empty()) + { + shader_source.Write( + "void process_vertex(in DolphinVertexInput vertex_input, out DolphinVertexOutput " + "vertex_output)\n"); + shader_source.Write("{{\n"); + + shader_source.Write("\tdolphin_process_emulated_vertex(vertex_input, vertex_output);\n"); + + shader_source.Write("}}\n"); + } + else + { + shader_source.Write("{}\n", custom_contents.shader); + } + + if (g_backend_info.bSupportsGeometryShaders) + { + shader_source.Write("VARYING_LOCATION(0) out VertexData {{\n"); + shader_source.Write("\tvec3 v_tex0;\n"); + shader_source.Write("}};\n"); + } + else + { + shader_source.Write("VARYING_LOCATION(0) out vec3 v_tex0;\n"); + } + + shader_source.Write("void main()\n"); + shader_source.Write("{{\n"); + shader_source.Write("\tDolphinVertexInput vertex_input;\n"); + shader_source.Write("\tvec3 vert = vec3(float((gl_VertexID << 1) & 2), " + "float(gl_VertexID & 2), 0.0f);\n"); + shader_source.Write("\tvertex_input.position = vec4(vert.xy * " + "float2(2.0f, -2.0f) + float2(-1.0f, 1.0f), 0.0f, 1.0f);\n"); + shader_source.Write("\tvertex_input.texture_coord_0 = vec3(source_region.xy + " + "(source_region.zw * vert.xy), 0.0f);\n"); + shader_source.Write("\tDolphinVertexOutput vertex_output;\n"); + shader_source.Write("\tprocess_vertex(vertex_input, vertex_output);\n"); + shader_source.Write("\tgl_Position = vertex_output.position;\n"); + shader_source.Write("\tv_tex0 = vertex_output.texture_coord_0;\n"); + + // NDC space is flipped in Vulkan + if (g_backend_info.api_type == APIType::Vulkan) + { + shader_source.Write("\tgl_Position.y = -gl_Position.y;\n"); + } + + shader_source.Write("}}\n"); +} + +void GeneratePostProcessingPixelShader(ShaderCode& shader_source, + const CustomPixelContents& custom_contents) +{ + GeneratePostProcessUniformOutput(shader_source, "PSBlock", custom_contents.uniforms); + + shader_source.Write("SAMPLER_BINDING(0) uniform sampler2DArray samp0;\n"); + + if (g_backend_info.bSupportsGeometryShaders) + { + shader_source.Write("VARYING_LOCATION(0) in VertexData {{\n"); + shader_source.Write("\tvec3 v_tex0;\n"); + shader_source.Write("}};\n"); + } + else + { + shader_source.Write("VARYING_LOCATION(0) in float3 v_tex0;\n"); + } + + shader_source.Write("FRAGMENT_OUTPUT_LOCATION(0) out vec4 ocol0;\n"); + + shader_source.Write("struct DolphinFragmentInput\n"); + shader_source.Write("{{\n"); + for (u32 i = 0; i < 1; i++) + { + shader_source.Write("\tvec3 tex{};\n", i); + } + shader_source.Write("\n"); + + shader_source.Write("}};\n\n"); + + shader_source.Write("struct DolphinFragmentOutput\n"); + shader_source.Write("{{\n"); + shader_source.Write("\tvec4 main;\n"); + shader_source.Write("}};\n\n"); + + constexpr std::string_view emulated_fragment_definition = + "void dolphin_process_emulated_fragment(in DolphinFragmentInput frag_input, out " + "DolphinFragmentOutput frag_output)"; + shader_source.Write("{}\n", emulated_fragment_definition); + shader_source.Write("{{\n"); + shader_source.Write("\tfrag_output.main = texture(samp0, frag_input.tex0);\n"); + shader_source.Write("}}\n"); + + if (custom_contents.shader.empty()) + { + shader_source.Write( + "void process_fragment(in DolphinFragmentInput frag_input, out DolphinFragmentOutput " + "frag_output)\n"); + shader_source.Write("{{\n"); + + shader_source.Write("\tdolphin_process_emulated_fragment(frag_input, frag_output);\n"); + + shader_source.Write("}}\n"); + } + else + { + shader_source.Write("{}\n", custom_contents.shader); + } + + shader_source.Write("void main()\n"); + shader_source.Write("{{\n"); + shader_source.Write("\tDolphinFragmentInput frag_input;\n"); + shader_source.Write("\tfrag_input.tex0 = v_tex0;\n"); + shader_source.Write("\tDolphinFragmentOutput frag_output;\n"); + shader_source.Write("\tprocess_fragment(frag_input, frag_output);\n"); + shader_source.Write("\tocol0 = frag_output.main;\n"); + shader_source.Write("}}\n"); +} + +std::unique_ptr CompileGeometryShader(GeometryShaderUid* uid, APIType api_type, + ShaderHostConfig host_config) { + if (!uid) + { + return g_gfx->CreateShaderFromSource( + ShaderStage::Geometry, FramebufferShaderGen::GeneratePassthroughGeometryShader(1, 0), + nullptr, "Custom Post Processing Geometry Shader"); + } + const ShaderCode source_code = - GenerateGeometryShaderCode(api_type, host_config, uid.GetUidData()); + GenerateGeometryShaderCode(api_type, host_config, uid->GetUidData()); return g_gfx->CreateShaderFromSource(ShaderStage::Geometry, source_code.GetBuffer(), nullptr, - fmt::format("Geometry shader: {}", *uid.GetUidData())); + fmt::format("Geometry shader: {}", *uid->GetUidData())); } -std::unique_ptr CompilePixelShader(const PixelShaderUid& uid, - std::string_view preprocessor_settings, - APIType api_type, - const ShaderHostConfig& host_config, - RasterSurfaceShaderData* shader_data) +std::unique_ptr +CompilePixelShader(PixelShaderUid* uid, std::string_view preprocessor_settings, APIType api_type, + const ShaderHostConfig& host_config, RasterSurfaceShaderData* shader_data) { ShaderCode shader_code; @@ -89,19 +293,25 @@ std::unique_ptr CompilePixelShader(const PixelShaderUid& uid, // Compile the shader CustomPixelContents contents{.shader = shader_code.GetBuffer(), .uniforms = uniform_code.GetBuffer()}; - const ShaderCode source_code = - GeneratePixelShaderCode(api_type, host_config, uid.GetUidData(), contents); + + ShaderCode source_code; + if (uid) + { + source_code = GeneratePixelShaderCode(api_type, host_config, uid->GetUidData(), contents); + } + else + { + GeneratePostProcessingPixelShader(source_code, contents); + } ShaderIncluder* shader_includer = shader_data->shader_includer ? &*shader_data->shader_includer : nullptr; return g_gfx->CreateShaderFromSource(ShaderStage::Pixel, source_code.GetBuffer(), shader_includer, "Custom Pixel Shader"); } -std::unique_ptr CompileVertexShader(const VertexShaderUid& uid, - std::string_view preprocessor_settings, - APIType api_type, - const ShaderHostConfig& host_config, - const RasterSurfaceShaderData& shader_data) +std::unique_ptr +CompileVertexShader(VertexShaderUid* uid, std::string_view preprocessor_settings, APIType api_type, + const ShaderHostConfig& host_config, const RasterSurfaceShaderData& shader_data) { ShaderCode shader_code; @@ -157,18 +367,26 @@ std::unique_ptr CompileVertexShader(const VertexShaderUid& uid, // Compile the shader CustomVertexContents contents{.shader = shader_code.GetBuffer(), .uniforms = uniform_code.GetBuffer()}; - const ShaderCode source_code = - GenerateVertexShaderCode(api_type, host_config, uid.GetUidData(), contents); + + ShaderCode source_code; + if (uid) + { + source_code = GenerateVertexShaderCode(api_type, host_config, uid->GetUidData(), contents); + } + else + { + GeneratePostProcessingVertexShader(source_code, contents); + } return g_gfx->CreateShaderFromSource(ShaderStage::Vertex, source_code.GetBuffer(), nullptr, "Custom Vertex Shader"); } } // namespace ShaderResource::ShaderResource(Resource::ResourceContext resource_context, - const GXPipelineUid& pipeline_uid, + std::optional pipeline_uid, const std::string& preprocessor_setting, const ShaderHostConfig& shader_host_config) : Resource(std::move(resource_context)), m_shader_host_config{.bits = shader_host_config.bits}, - m_uid(pipeline_uid), m_preprocessor_settings(preprocessor_setting) + m_uid(std::move(pipeline_uid)), m_preprocessor_settings(preprocessor_setting) { m_shader_asset = m_resource_context.asset_cache->CreateAsset( m_resource_context.primary_asset_id, m_resource_context.asset_library, this); @@ -257,24 +475,46 @@ Resource::TaskComplete ShaderResource::ProcessData() bool Compile() override { const ShaderHostConfig shader_host_config{.bits = m_shader_bits}; - auto actual_uid = ApplyDriverBugs(*m_uid); - - ClearUnusedPixelShaderUidBits(g_backend_info.api_type, shader_host_config, - &actual_uid.ps_uid); - m_resource_data->m_needs_geometry_shader = shader_host_config.backend_geometry_shaders && - !actual_uid.gs_uid.GetUidData()->IsPassthrough(); - - if (m_resource_data->m_needs_geometry_shader) + if (m_uid) + { + // Draw based shader + auto actual_uid = ApplyDriverBugs(*m_uid); + + ClearUnusedPixelShaderUidBits(g_backend_info.api_type, shader_host_config, + &actual_uid.ps_uid); + m_resource_data->m_needs_geometry_shader = shader_host_config.backend_geometry_shaders && + !actual_uid.gs_uid.GetUidData()->IsPassthrough(); + + if (m_resource_data->m_needs_geometry_shader) + { + m_resource_data->m_geometry_shader = CompileGeometryShader( + &actual_uid.gs_uid, g_backend_info.api_type, shader_host_config); + } + m_resource_data->m_pixel_shader = + CompilePixelShader(&actual_uid.ps_uid, m_preprocessor_settings, g_backend_info.api_type, + shader_host_config, m_resource_data->m_shader_data.get()); + m_resource_data->m_vertex_shader = CompileVertexShader( + &actual_uid.vs_uid, m_preprocessor_settings, g_backend_info.api_type, + shader_host_config, *m_resource_data->m_shader_data); + } + else { - m_resource_data->m_geometry_shader = - CompileGeometryShader(actual_uid.gs_uid, g_backend_info.api_type, shader_host_config); + // Post processing based shader + + m_resource_data->m_needs_geometry_shader = + shader_host_config.backend_geometry_shaders && shader_host_config.stereo; + if (m_resource_data->m_needs_geometry_shader) + { + m_resource_data->m_geometry_shader = + CompileGeometryShader(nullptr, g_backend_info.api_type, shader_host_config); + } + m_resource_data->m_pixel_shader = + CompilePixelShader(nullptr, m_preprocessor_settings, g_backend_info.api_type, + shader_host_config, m_resource_data->m_shader_data.get()); + m_resource_data->m_vertex_shader = + CompileVertexShader(nullptr, m_preprocessor_settings, g_backend_info.api_type, + shader_host_config, *m_resource_data->m_shader_data); } - m_resource_data->m_pixel_shader = - CompilePixelShader(actual_uid.ps_uid, m_preprocessor_settings, g_backend_info.api_type, - shader_host_config, m_resource_data->m_shader_data.get()); - m_resource_data->m_vertex_shader = - CompileVertexShader(actual_uid.vs_uid, m_preprocessor_settings, g_backend_info.api_type, - shader_host_config, *m_resource_data->m_shader_data); m_resource_data->m_processing_finished = true; return true; } @@ -291,7 +531,7 @@ Resource::TaskComplete ShaderResource::ProcessData() { std::string_view preprocessor_settings = m_preprocessor_settings; auto wi = m_resource_context.shader_compiler->CreateWorkItem( - m_load_data, &m_uid, m_shader_host_config.bits, preprocessor_settings); + m_load_data, m_uid ? &*m_uid : nullptr, m_shader_host_config.bits, preprocessor_settings); // We don't need priority, that is already handled by the resource system m_resource_context.shader_compiler->QueueWorkItem(std::move(wi), 0); diff --git a/Source/Core/VideoCommon/Resources/ShaderResource.h b/Source/Core/VideoCommon/Resources/ShaderResource.h index 0f91cd3714a7..c72f03be2bfb 100644 --- a/Source/Core/VideoCommon/Resources/ShaderResource.h +++ b/Source/Core/VideoCommon/Resources/ShaderResource.h @@ -4,6 +4,7 @@ #pragma once #include +#include #include "VideoCommon/Resources/Resource.h" @@ -16,7 +17,8 @@ namespace VideoCommon class ShaderResource final : public Resource { public: - ShaderResource(Resource::ResourceContext resource_context, const GXPipelineUid& pipeline_uid, + ShaderResource(Resource::ResourceContext resource_context, + std::optional pipeline_uid, const std::string& preprocessor_settings, const ShaderHostConfig& shader_host_config); @@ -61,7 +63,7 @@ class ShaderResource final : public Resource bool m_processing_load_data = false; ShaderHostConfig m_shader_host_config; - GXPipelineUid m_uid; + std::optional m_uid; std::string m_preprocessor_settings; }; } // namespace VideoCommon diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 6ae8b4f96f76..59c9d7fc8430 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -2253,16 +2253,16 @@ void TextureCacheBase::CopyRenderTargetToTexture( { for (const auto& action : g_graphics_mod_manager->GetXFBActions(info)) { - action->OnXFB(); + action->BeforeXFB(); } } else { bool skip = false; - GraphicsModActionData::EFB efb{tex_w, tex_h, &skip, &scaled_tex_w, &scaled_tex_h}; + GraphicsModActionData::PreEFB efb{tex_w, tex_h, &skip, &scaled_tex_w, &scaled_tex_h}; for (const auto& action : g_graphics_mod_manager->GetEFBActions(info)) { - action->OnEFB(&efb); + action->BeforeEFB(&efb); } if (skip == true) { @@ -2324,6 +2324,27 @@ void TextureCacheBase::CopyRenderTargetToTexture( isIntensity, gamma, clamp_top, clamp_bottom, GetVRAMCopyFilterCoefficients(filter_coefficients)); + if (g_ActiveConfig.bGraphicMods) + { + FBInfo info; + info.m_width = tex_w; + info.m_height = tex_h; + info.m_texture_format = baseFormat; + if (!is_xfb_copy) + { + VideoCommon::MaterialResource* material = nullptr; + GraphicsModActionData::PostEFB efb{&material}; + for (const auto& action : g_graphics_mod_manager->GetEFBActions(info)) + { + action->AfterEFB(&efb); + if (material) + { + ApplyMaterialToCacheEntry(*material, entry.get()); + } + } + } + } + if (is_xfb_copy && (g_ActiveConfig.bDumpXFBTarget || g_ActiveConfig.bGraphicMods)) { const std::string id = fmt::format("{}x{}", tex_w, tex_h); @@ -3030,6 +3051,110 @@ bool TextureCacheBase::DecodeTextureOnGPU(RcTcacheEntry& entry, u32 dst_level, c return true; } +void TextureCacheBase::ApplyMaterialToCacheEntry(const VideoCommon::MaterialResource& material, + TCacheEntry* entry) +{ + const auto material_data = material.GetData(); + if (!material_data) [[unlikely]] + return; + + // Make a copy, we can't write to our texture and use its framebuffer + // at the same time + auto new_entry = AllocateCacheEntry(entry->texture->GetConfig()); + new_entry->SetGeneralParameters(entry->addr, entry->size_in_bytes, entry->format, + entry->should_force_safe_hashing); + new_entry->SetDimensions(entry->native_width, entry->native_height, 1); + new_entry->SetEfbCopy(entry->memory_stride); + new_entry->may_have_overlapping_textures = false; + new_entry->frameCount = FRAMECOUNT_INVALID; + + g_gfx->BeginUtilityDrawing(); + entry->texture->FinishedRendering(); + + const auto custom_uniforms = material_data->GetUniforms(); + + // Set up uniforms. + // TODO: this struct should be shared with post processing + struct Uniforms + { + std::array source_resolution; + std::array target_resolution; + std::array window_resolution; + std::array source_rectangle; + s32 source_layer; + s32 source_layer_pad[3]; + u32 time; + u32 time_pad[3]; + s32 graphics_api; + s32 graphics_api_pad[3]; + u32 efb_scale; + u32 efb_scale_pad[3]; + } uniforms; + + const float rcp_src_width = 1.0f / entry->texture->GetWidth(); + const float rcp_src_height = 1.0f / entry->texture->GetHeight(); + + uniforms.source_resolution = {static_cast(entry->texture->GetWidth()), + static_cast(entry->texture->GetHeight()), rcp_src_width, + rcp_src_height}; + + // The target resolution is the same here, since we're + // injecting into the texture + uniforms.target_resolution = uniforms.source_resolution; + + const auto present_rect = g_presenter->GetTargetRectangle(); + uniforms.window_resolution = {static_cast(present_rect.GetWidth()), + static_cast(present_rect.GetHeight()), + 1.0f / static_cast(present_rect.GetWidth()), + 1.0f / static_cast(present_rect.GetHeight())}; + + uniforms.source_rectangle = {0, 0, 1, 1}; + uniforms.source_layer = 0; + uniforms.time = 0; + uniforms.graphics_api = static_cast(g_backend_info.api_type); + uniforms.efb_scale = g_framebuffer_manager->GetEFBScale(); + + Common::UniqueBuffer uniform_buffer(custom_uniforms.size() + sizeof(uniforms)); + std::memcpy(uniform_buffer.data(), &uniforms, sizeof(uniforms)); + std::memcpy(uniform_buffer.data() + sizeof(uniforms), custom_uniforms.data(), + custom_uniforms.size()); + g_vertex_manager->UploadUtilityUniforms(uniform_buffer.data(), + static_cast(uniform_buffer.size())); + + // Set framebuffer and viewport based on new entry + g_gfx->SetAndDiscardFramebuffer(new_entry->framebuffer.get()); + g_gfx->SetViewportAndScissor(new_entry->framebuffer->GetRect()); + g_gfx->SetPipeline(material_data->GetPipeline()); + + g_gfx->SetTexture(0, entry->texture.get()); + g_gfx->SetSamplerState(0, RenderState::GetPointSamplerState()); + + for (const auto texture : material_data->GetTextures()) + { + g_gfx->SetTexture(texture.sampler_index, texture.texture); + g_gfx->SetSamplerState(texture.sampler_index, texture.sampler); + } + + g_gfx->Draw(0, 3); + g_gfx->EndUtilityDrawing(); + + // Finish rendering new entry + new_entry->texture->FinishedRendering(); + + // Swap new entry and existing entry + std::swap(entry->texture, new_entry->texture); + std::swap(entry->framebuffer, new_entry->framebuffer); + + // Return old entry to pool for use in another pass + // or future functionality + ReleaseToPool(new_entry.get()); + + if (const auto next_material = material_data->GetNextMaterial(); next_material) + { + ApplyMaterialToCacheEntry(*next_material, entry); + } +} + u32 TCacheEntry::BytesPerRow() const { // RGBA takes two cache lines per block; all others take one diff --git a/Source/Core/VideoCommon/TextureCacheBase.h b/Source/Core/VideoCommon/TextureCacheBase.h index 9a95400679d1..f6db329e1438 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.h +++ b/Source/Core/VideoCommon/TextureCacheBase.h @@ -41,6 +41,7 @@ namespace VideoCommon { class CustomTextureData; class GameTextureAsset; +class MaterialResource; } // namespace VideoCommon constexpr std::string_view EFB_DUMP_PREFIX = "efb1"; @@ -407,6 +408,8 @@ class TextureCacheBase void DoSaveState(PointerWrap& p); void DoLoadState(PointerWrap& p); + void ApplyMaterialToCacheEntry(const VideoCommon::MaterialResource& material, TCacheEntry* entry); + // m_textures_by_address is the authoritive version of what's actually "in" the texture cache // but it's possible for invalidated TCache entries to live on elsewhere TexAddrCache m_textures_by_address;