vk_shader_gen_spv: Implement shadow plane sampling
This commit is contained in:
2
externals/sirit
vendored
2
externals/sirit
vendored
Submodule externals/sirit updated: 297d820eeb...f0b6bbe55b
@ -3,6 +3,7 @@
|
|||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include "common/microprofile.h"
|
#include "common/microprofile.h"
|
||||||
|
#include "core/core.h"
|
||||||
#include "video_core/regs.h"
|
#include "video_core/regs.h"
|
||||||
#include "video_core/renderer_vulkan/vk_shader_gen_spv.h"
|
#include "video_core/renderer_vulkan/vk_shader_gen_spv.h"
|
||||||
#include "video_core/shader/shader_uniforms.h"
|
#include "video_core/shader/shader_uniforms.h"
|
||||||
@ -56,6 +57,15 @@ void FragmentModule::Generate() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config.state.fog_mode == TexturingRegs::FogMode::Gas) {
|
||||||
|
Core::System::GetInstance().TelemetrySession().AddField(
|
||||||
|
Common::Telemetry::FieldType::Session, "VideoCore_Pica_UseGasMode", true);
|
||||||
|
LOG_CRITICAL(Render_Vulkan, "Unimplemented gas mode");
|
||||||
|
OpKill();
|
||||||
|
OpFunctionEnd();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// After perspective divide, OpenGL transform z_over_w from [-1, 1] to [near, far]. Here we use
|
// After perspective divide, OpenGL transform z_over_w from [-1, 1] to [near, far]. Here we use
|
||||||
// default near = 0 and far = 1, and undo the transformation to get the original z_over_w, then
|
// default near = 0 and far = 1, and undo the transformation to get the original z_over_w, then
|
||||||
// do our own transformation according to PICA specification.
|
// do our own transformation according to PICA specification.
|
||||||
@ -575,9 +585,10 @@ Id FragmentModule::SampleTexture(u32 texture_unit) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const auto Sample = [this](Id tex_id, Id tex_sampler_id, bool projection) {
|
const auto Sample = [this](Id tex_id, Id tex_sampler_id, bool projection) {
|
||||||
const Id tex{OpLoad(image2d_id, tex_id)};
|
const Id image_type = tex_id.value == tex_cube_id.value ? image_cube_id : image2d_id;
|
||||||
|
const Id tex{OpLoad(image_type, tex_id)};
|
||||||
const Id tex_sampler{OpLoad(sampler_id, tex_sampler_id)};
|
const Id tex_sampler{OpLoad(sampler_id, tex_sampler_id)};
|
||||||
const Id sampled_image{OpSampledImage(TypeSampledImage(image2d_id), tex, tex_sampler)};
|
const Id sampled_image{OpSampledImage(TypeSampledImage(image_type), tex, tex_sampler)};
|
||||||
const Id texcoord0{OpLoad(vec_ids.Get(2), texcoord0_id)};
|
const Id texcoord0{OpLoad(vec_ids.Get(2), texcoord0_id)};
|
||||||
const Id texcoord0_w{OpLoad(f32_id, texcoord0_w_id)};
|
const Id texcoord0_w{OpLoad(f32_id, texcoord0_w_id)};
|
||||||
const Id coord{OpCompositeConstruct(vec_ids.Get(3), OpCompositeExtract(f32_id, texcoord0, 0),
|
const Id coord{OpCompositeConstruct(vec_ids.Get(3), OpCompositeExtract(f32_id, texcoord0, 0),
|
||||||
@ -600,8 +611,8 @@ Id FragmentModule::SampleTexture(u32 texture_unit) {
|
|||||||
return Sample(tex0_id, tex0_sampler_id, true);
|
return Sample(tex0_id, tex0_sampler_id, true);
|
||||||
case Pica::TexturingRegs::TextureConfig::TextureCube:
|
case Pica::TexturingRegs::TextureConfig::TextureCube:
|
||||||
return Sample(tex_cube_id, tex_cube_sampler_id, false);
|
return Sample(tex_cube_id, tex_cube_sampler_id, false);
|
||||||
//case Pica::TexturingRegs::TextureConfig::Shadow2D:
|
case Pica::TexturingRegs::TextureConfig::Shadow2D:
|
||||||
//return "shadowTexture(texcoord0, texcoord0_w)";
|
return SampleShadow();
|
||||||
//case Pica::TexturingRegs::TextureConfig::ShadowCube:
|
//case Pica::TexturingRegs::TextureConfig::ShadowCube:
|
||||||
//return "shadowTextureCube(texcoord0, texcoord0_w)";
|
//return "shadowTextureCube(texcoord0, texcoord0_w)";
|
||||||
case Pica::TexturingRegs::TextureConfig::Disabled:
|
case Pica::TexturingRegs::TextureConfig::Disabled:
|
||||||
@ -631,6 +642,65 @@ Id FragmentModule::SampleTexture(u32 texture_unit) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Id FragmentModule::CompareShadow(Id pixel, Id z) {
|
||||||
|
const Id pixel_d24{OpShiftRightLogical(u32_id, pixel, ConstS32(8))};
|
||||||
|
const Id pixel_s8{OpConvertUToF(f32_id, OpBitwiseAnd(u32_id, pixel, ConstU32(255u)))};
|
||||||
|
const Id s8_mul{OpFMul(f32_id, pixel_s8, ConstF32(1.f / 255.f))};
|
||||||
|
const Id d24_leq_z{OpULessThanEqual(bool_id, pixel_d24, z)};
|
||||||
|
return OpSelect(f32_id, d24_leq_z, ConstF32(0.f), s8_mul);
|
||||||
|
}
|
||||||
|
|
||||||
|
Id FragmentModule::SampleShadow() {
|
||||||
|
dump_shader = true;
|
||||||
|
const Id texcoord0{OpLoad(vec_ids.Get(2), texcoord0_id)};
|
||||||
|
const Id texcoord0_w{OpLoad(f32_id, texcoord0_w_id)};
|
||||||
|
const Id abs_min_w{OpFMul(f32_id, OpFMin(f32_id, OpFAbs(f32_id, texcoord0_w),
|
||||||
|
ConstF32(1.f)), ConstF32(16777215.f))};
|
||||||
|
const Id shadow_texture_bias{GetShaderDataMember(i32_id, ConstS32(17))};
|
||||||
|
const Id z_i32{OpSMax(i32_id, ConstS32(0), OpISub(i32_id, OpConvertFToS(i32_id, abs_min_w), shadow_texture_bias))};
|
||||||
|
const Id z{OpBitcast(u32_id, z_i32)};
|
||||||
|
const Id shadow_texture_px{OpLoad(image_r32_id, shadow_texture_px_id)};
|
||||||
|
const Id px_size{OpImageQuerySize(ivec_ids.Get(2), shadow_texture_px)};
|
||||||
|
const Id coord{OpFma(vec_ids.Get(2), OpConvertSToF(vec_ids.Get(2), px_size), texcoord0, ConstF32(-0.5f, -0.5f))};
|
||||||
|
const Id coord_floor{OpFloor(vec_ids.Get(2), coord)};
|
||||||
|
const Id f{OpFSub(vec_ids.Get(2), coord_floor, coord)};
|
||||||
|
const Id i{OpConvertFToS(ivec_ids.Get(2), coord_floor)};
|
||||||
|
|
||||||
|
const auto SampleShadow2D = [&](Id uv) -> Id {
|
||||||
|
const Id true_label{OpLabel()};
|
||||||
|
const Id false_label{OpLabel()};
|
||||||
|
const Id end_label{OpLabel()};
|
||||||
|
const Id uv_le_zero{OpSLessThan(bvec_ids.Get(2), uv, ConstS32(0, 0))};
|
||||||
|
const Id uv_geq_size{OpSGreaterThanEqual(bvec_ids.Get(2), uv, px_size)};
|
||||||
|
const Id cond{OpAny(bool_id, OpCompositeConstruct(bvec_ids.Get(4), uv_le_zero, uv_geq_size))};
|
||||||
|
OpSelectionMerge(end_label, spv::SelectionControlMask::MaskNone);
|
||||||
|
OpBranchConditional(cond, true_label, false_label);
|
||||||
|
AddLabel(true_label);
|
||||||
|
OpBranch(end_label);
|
||||||
|
AddLabel(false_label);
|
||||||
|
const Id px_texel{OpImageRead(uvec_ids.Get(4), shadow_texture_px, uv)};
|
||||||
|
const Id px_texel_x{OpCompositeExtract(u32_id, px_texel, 0)};
|
||||||
|
const Id result{CompareShadow(px_texel_x, z)};
|
||||||
|
OpBranch(end_label);
|
||||||
|
AddLabel(end_label);
|
||||||
|
return OpPhi(f32_id, ConstF32(1.f), true_label, result, false_label);
|
||||||
|
};
|
||||||
|
|
||||||
|
const Id s_xy{OpCompositeConstruct(vec_ids.Get(2),
|
||||||
|
SampleShadow2D(i),
|
||||||
|
SampleShadow2D(OpIAdd(ivec_ids.Get(2), i, ConstS32(1, 0))))};
|
||||||
|
const Id s_zw{OpCompositeConstruct(vec_ids.Get(2),
|
||||||
|
SampleShadow2D(OpIAdd(ivec_ids.Get(2), i, ConstS32(0, 1))),
|
||||||
|
SampleShadow2D(OpIAdd(ivec_ids.Get(2), i, ConstS32(1, 1))))};
|
||||||
|
const Id f_yy{OpVectorShuffle(vec_ids.Get(2), f, f, 1, 1)};
|
||||||
|
const Id t{OpFMix(vec_ids.Get(2), s_xy, s_zw, f_yy)};
|
||||||
|
const Id t_x{OpCompositeExtract(f32_id, t, 0)};
|
||||||
|
const Id t_y{OpCompositeExtract(f32_id, t, 1)};
|
||||||
|
const Id a_x{OpCompositeExtract(f32_id, f, 0)};
|
||||||
|
const Id val{OpFMix(f32_id, t_x, t_y, a_x)};
|
||||||
|
return OpCompositeConstruct(vec_ids.Get(4), val, val, val, val);
|
||||||
|
}
|
||||||
|
|
||||||
Id FragmentModule::Byteround(Id variable_id, u32 size) {
|
Id FragmentModule::Byteround(Id variable_id, u32 size) {
|
||||||
if (size > 1) {
|
if (size > 1) {
|
||||||
const Id scaled_vec_id{OpVectorTimesScalar(vec_ids.Get(size), variable_id, ConstF32(255.f))};
|
const Id scaled_vec_id{OpVectorTimesScalar(vec_ids.Get(size), variable_id, ConstF32(255.f))};
|
||||||
@ -859,6 +929,7 @@ void FragmentModule::DefineArithmeticTypes() {
|
|||||||
vec_ids.ids[i] = Name(TypeVector(f32_id, size), fmt::format("vec{}_id", size));
|
vec_ids.ids[i] = Name(TypeVector(f32_id, size), fmt::format("vec{}_id", size));
|
||||||
ivec_ids.ids[i] = Name(TypeVector(i32_id, size), fmt::format("ivec{}_id", size));
|
ivec_ids.ids[i] = Name(TypeVector(i32_id, size), fmt::format("ivec{}_id", size));
|
||||||
uvec_ids.ids[i] = Name(TypeVector(u32_id, size), fmt::format("uvec{}_id", size));
|
uvec_ids.ids[i] = Name(TypeVector(u32_id, size), fmt::format("uvec{}_id", size));
|
||||||
|
bvec_ids.ids[i] = Name(TypeVector(bool_id, size), fmt::format("bvec{}_id", size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -928,6 +999,7 @@ void FragmentModule::DefineInterface() {
|
|||||||
image_buffer_id = TypeImage(f32_id, spv::Dim::Buffer, 0, 0, 0, 1, spv::ImageFormat::Unknown);
|
image_buffer_id = TypeImage(f32_id, spv::Dim::Buffer, 0, 0, 0, 1, spv::ImageFormat::Unknown);
|
||||||
image2d_id = TypeImage(f32_id, spv::Dim::Dim2D, 0, 0, 0, 1, spv::ImageFormat::Unknown);
|
image2d_id = TypeImage(f32_id, spv::Dim::Dim2D, 0, 0, 0, 1, spv::ImageFormat::Unknown);
|
||||||
image_cube_id = TypeImage(f32_id, spv::Dim::Cube, 0, 0, 0, 1, spv::ImageFormat::Unknown);
|
image_cube_id = TypeImage(f32_id, spv::Dim::Cube, 0, 0, 0, 1, spv::ImageFormat::Unknown);
|
||||||
|
image_r32_id = TypeImage(u32_id, spv::Dim::Dim2D, 0, 0, 0, 2, spv::ImageFormat::R32ui);
|
||||||
sampler_id = TypeSampler();
|
sampler_id = TypeSampler();
|
||||||
|
|
||||||
texture_buffer_lut_lf_id = DefineUniformConst(TypeSampledImage(image_buffer_id), 0, 2);
|
texture_buffer_lut_lf_id = DefineUniformConst(TypeSampledImage(image_buffer_id), 0, 2);
|
||||||
@ -941,6 +1013,7 @@ void FragmentModule::DefineInterface() {
|
|||||||
tex1_sampler_id = DefineUniformConst(sampler_id, 2, 1);
|
tex1_sampler_id = DefineUniformConst(sampler_id, 2, 1);
|
||||||
tex2_sampler_id = DefineUniformConst(sampler_id, 2, 2);
|
tex2_sampler_id = DefineUniformConst(sampler_id, 2, 2);
|
||||||
tex_cube_sampler_id = DefineUniformConst(sampler_id, 2, 3);
|
tex_cube_sampler_id = DefineUniformConst(sampler_id, 2, 3);
|
||||||
|
shadow_texture_px_id = DefineUniformConst(image_r32_id, 3, 0, true);
|
||||||
|
|
||||||
// Define built-ins
|
// Define built-ins
|
||||||
gl_frag_coord_id = DefineVar(vec_ids.Get(4), spv::StorageClass::Input);
|
gl_frag_coord_id = DefineVar(vec_ids.Get(4), spv::StorageClass::Input);
|
||||||
@ -949,6 +1022,8 @@ void FragmentModule::DefineInterface() {
|
|||||||
Decorate(gl_frag_depth_id, spv::Decoration::BuiltIn, spv::BuiltIn::FragDepth);
|
Decorate(gl_frag_depth_id, spv::Decoration::BuiltIn, spv::BuiltIn::FragDepth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int i = 0;
|
||||||
|
|
||||||
std::vector<u32> GenerateFragmentShaderSPV(const PicaFSConfig& config) {
|
std::vector<u32> GenerateFragmentShaderSPV(const PicaFSConfig& config) {
|
||||||
FragmentModule module{config};
|
FragmentModule module{config};
|
||||||
module.Generate();
|
module.Generate();
|
||||||
|
@ -48,6 +48,9 @@ public:
|
|||||||
/// Samples the current fragment texel from the provided texture unit
|
/// Samples the current fragment texel from the provided texture unit
|
||||||
[[nodiscard]] Id SampleTexture(u32 texture_unit);
|
[[nodiscard]] Id SampleTexture(u32 texture_unit);
|
||||||
|
|
||||||
|
/// Samples the current fragment texel from shadow plane
|
||||||
|
[[nodiscard]] Id SampleShadow();
|
||||||
|
|
||||||
/// Rounds the provided variable to the nearest 1/255th
|
/// Rounds the provided variable to the nearest 1/255th
|
||||||
[[nodiscard]] Id Byteround(Id variable_id, u32 size = 1);
|
[[nodiscard]] Id Byteround(Id variable_id, u32 size = 1);
|
||||||
|
|
||||||
@ -70,7 +73,9 @@ public:
|
|||||||
|
|
||||||
/// Writes the combiner function for the alpha component for the specified TEV stage operation
|
/// Writes the combiner function for the alpha component for the specified TEV stage operation
|
||||||
[[nodiscard]] Id AppendAlphaCombiner(Pica::TexturingRegs::TevStageConfig::Operation operation);
|
[[nodiscard]] Id AppendAlphaCombiner(Pica::TexturingRegs::TevStageConfig::Operation operation);
|
||||||
|
bool dump_shader{false};
|
||||||
|
|
||||||
|
private:
|
||||||
/// Loads the member specified from the shader_data uniform struct
|
/// Loads the member specified from the shader_data uniform struct
|
||||||
template <typename... Ids>
|
template <typename... Ids>
|
||||||
[[nodiscard]] Id GetShaderDataMember(Id type, Ids... ids) {
|
[[nodiscard]] Id GetShaderDataMember(Id type, Ids... ids) {
|
||||||
@ -99,10 +104,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Defines a uniform constant variable
|
/// Defines a uniform constant variable
|
||||||
[[nodiscard]] Id DefineUniformConst(Id type, u32 set, u32 binding) {
|
[[nodiscard]] Id DefineUniformConst(Id type, u32 set, u32 binding, bool readonly = false) {
|
||||||
const Id uniform_id{DefineVar(type, spv::StorageClass::UniformConstant)};
|
const Id uniform_id{DefineVar(type, spv::StorageClass::UniformConstant)};
|
||||||
Decorate(uniform_id, spv::Decoration::DescriptorSet, set);
|
Decorate(uniform_id, spv::Decoration::DescriptorSet, set);
|
||||||
Decorate(uniform_id, spv::Decoration::Binding, binding);
|
Decorate(uniform_id, spv::Decoration::Binding, binding);
|
||||||
|
if (readonly) {
|
||||||
|
Decorate(uniform_id, spv::Decoration::NonWritable);
|
||||||
|
}
|
||||||
return uniform_id;
|
return uniform_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +146,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the id of a float constant of value
|
/// Returns the id of a float constant of value
|
||||||
[[nodiscard]] Id ConstF32(float value) {
|
[[nodiscard]] Id ConstF32(f32 value) {
|
||||||
return Constant(f32_id, value);
|
return Constant(f32_id, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,11 +158,11 @@ public:
|
|||||||
return ConstantComposite(vec_ids.Get(size), constituents);
|
return ConstantComposite(vec_ids.Get(size), constituents);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
void DefineArithmeticTypes();
|
void DefineArithmeticTypes();
|
||||||
void DefineEntryPoint();
|
void DefineEntryPoint();
|
||||||
void DefineUniformStructs();
|
void DefineUniformStructs();
|
||||||
void DefineInterface();
|
void DefineInterface();
|
||||||
|
Id CompareShadow(Id pixel, Id z);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PicaFSConfig config;
|
PicaFSConfig config;
|
||||||
@ -167,10 +175,12 @@ private:
|
|||||||
VectorIds vec_ids{};
|
VectorIds vec_ids{};
|
||||||
VectorIds ivec_ids{};
|
VectorIds ivec_ids{};
|
||||||
VectorIds uvec_ids{};
|
VectorIds uvec_ids{};
|
||||||
|
VectorIds bvec_ids{};
|
||||||
|
|
||||||
Id image2d_id{};
|
Id image2d_id{};
|
||||||
Id image_cube_id{};
|
Id image_cube_id{};
|
||||||
Id image_buffer_id{};
|
Id image_buffer_id{};
|
||||||
|
Id image_r32_id{};
|
||||||
Id sampler_id{};
|
Id sampler_id{};
|
||||||
Id shader_data_id{};
|
Id shader_data_id{};
|
||||||
|
|
||||||
@ -197,6 +207,12 @@ private:
|
|||||||
Id texture_buffer_lut_lf_id{};
|
Id texture_buffer_lut_lf_id{};
|
||||||
Id texture_buffer_lut_rg_id{};
|
Id texture_buffer_lut_rg_id{};
|
||||||
Id texture_buffer_lut_rgba_id{};
|
Id texture_buffer_lut_rgba_id{};
|
||||||
|
Id shadow_texture_px_id{};
|
||||||
|
Id shadow_texture_nx_id{};
|
||||||
|
Id shadow_texture_py_id{};
|
||||||
|
Id shadow_texture_ny_id{};
|
||||||
|
Id shadow_texture_pz_id{};
|
||||||
|
Id shadow_texture_nz_id{};
|
||||||
|
|
||||||
Id texture_buffer_lut_lf{};
|
Id texture_buffer_lut_lf{};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user