From 3bb1ccd4d8d0a144eeba737270b2aaac8d44c17d Mon Sep 17 00:00:00 2001
From: Samuliak <samuliak77@gmail.com>
Date: Tue, 2 Jul 2024 14:02:00 +0200
Subject: [PATCH] sample textures

---
 include/renderer_mtl/renderer_mtl.hpp  |  2 +-
 src/core/renderer_mtl/renderer_mtl.cpp |  7 ++-
 src/host_shaders/metal_shaders.metal   | 69 +++++++++++++++++++++++++-
 3 files changed, 72 insertions(+), 6 deletions(-)

diff --git a/include/renderer_mtl/renderer_mtl.hpp b/include/renderer_mtl/renderer_mtl.hpp
index 5d30c644..751f3dee 100644
--- a/include/renderer_mtl/renderer_mtl.hpp
+++ b/include/renderer_mtl/renderer_mtl.hpp
@@ -56,5 +56,5 @@ class RendererMTL final : public Renderer {
 	}
 
 	MTL::Texture* getTexture(Metal::Texture& tex);
-	void bindTexturesToSlots();
+	void bindTexturesToSlots(MTL::RenderCommandEncoder* encoder);
 };
diff --git a/src/core/renderer_mtl/renderer_mtl.cpp b/src/core/renderer_mtl/renderer_mtl.cpp
index d1b734e3..e6694647 100644
--- a/src/core/renderer_mtl/renderer_mtl.cpp
+++ b/src/core/renderer_mtl/renderer_mtl.cpp
@@ -211,7 +211,7 @@ void RendererMTL::drawVertices(PICA::PrimType primType, std::span<const PICA::Ve
 	renderCommandEncoder->setVertexBytes(vertices.data(), vertices.size_bytes(), VERTEX_BUFFER_BINDING_INDEX);
 
 	// Bind resources
-	bindTexturesToSlots();
+	bindTexturesToSlots(renderCommandEncoder);
 
 	// TODO: respect primitive type
 	renderCommandEncoder->drawPrimitives(MTL::PrimitiveTypeTriangle, NS::UInteger(0), NS::UInteger(vertices.size()));
@@ -245,7 +245,7 @@ MTL::Texture* RendererMTL::getTexture(Metal::Texture& tex) {
 	}
 }
 
-void RendererMTL::bindTexturesToSlots() {
+void RendererMTL::bindTexturesToSlots(MTL::RenderCommandEncoder* encoder) {
 	static constexpr std::array<u32, 3> ioBases = {
 		PICA::InternalRegs::Tex0BorderColor,
 		PICA::InternalRegs::Tex1BorderColor,
@@ -269,8 +269,7 @@ void RendererMTL::bindTexturesToSlots() {
 		if (addr != 0) [[likely]] {
 			Metal::Texture targetTex(device, addr, static_cast<PICA::TextureFmt>(format), width, height, config);
 			MTL::Texture* tex = getTexture(targetTex);
-			// TODO: bind the texture
-			Helpers::warn("Wanted to bind texture %p at index %i", tex, i);
+			encoder->setFragmentTexture(tex, i);
 		} else {
 			// TODO: bind a dummy texture?
 		}
diff --git a/src/host_shaders/metal_shaders.metal b/src/host_shaders/metal_shaders.metal
index 7c13f524..3ad30d0a 100644
--- a/src/host_shaders/metal_shaders.metal
+++ b/src/host_shaders/metal_shaders.metal
@@ -32,16 +32,83 @@ struct DrawVertexIn {
 struct DrawVertexOut {
 	float4 position [[position]];
 	float4 color;
+	float3 texCoord0;
+	float2 texCoord1;
+	float2 texCoord2;
 };
 
 vertex DrawVertexOut vertexDraw(DrawVertexIn in [[stage_in]]) {
 	DrawVertexOut out;
+
+	// Position
 	out.position = in.position;
+	// HACK: rotate the position
+	out.position.xy = -out.position.yx;
 	// in.position.z is in range of [-1 ... 1], convert it to [0 ... 1]
 	out.position.z = (in.position.z + 1.0) * 0.5;
+
+	// Color
 	out.color = in.color;
 
+	// Texture coordinates
+	out.texCoord0 = float3(in.texCoord0, in.texCoord0W);
+	out.texCoord0.y = 1.0 - out.texCoord0.y;
+	out.texCoord1 = in.texCoord1;
+	out.texCoord1.y = 1.0 - out.texCoord1.y;
+	out.texCoord2 = in.texCoord2;
+	out.texCoord2.y = 1.0 - out.texCoord2.y;
+
 	return out;
 }
 
-fragment float4 fragmentDraw(DrawVertexOut in [[stage_in]]) { return in.color; }
+fragment float4 fragmentDraw(DrawVertexOut in [[stage_in]], texture2d<float> tex0 [[texture(0)]], texture2d<float> tex1 [[texture(1)]], texture2d<float> tex2 [[texture(2)]]) {
+    // TODO: upload this as argument
+    sampler samplr;
+
+    float4 tevSources[16];
+    tevSources[0] = in.color;
+    // TODO: uncomment
+	//calcLighting(tevSources[1], tevSources[2]);
+
+	// TODO: uncomment
+	//uint textureConfig = readPicaReg(0x80u);
+	// HACK
+	uint textureConfig = 0b111u;
+	float2 texCoord2 = (textureConfig & (1u << 13)) != 0u ? in.texCoord1 : in.texCoord2;
+
+	if ((textureConfig & 1u) != 0u) tevSources[3] = tex0.sample(samplr, in.texCoord0.xy);
+	if ((textureConfig & 2u) != 0u) tevSources[4] = tex1.sample(samplr, in.texCoord1);
+	if ((textureConfig & 4u) != 0u) tevSources[5] = tex2.sample(samplr, texCoord2);
+	tevSources[13] = float4(0.0);  // Previous buffer
+	tevSources[15] = in.color;     // Previous combiner
+
+	// TODO: uncomment
+	//float4 tevNextPreviousBuffer = v_textureEnvBufferColor;
+	// HACK
+	float4 tevNextPreviousBuffer = float4(0.0);
+	// TODO: uncomment
+	//uint textureEnvUpdateBuffer = readPicaReg(0xE0u);
+	// HACK
+	uint textureEnvUpdateBuffer = 0b111111u;
+
+	for (int i = 0; i < 6; i++) {
+	   // TODO: uncomment
+		tevSources[14] = float4(0.0);//v_textureEnvColor[i];  // Constant color
+		// TODO: uncomment
+		tevSources[15] = float4(1.0);//tevCalculateCombiner(i);
+		tevSources[13] = tevNextPreviousBuffer;
+
+		if (i < 4) {
+			if ((textureEnvUpdateBuffer & (0x100u << i)) != 0u) {
+				tevNextPreviousBuffer.rgb = tevSources[15].rgb;
+			}
+
+			if ((textureEnvUpdateBuffer & (0x1000u << i)) != 0u) {
+				tevNextPreviousBuffer.a = tevSources[15].a;
+			}
+		}
+	}
+
+	// HACK: should be tevSources[15]
+	return tevSources[3];
+}