From c4c3e1883f5a1bfa6e730dfa38cbea7372df6a29 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Sun, 31 Jul 2016 10:52:04 -1000 Subject: [PATCH] Metal extended shader support --- Runtime/Graphics/CModelBoo.cpp | 1 + Runtime/Graphics/Shaders/CModelShaders.cpp | 5 + Runtime/Graphics/Shaders/CModelShaders.hpp | 1 + .../Graphics/Shaders/CModelShadersGLSL.cpp | 5 - .../Graphics/Shaders/CModelShadersMetal.cpp | 23 +++- Runtime/Graphics/Shaders/CSpaceWarpFilter.cpp | 14 ++- Runtime/Graphics/Shaders/CSpaceWarpFilter.hpp | 1 + .../Shaders/CSpaceWarpFilterMetal.cpp | 79 ++++++++++++- .../Graphics/Shaders/CThermalColdFilter.hpp | 1 + .../Shaders/CThermalColdFilterMetal.cpp | 106 +++++++++++++++++- hecl | 2 +- kabufuda | 2 +- 12 files changed, 228 insertions(+), 12 deletions(-) diff --git a/Runtime/Graphics/CModelBoo.cpp b/Runtime/Graphics/CModelBoo.cpp index 05974565d..3d092ce10 100644 --- a/Runtime/Graphics/CModelBoo.cpp +++ b/Runtime/Graphics/CModelBoo.cpp @@ -8,6 +8,7 @@ #include "Shaders/CModelShaders.hpp" #include "Graphics/CBooRenderer.hpp" #include "GameGlobalObjects.hpp" +#include namespace urde { diff --git a/Runtime/Graphics/Shaders/CModelShaders.cpp b/Runtime/Graphics/Shaders/CModelShaders.cpp index f3387fd53..c00246cef 100644 --- a/Runtime/Graphics/Shaders/CModelShaders.cpp +++ b/Runtime/Graphics/Shaders/CModelShaders.cpp @@ -27,6 +27,11 @@ CModelShaders::GetShaderExtensions(boo::IGraphicsDataFactory::Platform plat) } } +const hecl::Backend::TextureInfo CModelShaders::ThermalTextures[] = +{ + {hecl::Backend::TexGenSrc::Normal, 7, 0, 7, true} +}; + CModelShaders::CModelShaders(const hecl::Runtime::FileStoreManager& storeMgr, boo::IGraphicsDataFactory* gfxFactory) : m_shaderCache(storeMgr, gfxFactory, GetShaderExtensions(gfxFactory->platform())) {} diff --git a/Runtime/Graphics/Shaders/CModelShaders.hpp b/Runtime/Graphics/Shaders/CModelShaders.hpp index 18ce5ddea..1585c6d8b 100644 --- a/Runtime/Graphics/Shaders/CModelShaders.hpp +++ b/Runtime/Graphics/Shaders/CModelShaders.hpp @@ -20,6 +20,7 @@ class CModelShaders static hecl::Runtime::ShaderCacheExtensions GetShaderExtensionsGLSL(boo::IGraphicsDataFactory::Platform plat); static hecl::Runtime::ShaderCacheExtensions GetShaderExtensionsHLSL(boo::IGraphicsDataFactory::Platform plat); static hecl::Runtime::ShaderCacheExtensions GetShaderExtensionsMetal(boo::IGraphicsDataFactory::Platform plat); + static const hecl::Backend::TextureInfo ThermalTextures[]; public: struct Light { diff --git a/Runtime/Graphics/Shaders/CModelShadersGLSL.cpp b/Runtime/Graphics/Shaders/CModelShadersGLSL.cpp index 76de712bc..1898774be 100644 --- a/Runtime/Graphics/Shaders/CModelShadersGLSL.cpp +++ b/Runtime/Graphics/Shaders/CModelShadersGLSL.cpp @@ -64,11 +64,6 @@ static const char* ThermalBlockNames[] = {HECL_GLSL_VERT_UNIFORM_BLOCK_NAME, HECL_GLSL_TEXMTX_UNIFORM_BLOCK_NAME, "ThermalUniform"}; -static const hecl::Backend::TextureInfo ThermalTextures[] = -{ - {hecl::Backend::TexGenSrc::Normal, 7, 0, 7, true} -}; - hecl::Runtime::ShaderCacheExtensions CModelShaders::GetShaderExtensionsGLSL(boo::IGraphicsDataFactory::Platform plat) { diff --git a/Runtime/Graphics/Shaders/CModelShadersMetal.cpp b/Runtime/Graphics/Shaders/CModelShadersMetal.cpp index 331c59c43..c600dffa0 100644 --- a/Runtime/Graphics/Shaders/CModelShadersMetal.cpp +++ b/Runtime/Graphics/Shaders/CModelShadersMetal.cpp @@ -43,13 +43,34 @@ static const char* LightingMetal = " return saturate(ret);\n" "}\n"; +static const char* ThermalPostMetal = +"struct ThermalUniform\n" +"{\n" +" float4 mulColor;\n" +" float4 addColor;\n" +"};\n" +"static float4 ThermalPostFunc(thread VertToFrag& vtf, constant ThermalUniform& lu, texture2d tex7, float4 colorIn)\n" +"{\n" +" return tex7.sample(samp, vtf.extTcgs0).rrrr * lu.mulColor + lu.addColor;\n" +"}\n" +"\n"; + static const char* BlockNames[] = {"LightingUniform"}; +static const char* ThermalBlockNames[] = {"ThermalUniform"}; hecl::Runtime::ShaderCacheExtensions CModelShaders::GetShaderExtensionsMetal(boo::IGraphicsDataFactory::Platform plat) { hecl::Runtime::ShaderCacheExtensions ext(plat); - ext.registerExtensionSlot({LightingMetal, "LightingFunc"}, {}, 1, BlockNames); + + /* Normal lit shading */ + ext.registerExtensionSlot({LightingMetal, "LightingFunc"}, {}, 1, BlockNames, 0, nullptr, + hecl::Backend::BlendFactor::Original, hecl::Backend::BlendFactor::Original); + + /* Thermal Visor shading */ + ext.registerExtensionSlot({}, {ThermalPostMetal, "ThermalPostFunc"}, 1, ThermalBlockNames, 1, ThermalTextures, + hecl::Backend::BlendFactor::One, hecl::Backend::BlendFactor::One); + return ext; } diff --git a/Runtime/Graphics/Shaders/CSpaceWarpFilter.cpp b/Runtime/Graphics/Shaders/CSpaceWarpFilter.cpp index 1b728e9cd..f000a6059 100644 --- a/Runtime/Graphics/Shaders/CSpaceWarpFilter.cpp +++ b/Runtime/Graphics/Shaders/CSpaceWarpFilter.cpp @@ -88,7 +88,7 @@ void CSpaceWarpFilter::draw(const zeus::CVector3f& pt) m_uniform.m_indXf[2][0] = -clipRect.x4_left / oldW; clipRect.x4_left = 0; } - + float oldH = clipRect.x10_height; if (clipRect.x8_top < 0) { @@ -104,7 +104,7 @@ void CSpaceWarpFilter::draw(const zeus::CVector3f& pt) clipRect.xc_width = CGraphics::g_ViewportResolution.x - clipRect.x4_left; m_uniform.m_indXf[0][0] = clipRect.xc_width / oldW; } - + tmp = clipRect.x8_top + clipRect.x10_height; if (tmp >= CGraphics::g_ViewportResolution.y) { @@ -123,6 +123,16 @@ void CSpaceWarpFilter::draw(const zeus::CVector3f& pt) else m_uniform.m_matrix[3][2] = pt.z; + if (clipRect.x4_left) + { + clipRect.x4_left -= 1; + clipRect.xc_width += 1; + } + if (clipRect.x8_top) + { + clipRect.x8_top -= 1; + clipRect.x10_height += 1; + } if (clipRect.x4_left + clipRect.xc_width < CGraphics::g_ViewportResolution.x) clipRect.xc_width += 1; if (clipRect.x8_top + clipRect.x10_height < CGraphics::g_ViewportResolution.y) diff --git a/Runtime/Graphics/Shaders/CSpaceWarpFilter.hpp b/Runtime/Graphics/Shaders/CSpaceWarpFilter.hpp index 04442e749..c10685e5e 100644 --- a/Runtime/Graphics/Shaders/CSpaceWarpFilter.hpp +++ b/Runtime/Graphics/Shaders/CSpaceWarpFilter.hpp @@ -12,6 +12,7 @@ class CSpaceWarpFilter { friend struct CSpaceWarpFilterGLDataBindingFactory; friend struct CSpaceWarpFilterVulkanDataBindingFactory; + friend struct CSpaceWarpFilterMetalDataBindingFactory; struct Uniform { diff --git a/Runtime/Graphics/Shaders/CSpaceWarpFilterMetal.cpp b/Runtime/Graphics/Shaders/CSpaceWarpFilterMetal.cpp index 9a4c3cdda..2cc9b0464 100644 --- a/Runtime/Graphics/Shaders/CSpaceWarpFilterMetal.cpp +++ b/Runtime/Graphics/Shaders/CSpaceWarpFilterMetal.cpp @@ -3,11 +3,88 @@ namespace urde { +static const char* VS = +"#include \n" +"using namespace metal;\n" +"struct VertData\n" +"{\n" +" float4 posIn [[ attribute(0) ]];\n" +" float4 uvIn [[ attribute(1) ]];\n" +"};\n" +"struct SpaceWarpUniform\n" +"{\n" +" float4x4 mainMtx;\n" +" float4x4 indMtx;\n" +" float4 strength;\n" +"};\n" +"\n" +"struct VertToFrag\n" +"{\n" +" float4 position [[ position ]];\n" +" float2 sceneUv;\n" +" float2 indUv;\n" +" float2 strength;\n" +"};\n" +"\n" +"vertex VertToFrag vmain(VertData v [[ stage_in ]], constant SpaceWarpUniform& swu [[ buffer(2) ]])\n" +"{\n" +" VertToFrag vtf;\n" +" vtf.position = swu.mainMtx * float4(v.posIn.xy, 0.0, 1.0);\n" +" vtf.sceneUv = vtf.position.xy * float2(0.5) + float2(0.5);\n" +" vtf.sceneUv.y = -vtf.sceneUv.y;\n" +" vtf.indUv = (float3x3(swu.indMtx[0].xyz, swu.indMtx[1].xyz, swu.indMtx[2].xyz) * float3(v.uvIn.xy, 1.0)).xy;\n" +" vtf.indUv.y = -vtf.indUv.y;\n" +" vtf.strength = swu.strength.xy;\n" +" return vtf;\n" +"}\n"; + +static const char* FS = +"#include \n" +"using namespace metal;\n" +"constexpr sampler samp(address::repeat, filter::linear);\n" +"struct VertToFrag\n" +"{\n" +" float4 position [[ position ]];\n" +" float2 sceneUv;\n" +" float2 indUv;\n" +" float2 strength;\n" +"};\n" +"\n" +"fragment float4 fmain(VertToFrag vtf [[ stage_in ]], texture2d sceneTex [[ texture(0) ]], texture2d indTex [[ texture(1) ]])\n" +"{\n" +" return sceneTex.sample(samp, vtf.sceneUv + (indTex.sample(samp, vtf.indUv).xy * float2(2.0) - float2(1.0 - 1.0 / 256.0)) * vtf.strength.xy);\n" +"}\n"; + +URDE_DECL_SPECIALIZE_SHADER(CSpaceWarpFilter) + +struct CSpaceWarpFilterMetalDataBindingFactory : TShader::IDataBindingFactory +{ + boo::IShaderDataBinding* BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, CSpaceWarpFilter& filter) + { + boo::MetalDataFactory::Context& cctx = static_cast(ctx); + + boo::IGraphicsBuffer* bufs[] = {filter.m_uniBuf}; + boo::ITexture* texs[] = {CGraphics::g_SpareTexture, filter.m_warpTex}; + return cctx.newShaderDataBinding(TShader::m_pipeline, + TShader::m_vtxFmt, + filter.m_vbo, nullptr, nullptr, 1, bufs, + nullptr, nullptr, nullptr, 2, texs); + } +}; + TShader::IDataBindingFactory* CSpaceWarpFilter::Initialize(boo::MetalDataFactory::Context& ctx, boo::IShaderPipeline*& pipeOut, boo::IVertexFormat*& vtxFmtOut) { - return nullptr; + const boo::VertexElementDescriptor VtxVmt[] = + { + {nullptr, nullptr, boo::VertexSemantic::Position4}, + {nullptr, nullptr, boo::VertexSemantic::UV4} + }; + vtxFmtOut = ctx.newVertexFormat(2, VtxVmt); + pipeOut = ctx.newShaderPipeline(VS, FS, vtxFmtOut, CGraphics::g_ViewportSamples, boo::BlendFactor::One, + boo::BlendFactor::Zero, boo::Primitive::TriStrips, false, false, false); + return new CSpaceWarpFilterMetalDataBindingFactory; } } diff --git a/Runtime/Graphics/Shaders/CThermalColdFilter.hpp b/Runtime/Graphics/Shaders/CThermalColdFilter.hpp index 117657d6d..39afa0457 100644 --- a/Runtime/Graphics/Shaders/CThermalColdFilter.hpp +++ b/Runtime/Graphics/Shaders/CThermalColdFilter.hpp @@ -12,6 +12,7 @@ class CThermalColdFilter { friend struct CThermalColdFilterGLDataBindingFactory; friend struct CThermalColdFilterVulkanDataBindingFactory; + friend struct CThemalColdFilterMetalDataBindingFactory; struct Uniform { diff --git a/Runtime/Graphics/Shaders/CThermalColdFilterMetal.cpp b/Runtime/Graphics/Shaders/CThermalColdFilterMetal.cpp index cd7f85343..ad7bf840a 100644 --- a/Runtime/Graphics/Shaders/CThermalColdFilterMetal.cpp +++ b/Runtime/Graphics/Shaders/CThermalColdFilterMetal.cpp @@ -3,11 +3,115 @@ namespace urde { +static const char* VS = +"#include \n" +"using namespace metal;\n" +"struct VertData\n" +"{\n" +" float4 posIn [[ attribute(0) ]];\n" +" float4 uvIn [[ attribute(1) ]];\n" +"};\n" +"\n" +"struct ThermalColdUniform\n" +"{\n" +" float4x4 shiftMtx;\n" +" float4x4 indMtx;\n" +" float4 shiftScale;\n" +" float4 colorReg0;\n" +" float4 colorReg1;\n" +" float4 colorReg2;\n" +"};\n" +"\n" +"struct VertToFrag\n" +"{\n" +" float4 position [[ position ]];\n" +" float3 indMtx0;\n" +" float3 indMtx1;\n" +" float3 indMtx2;\n" +" float4 colorReg0;\n" +" float4 colorReg1;\n" +" float4 colorReg2;\n" +" float2 sceneUv;\n" +" float2 shiftUv;\n" +" float2 shiftScale;\n" +"};\n" +"\n" +"vertex VertToFrag vmain(VertData v [[ stage_in ]], constant ThermalColdUniform& tcu [[ buffer(2) ]])\n" +"{\n" +" VertToFrag vtf;\n" +" vtf.indMtx0 = tcu.indMtx[0].xyz;\n" +" vtf.indMtx1 = tcu.indMtx[1].xyz;\n" +" vtf.indMtx2 = tcu.indMtx[2].xyz;\n" +" vtf.colorReg0 = tcu.colorReg0;\n" +" vtf.colorReg1 = tcu.colorReg1;\n" +" vtf.colorReg2 = tcu.colorReg2;\n" +" vtf.sceneUv = v.uvIn.xy;\n" +" vtf.shiftUv = (float3x3(tcu.shiftMtx[0].xyz, tcu.shiftMtx[1].xyz, tcu.shiftMtx[2].xyz) * v.uvIn.xyz).xy;\n" +" vtf.shiftScale = tcu.shiftScale.xy;\n" +" vtf.position = float4(v.posIn.xyz, 1.0);\n" +" return vtf;\n" +"}\n"; + +static const char* FS = +"#include \n" +"using namespace metal;\n" +"constexpr sampler samp(address::repeat, filter::linear);\n" +"struct VertToFrag\n" +"{\n" +" float4 position [[ position ]];\n" +" float3 indMtx0;\n" +" float3 indMtx1;\n" +" float3 indMtx2;\n" +" float4 colorReg0;\n" +" float4 colorReg1;\n" +" float4 colorReg2;\n" +" float2 sceneUv;\n" +" float2 shiftUv;\n" +" float2 shiftScale;\n" +"};\n" +"\n" +"constant float4 kRGBToYPrime = {0.299, 0.587, 0.114, 0.0};\n" +"fragment float4 fmain(VertToFrag vtf [[ stage_in ]], texture2d sceneTex [[ texture(0) ]], texture2d shiftTex [[ texture(1) ]])\n" +"{\n" +" float2 shiftCoordTexel = shiftTex.sample(samp, vtf.shiftUv).xy;\n" +" float2 shiftCoord = vtf.sceneUv + shiftCoordTexel * vtf.shiftScale;\n" +" float shiftScene0 = dot(sceneTex.sample(samp, shiftCoord), kRGBToYPrime);\n" +" float shiftScene1 = dot(sceneTex.sample(samp, shiftCoord + float2(vtf.shiftScale.x / 8.0, 0.0)), kRGBToYPrime);\n" +" float2 indCoord = (float3x3(vtf.indMtx0, vtf.indMtx1, vtf.indMtx2) * float3(shiftScene0 - 0.5, shiftScene1 - 0.5, 1.0)).xy;\n" +" float indScene = dot(sceneTex.sample(samp, vtf.sceneUv + indCoord), kRGBToYPrime);\n" +" return vtf.colorReg0 * indScene + vtf.colorReg1 * shiftScene0 + vtf.colorReg2;\n" +"}\n"; + +URDE_DECL_SPECIALIZE_SHADER(CThermalColdFilter) + +struct CThemalColdFilterMetalDataBindingFactory : TShader::IDataBindingFactory +{ + boo::IShaderDataBinding* BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, CThermalColdFilter& filter) + { + boo::MetalDataFactory::Context& cctx = static_cast(ctx); + + boo::IGraphicsBuffer* bufs[] = {filter.m_uniBuf}; + boo::ITexture* texs[] = {CGraphics::g_SpareTexture, filter.m_shiftTex}; + return cctx.newShaderDataBinding(TShader::m_pipeline, + TShader::m_vtxFmt, + filter.m_vbo, nullptr, nullptr, 1, bufs, + nullptr, nullptr, nullptr, 2, texs); + } +}; + TShader::IDataBindingFactory* CThermalColdFilter::Initialize(boo::MetalDataFactory::Context& ctx, boo::IShaderPipeline*& pipeOut, boo::IVertexFormat*& vtxFmtOut) { - return nullptr; + const boo::VertexElementDescriptor VtxVmt[] = + { + {nullptr, nullptr, boo::VertexSemantic::Position4}, + {nullptr, nullptr, boo::VertexSemantic::UV4} + }; + vtxFmtOut = ctx.newVertexFormat(2, VtxVmt); + pipeOut = ctx.newShaderPipeline(VS, FS, vtxFmtOut, CGraphics::g_ViewportSamples, boo::BlendFactor::One, + boo::BlendFactor::Zero, boo::Primitive::TriStrips, false, false, false); + return new CThemalColdFilterMetalDataBindingFactory; } } diff --git a/hecl b/hecl index 3f47a0524..cb3e8d09f 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit 3f47a0524451e46c73915e81de85e0a926a29e12 +Subproject commit cb3e8d09fe2def4bf594d5d4f8822440dddb3ce9 diff --git a/kabufuda b/kabufuda index 99069bd06..d242e2deb 160000 --- a/kabufuda +++ b/kabufuda @@ -1 +1 @@ -Subproject commit 99069bd069a93ab2d98dcd09b799711d2f93754c +Subproject commit d242e2deb63b2fc6da526e7245d4dfa487731af4