diff --git a/include/renderer_mtl/mtl_draw_pipeline_cache.hpp b/include/renderer_mtl/mtl_draw_pipeline_cache.hpp index 5e9e1b66..a28caf1b 100644 --- a/include/renderer_mtl/mtl_draw_pipeline_cache.hpp +++ b/include/renderer_mtl/mtl_draw_pipeline_cache.hpp @@ -17,6 +17,7 @@ struct DrawPipelineHash { // Specialization constants bool lightingEnabled; + u8 lightingNumLights; }; // Bind the vertex buffer to binding 30 so that it doesn't occupy the lower indices @@ -41,14 +42,15 @@ public: } MTL::RenderPipelineState* get(DrawPipelineHash hash) { - u64 pipelineHash = ((u64)hash.colorFmt << 37) | ((u64)hash.depthFmt << 34) | ((u64)hash.blendEnabled << 33) | ((u64)hash.blendControl << 1) | (u64)hash.lightingEnabled; + u8 fragmentFunctionHash = ((u8)hash.lightingEnabled << 4) | hash.lightingNumLights; + u64 pipelineHash = ((u64)hash.colorFmt << 44) | ((u64)hash.depthFmt << 41) | ((u64)hash.blendEnabled << 40) | ((u64)hash.blendControl << 8) | fragmentFunctionHash; auto& pipeline = pipelineCache[pipelineHash]; if (!pipeline) { - u8 fragmentFunctionHash = (u8)hash.lightingEnabled; auto& fragmentFunction = fragmentFunctionCache[fragmentFunctionHash]; if (!fragmentFunction) { MTL::FunctionConstantValues* constants = MTL::FunctionConstantValues::alloc()->init(); constants->setConstantValue(&hash.lightingEnabled, MTL::DataTypeBool, NS::UInteger(0)); + constants->setConstantValue(&hash.lightingNumLights, MTL::DataTypeUChar, NS::UInteger(1)); NS::Error* error = nullptr; fragmentFunction = library->newFunction(NS::String::string("fragmentDraw", NS::ASCIIStringEncoding), constants, &error); diff --git a/src/core/renderer_mtl/renderer_mtl.cpp b/src/core/renderer_mtl/renderer_mtl.cpp index f07c85c5..a7fa208e 100644 --- a/src/core/renderer_mtl/renderer_mtl.cpp +++ b/src/core/renderer_mtl/renderer_mtl.cpp @@ -385,6 +385,7 @@ void RendererMTL::drawVertices(PICA::PrimType primType, std::spanformat; } pipelineHash.lightingEnabled = regs[0x008F] & 1; + pipelineHash.lightingNumLights = (regs[0x01C2] & 0x7) + 1; // Blending and logic op pipelineHash.blendEnabled = (regs[PICA::InternalRegs::ColourOperation] & (1 << 8)) != 0; diff --git a/src/host_shaders/metal_shaders.metal b/src/host_shaders/metal_shaders.metal index 2f92ff27..e88b867e 100644 --- a/src/host_shaders/metal_shaders.metal +++ b/src/host_shaders/metal_shaders.metal @@ -383,6 +383,9 @@ float3 regToColor(uint reg) { return scale * float3(float(extract_bits(reg, 20, 8)), float(extract_bits(reg, 10, 8)), float(extract_bits(reg, 00, 8))); } +constant bool lightingEnabled [[function_constant(0)]]; +constant uint8_t lightingNumLights [[function_constant(1)]]; + // Implements the following algorthm: https://mathb.in/26766 void calcLighting(thread DrawVertexOut& in, constant PicaRegs& picaRegs, texture1d_array texLightingLut, sampler linearSampler, thread float4& primaryColor, thread float4& secondaryColor) { // Quaternions describe a transformation from surface-local space to eye space. @@ -394,7 +397,6 @@ void calcLighting(thread DrawVertexOut& in, constant PicaRegs& picaRegs, texture float3 view = normalize(in.view); uint GPUREG_LIGHTING_AMBIENT = picaRegs.read(0x01C0u); - uint GPUREG_LIGHTING_NUM_LIGHTS = (picaRegs.read(0x01C2u) & 0x7u) + 1u; uint GPUREG_LIGHTING_LIGHT_PERMUTATION = picaRegs.read(0x01D9u); primaryColor = float4(float3(0.0), 1.0); @@ -411,7 +413,7 @@ void calcLighting(thread DrawVertexOut& in, constant PicaRegs& picaRegs, texture bool errorUnimpl = false; - for (uint i = 0u; i < GPUREG_LIGHTING_NUM_LIGHTS; i++) { + for (uint i = 0u; i < lightingNumLights; i++) { uint lightID = extract_bits(GPUREG_LIGHTING_LIGHT_PERMUTATION, int(i * 3u), 3); uint GPUREG_LIGHTi_SPECULAR0 = picaRegs.read(0x0140u + 0x10u * lightID); @@ -535,9 +537,6 @@ float4 performLogicOp(LogicOp logicOp, float4 s, float4 d) { return as_type(performLogicOpU(logicOp, as_type(s), as_type(d))); } -constant int LIGHTING_ENABLED_INDEX = 0; -constant bool lightingEnabled [[function_constant(LIGHTING_ENABLED_INDEX)]]; - fragment float4 fragmentDraw(DrawVertexOut in [[stage_in]], float4 prevColor [[color(0)]], constant PicaRegs& picaRegs [[buffer(0)]], constant FragTEV& tev [[buffer(1)]], constant LogicOp& logicOp [[buffer(2)]], texture2d tex0 [[texture(0)]], texture2d tex1 [[texture(1)]], texture2d tex2 [[texture(2)]], texture1d_array texLightingLut [[texture(3)]], sampler samplr0 [[sampler(0)]], sampler samplr1 [[sampler(1)]], sampler samplr2 [[sampler(2)]], sampler linearSampler [[sampler(3)]]) {