diff --git a/source/Irrlicht/CD3D9Driver.cpp b/source/Irrlicht/CD3D9Driver.cpp index 97596eeb..5db56bad 100644 --- a/source/Irrlicht/CD3D9Driver.cpp +++ b/source/Irrlicht/CD3D9Driver.cpp @@ -3100,31 +3100,6 @@ const core::matrix4& CD3D9Driver::getTransform(E_TRANSFORMATION_STATE state) con } -//! Get a vertex shader constant index. -s32 CD3D9Driver::getVertexShaderConstantID(const c8* name) -{ - if (Material.MaterialType >= 0 && Material.MaterialType < (s32)MaterialRenderers.size()) - { - CD3D9MaterialRenderer* r = (CD3D9MaterialRenderer*)MaterialRenderers[Material.MaterialType].Renderer; - return r->getVariableID(true, name); - } - - return -1; -} - -//! Get a pixel shader constant index. -s32 CD3D9Driver::getPixelShaderConstantID(const c8* name) -{ - if (Material.MaterialType >= 0 && Material.MaterialType < (s32)MaterialRenderers.size()) - { - CD3D9MaterialRenderer* r = (CD3D9MaterialRenderer*)MaterialRenderers[Material.MaterialType].Renderer; - return r->getVariableID(false, name); - } - - return -1; -} - - //! Sets a vertex shader constant. void CD3D9Driver::setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount) { @@ -3132,7 +3107,6 @@ void CD3D9Driver::setVertexShaderConstant(const f32* data, s32 startRegister, s3 pID3DDevice->SetVertexShaderConstantF(startRegister, data, constantAmount); } - //! Sets a pixel shader constant. void CD3D9Driver::setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount) { @@ -3140,86 +3114,55 @@ void CD3D9Driver::setPixelShaderConstant(const f32* data, s32 startRegister, s32 pID3DDevice->SetPixelShaderConstantF(startRegister, data, constantAmount); } +s32 CD3D9Driver::getVertexShaderConstantID(const c8* name) +{ + os::Printer::log("Error: Please call services->getVertexShaderConstantID(), not VideoDriver->getVertexShaderConstantID()."); + return -1; +} + +s32 CD3D9Driver::getPixelShaderConstantID(const c8* name) +{ + os::Printer::log("Error: Please call services->getPixelShaderConstantID(), not VideoDriver->getPixelShaderConstantID()."); + return -1; +} -//! Sets a constant for the vertex shader based on an index. bool CD3D9Driver::setVertexShaderConstant(s32 index, const f32* floats, int count) { - if (Material.MaterialType >= 0 && Material.MaterialType < (s32)MaterialRenderers.size()) - { - CD3D9MaterialRenderer* r = (CD3D9MaterialRenderer*)MaterialRenderers[Material.MaterialType].Renderer; - return r->setVariable(true, index, floats, count); - } - + os::Printer::log("Error: Please call services->setVertexShaderConstant(), not VideoDriver->setVertexShaderConstant()."); return false; } - -//! Int interface for the above. bool CD3D9Driver::setVertexShaderConstant(s32 index, const s32* ints, int count) { - if (Material.MaterialType >= 0 && Material.MaterialType < (s32)MaterialRenderers.size()) - { - CD3D9MaterialRenderer* r = (CD3D9MaterialRenderer*)MaterialRenderers[Material.MaterialType].Renderer; - return r->setVariable(true, index, ints, count); - } - + os::Printer::log("Error: Please call services->setVertexShaderConstant(), not VideoDriver->setVertexShaderConstant()."); return false; } - -//! Uint interface for the above. bool CD3D9Driver::setVertexShaderConstant(s32 index, const u32* ints, int count) { - if (Material.MaterialType >= 0 && Material.MaterialType < (s32)MaterialRenderers.size()) - { - CD3D9MaterialRenderer* r = (CD3D9MaterialRenderer*)MaterialRenderers[Material.MaterialType].Renderer; - return r->setVariable(true, index, ints, count); - } - + os::Printer::log("Error: Please call services->setVertexShaderConstant(), not VideoDriver->setVertexShaderConstant()."); return false; } - -//! Sets a constant for the pixel shader based on an index. bool CD3D9Driver::setPixelShaderConstant(s32 index, const f32* floats, int count) { - if (Material.MaterialType >= 0 && Material.MaterialType < (s32)MaterialRenderers.size()) - { - CD3D9MaterialRenderer* r = (CD3D9MaterialRenderer*)MaterialRenderers[Material.MaterialType].Renderer; - return r->setVariable(false, index, floats, count); - } - + os::Printer::log("Error: Please call services->setPixelShaderConstant(), not VideoDriver->setPixelShaderConstant()."); return false; } - -//! Int interface for the above. bool CD3D9Driver::setPixelShaderConstant(s32 index, const s32* ints, int count) { - if (Material.MaterialType >= 0 && Material.MaterialType < (s32)MaterialRenderers.size()) - { - CD3D9MaterialRenderer* r = (CD3D9MaterialRenderer*)MaterialRenderers[Material.MaterialType].Renderer; - return r->setVariable(false, index, ints, count); - } - + os::Printer::log("Error: Please call services->setPixelShaderConstant(), not VideoDriver->setPixelShaderConstant()."); return false; } - -//! Uint interface for the above. bool CD3D9Driver::setPixelShaderConstant(s32 index, const u32* ints, int count) { - if (Material.MaterialType >= 0 && Material.MaterialType < (s32)MaterialRenderers.size()) - { - CD3D9MaterialRenderer* r = (CD3D9MaterialRenderer*)MaterialRenderers[Material.MaterialType].Renderer; - return r->setVariable(false, index, ints, count); - } - + os::Printer::log("Error: Please call services->setPixelShaderConstant(), not VideoDriver->setPixelShaderConstant()."); return false; } - //! Adds a new material renderer to the VideoDriver, using pixel and/or //! vertex shaders to render geometry. s32 CD3D9Driver::addShaderMaterial(const c8* vertexShaderProgram, diff --git a/source/Irrlicht/CD3D9HLSLMaterialRenderer.cpp b/source/Irrlicht/CD3D9HLSLMaterialRenderer.cpp index b7007d63..7da11125 100644 --- a/source/Irrlicht/CD3D9HLSLMaterialRenderer.cpp +++ b/source/Irrlicht/CD3D9HLSLMaterialRenderer.cpp @@ -8,6 +8,7 @@ #include "CD3D9HLSLMaterialRenderer.h" #include "IShaderConstantSetCallBack.h" #include "IVideoDriver.h" +#include "CD3D9Driver.h" #include "os.h" #include "irrString.h" @@ -24,7 +25,7 @@ namespace video //! Public constructor CD3D9HLSLMaterialRenderer::CD3D9HLSLMaterialRenderer(IDirect3DDevice9* d3ddev, - video::IVideoDriver* driver, s32& outMaterialTypeNr, + video::CD3D9Driver* driver, s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* vertexShaderEntryPointName, E_VERTEX_SHADER_TYPE vsCompileTarget, @@ -274,6 +275,69 @@ bool CD3D9HLSLMaterialRenderer::createHLSLPixelShader(const char* pixelShaderPro return false; } +void CD3D9HLSLMaterialRenderer::setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates) +{ + Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); +} + +s32 CD3D9HLSLMaterialRenderer::getVertexShaderConstantID(const c8* name) +{ + return getVariableID(true, name); +} + +s32 CD3D9HLSLMaterialRenderer::getPixelShaderConstantID(const c8* name) +{ + return getVariableID(false, name); +} + +void CD3D9HLSLMaterialRenderer::setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount) +{ + // TODO: Not sure if setting constants which are not bound to the shader in hlsl + // I mainly kept this here so it works same as in Irrlicht 1.8 and it probably won't hurt + Driver->setVertexShaderConstant(data, startRegister, constantAmount); +} + +void CD3D9HLSLMaterialRenderer::setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount) +{ + // TODO: Not sure if setting constants which are not bound to the shader in hlsl + // I mainly kept this here so it works same as in Irrlicht 1.8 and it probably won't hurt + static_cast(Driver)->setPixelShaderConstant(data, startRegister, constantAmount); +} + +bool CD3D9HLSLMaterialRenderer::setVertexShaderConstant(s32 index, const f32* floats, int count) +{ + return setVariable(true, index, floats, count); +} + +bool CD3D9HLSLMaterialRenderer::setVertexShaderConstant(s32 index, const s32* ints, int count) +{ + return setVariable(true, index, ints, count); +} + +bool CD3D9HLSLMaterialRenderer::setVertexShaderConstant(s32 index, const u32* ints, int count) +{ + return setVariable(true, index, ints, count); +} + +bool CD3D9HLSLMaterialRenderer::setPixelShaderConstant(s32 index, const f32* floats, int count) +{ + return setVariable(false, index, floats, count); +} + +bool CD3D9HLSLMaterialRenderer::setPixelShaderConstant(s32 index, const s32* ints, int count) +{ + return setVariable(false, index, ints, count); +} + +bool CD3D9HLSLMaterialRenderer::setPixelShaderConstant(s32 index, const u32* ints, int count) +{ + return setVariable(false, index, ints, count); +} + +IVideoDriver* CD3D9HLSLMaterialRenderer::getVideoDriver() +{ + return Driver; +} s32 CD3D9HLSLMaterialRenderer::getVariableID(bool vertexShader, const c8* name) { @@ -305,7 +369,6 @@ s32 CD3D9HLSLMaterialRenderer::getVariableID(bool vertexShader, const c8* name) return -1; } - bool CD3D9HLSLMaterialRenderer::setVariable(bool vertexShader, s32 index, const f32* floats, int count) { @@ -383,7 +446,7 @@ bool CD3D9HLSLMaterialRenderer::OnRender(IMaterialRendererServices* service, E_V if (VSConstantsTable) VSConstantsTable->SetDefaults(pID3DDevice); - return CD3D9ShaderMaterialRenderer::OnRender(service, vtxtype); + return CD3D9ShaderMaterialRenderer::OnRender(this, vtxtype); } diff --git a/source/Irrlicht/CD3D9HLSLMaterialRenderer.h b/source/Irrlicht/CD3D9HLSLMaterialRenderer.h index a9156b67..3b61483e 100644 --- a/source/Irrlicht/CD3D9HLSLMaterialRenderer.h +++ b/source/Irrlicht/CD3D9HLSLMaterialRenderer.h @@ -12,6 +12,7 @@ #include "CD3D9ShaderMaterialRenderer.h" #include "IGPUProgrammingServices.h" +#include "IMaterialRendererServices.h" namespace irr { @@ -23,12 +24,12 @@ class IShaderConstantSetCallBack; class IMaterialRenderer; //! Class for using vertex and pixel shaders via HLSL with D3D9 -class CD3D9HLSLMaterialRenderer : public CD3D9ShaderMaterialRenderer +class CD3D9HLSLMaterialRenderer : public CD3D9ShaderMaterialRenderer, public IMaterialRendererServices { public: //! Public constructor - CD3D9HLSLMaterialRenderer(IDirect3DDevice9* d3ddev, video::IVideoDriver* driver, + CD3D9HLSLMaterialRenderer(IDirect3DDevice9* d3ddev, video::CD3D9Driver* driver, s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* vertexShaderEntryPointName, @@ -43,7 +44,25 @@ public: //! Destructor ~CD3D9HLSLMaterialRenderer(); - virtual s32 getVariableID(bool vertexShader, const c8* name); + bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) IRR_OVERRIDE; + + // implementations for IMaterialRendererServices + virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates) IRR_OVERRIDE; + virtual s32 getVertexShaderConstantID(const c8* name) IRR_OVERRIDE; + virtual s32 getPixelShaderConstantID(const c8* name) IRR_OVERRIDE; + virtual void setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount=1) IRR_OVERRIDE; + virtual void setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount=1) IRR_OVERRIDE; + virtual bool setVertexShaderConstant(s32 index, const f32* floats, int count) IRR_OVERRIDE; + virtual bool setVertexShaderConstant(s32 index, const s32* ints, int count) IRR_OVERRIDE; + virtual bool setVertexShaderConstant(s32 index, const u32* ints, int count) IRR_OVERRIDE; + virtual bool setPixelShaderConstant(s32 index, const f32* floats, int count) IRR_OVERRIDE; + virtual bool setPixelShaderConstant(s32 index, const s32* ints, int count) IRR_OVERRIDE; + virtual bool setPixelShaderConstant(s32 index, const u32* ints, int count) IRR_OVERRIDE; + virtual IVideoDriver* getVideoDriver() IRR_OVERRIDE; + +protected: + + s32 getVariableID(bool vertexShader, const c8* name); //! sets a variable in the shader. //! \param vertexShader: True if this should be set in the vertex shader, false if @@ -51,17 +70,14 @@ public: //! \param index: Index of the variable //! \param floats: Pointer to array of floats //! \param count: Amount of floats in array. - virtual bool setVariable(bool vertexShader, s32 index, const f32* floats, int count); + bool setVariable(bool vertexShader, s32 index, const f32* floats, int count); //! Int interface for the above. - virtual bool setVariable(bool vertexShader, s32 index, const s32* ints, int count); + bool setVariable(bool vertexShader, s32 index, const s32* ints, int count); //! Uint interface for the above. - virtual bool setVariable(bool vertexShader, s32 index, const u32* ints, int count); + bool setVariable(bool vertexShader, s32 index, const u32* ints, int count); - bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) IRR_OVERRIDE; - -protected: bool createHLSLVertexShader(const char* vertexShaderProgram, const char* shaderEntryPointName, diff --git a/source/Irrlicht/CD3D9MaterialRenderer.h b/source/Irrlicht/CD3D9MaterialRenderer.h index d67e81c0..08f36bf4 100644 --- a/source/Irrlicht/CD3D9MaterialRenderer.h +++ b/source/Irrlicht/CD3D9MaterialRenderer.h @@ -53,7 +53,7 @@ inline void setTextureAlphaStage(IDirect3DDevice9* dev, DWORD i, DWORD arg1) } } // anonymous namespace -//! Base class for all internal D3D9 material renderers +//! Base class for all internal D3D9 fixed function material renderers class CD3D9MaterialRenderer : public IMaterialRenderer { public: @@ -64,38 +64,6 @@ public: { } - virtual s32 getVariableID(bool vertexShader, const c8* name) - { - os::Printer::log("Invalid material to set variable in."); - return -1; - } - - //! sets a variable in the shader. - //! \param vertexShader: True if this should be set in the vertex shader, false if - //! in the pixel shader. - //! \param index: Index of the variable - //! \param floats: Pointer to array of floats - //! \param count: Amount of floats in array. - virtual bool setVariable(bool vertexShader, s32 index, const f32* floats, int count) - { - os::Printer::log("Invalid material to set variable in."); - return false; - } - - //! Int interface for the above. - virtual bool setVariable(bool vertexShader, s32 index, const s32* ints, int count) - { - os::Printer::log("Invalid material to set variable in."); - return false; - } - - //! Uint interface for the above. - virtual bool setVariable(bool vertexShader, s32 index, const u32* ints, int count) - { - os::Printer::log("Invalid material to set variable in."); - return false; - } - protected: IDirect3DDevice9* pID3DDevice; diff --git a/source/Irrlicht/CD3D9NormalMapRenderer.cpp b/source/Irrlicht/CD3D9NormalMapRenderer.cpp index 13c6d361..46799876 100644 --- a/source/Irrlicht/CD3D9NormalMapRenderer.cpp +++ b/source/Irrlicht/CD3D9NormalMapRenderer.cpp @@ -6,7 +6,7 @@ #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ #include "CD3D9NormalMapRenderer.h" -#include "IVideoDriver.h" +#include "CD3D9Driver.h" #include "IMaterialRendererServices.h" #include "os.h" #include "SLight.h" @@ -164,7 +164,7 @@ namespace video ""; CD3D9NormalMapRenderer::CD3D9NormalMapRenderer( - IDirect3DDevice9* d3ddev, video::IVideoDriver* driver, + IDirect3DDevice9* d3ddev, video::CD3D9Driver* driver, s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial) : CD3D9ShaderMaterialRenderer(d3ddev, driver, 0, baseMaterial) { diff --git a/source/Irrlicht/CD3D9NormalMapRenderer.h b/source/Irrlicht/CD3D9NormalMapRenderer.h index ff0f333b..cccdacce 100644 --- a/source/Irrlicht/CD3D9NormalMapRenderer.h +++ b/source/Irrlicht/CD3D9NormalMapRenderer.h @@ -29,7 +29,7 @@ class CD3D9NormalMapRenderer : public: CD3D9NormalMapRenderer( - IDirect3DDevice9* d3ddev, video::IVideoDriver* driver, + IDirect3DDevice9* d3ddev, video::CD3D9Driver* driver, s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial); ~CD3D9NormalMapRenderer(); diff --git a/source/Irrlicht/CD3D9ParallaxMapRenderer.cpp b/source/Irrlicht/CD3D9ParallaxMapRenderer.cpp index 5d002df2..5eeb020d 100644 --- a/source/Irrlicht/CD3D9ParallaxMapRenderer.cpp +++ b/source/Irrlicht/CD3D9ParallaxMapRenderer.cpp @@ -6,8 +6,8 @@ #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ #include "CD3D9ParallaxMapRenderer.h" +#include "CD3D9Driver.h" #include "IMaterialRendererServices.h" -#include "IVideoDriver.h" #include "os.h" #include "SLight.h" @@ -222,7 +222,7 @@ namespace video "\n"; CD3D9ParallaxMapRenderer::CD3D9ParallaxMapRenderer( - IDirect3DDevice9* d3ddev, video::IVideoDriver* driver, + IDirect3DDevice9* d3ddev, video::CD3D9Driver* driver, s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial) : CD3D9ShaderMaterialRenderer(d3ddev, driver, 0, baseMaterial), CurrentScale(0.0f) diff --git a/source/Irrlicht/CD3D9ParallaxMapRenderer.h b/source/Irrlicht/CD3D9ParallaxMapRenderer.h index 17dbdac3..b4d803f2 100644 --- a/source/Irrlicht/CD3D9ParallaxMapRenderer.h +++ b/source/Irrlicht/CD3D9ParallaxMapRenderer.h @@ -29,7 +29,7 @@ class CD3D9ParallaxMapRenderer : public: CD3D9ParallaxMapRenderer( - IDirect3DDevice9* d3ddev, video::IVideoDriver* driver, + IDirect3DDevice9* d3ddev, video::CD3D9Driver* driver, s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial); ~CD3D9ParallaxMapRenderer(); diff --git a/source/Irrlicht/CD3D9ShaderMaterialRenderer.cpp b/source/Irrlicht/CD3D9ShaderMaterialRenderer.cpp index fecc85fa..a53acc67 100644 --- a/source/Irrlicht/CD3D9ShaderMaterialRenderer.cpp +++ b/source/Irrlicht/CD3D9ShaderMaterialRenderer.cpp @@ -6,9 +6,9 @@ #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ #include "CD3D9ShaderMaterialRenderer.h" +#include "CD3D9Driver.h" #include "IShaderConstantSetCallBack.h" #include "IMaterialRendererServices.h" -#include "IVideoDriver.h" #include "os.h" #include "irrString.h" @@ -23,7 +23,7 @@ namespace video { //! Public constructor -CD3D9ShaderMaterialRenderer::CD3D9ShaderMaterialRenderer(IDirect3DDevice9* d3ddev, video::IVideoDriver* driver, +CD3D9ShaderMaterialRenderer::CD3D9ShaderMaterialRenderer(IDirect3DDevice9* d3ddev, video::CD3D9Driver* driver, s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram, IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData) : pID3DDevice(d3ddev), Driver(driver), CallBack(callback), BaseMaterial(baseMaterial), @@ -46,7 +46,7 @@ CD3D9ShaderMaterialRenderer::CD3D9ShaderMaterialRenderer(IDirect3DDevice9* d3dde //! constructor only for use by derived classes who want to //! create a fall back material for example. CD3D9ShaderMaterialRenderer::CD3D9ShaderMaterialRenderer(IDirect3DDevice9* d3ddev, - video::IVideoDriver* driver, + video::CD3D9Driver* driver, IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData) : pID3DDevice(d3ddev), Driver(driver), CallBack(callback), BaseMaterial(baseMaterial), diff --git a/source/Irrlicht/CD3D9ShaderMaterialRenderer.h b/source/Irrlicht/CD3D9ShaderMaterialRenderer.h index 88d61e43..d5bd689f 100644 --- a/source/Irrlicht/CD3D9ShaderMaterialRenderer.h +++ b/source/Irrlicht/CD3D9ShaderMaterialRenderer.h @@ -21,7 +21,7 @@ namespace irr namespace video { -class IVideoDriver; +class CD3D9Driver; class IShaderConstantSetCallBack; class IMaterialRenderer; @@ -31,7 +31,7 @@ class CD3D9ShaderMaterialRenderer : public IMaterialRenderer public: //! Public constructor - CD3D9ShaderMaterialRenderer(IDirect3DDevice9* d3ddev, video::IVideoDriver* driver, + CD3D9ShaderMaterialRenderer(IDirect3DDevice9* d3ddev, video::CD3D9Driver* driver, s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram, IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData); @@ -59,7 +59,7 @@ protected: //! constructor only for use by derived classes who want to //! create a fall back material for example. CD3D9ShaderMaterialRenderer(IDirect3DDevice9* d3ddev, - video::IVideoDriver* driver, + video::CD3D9Driver* driver, IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData=0); @@ -88,7 +88,7 @@ protected: LPD3DXCONSTANTTABLE* ppConstantTable); IDirect3DDevice9* pID3DDevice; - video::IVideoDriver* Driver; + video::CD3D9Driver* Driver; IShaderConstantSetCallBack* CallBack; IMaterialRenderer* BaseMaterial; diff --git a/source/Irrlicht/COpenGLSLMaterialRenderer.h b/source/Irrlicht/COpenGLSLMaterialRenderer.h index 389157c6..549e27cd 100644 --- a/source/Irrlicht/COpenGLSLMaterialRenderer.h +++ b/source/Irrlicht/COpenGLSLMaterialRenderer.h @@ -71,7 +71,7 @@ public: return CallBack; } - // implementations for the render services + // implementations for IMaterialRendererServices virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates) IRR_OVERRIDE; virtual s32 getVertexShaderConstantID(const c8* name) IRR_OVERRIDE; virtual s32 getPixelShaderConstantID(const c8* name) IRR_OVERRIDE; diff --git a/tests/tests-last-passed-at.txt b/tests/tests-last-passed-at.txt index 922e932b..6dfcd8af 100644 --- a/tests/tests-last-passed-at.txt +++ b/tests/tests-last-passed-at.txt @@ -1,4 +1,4 @@ Tests finished. 72 tests of 72 passed. Compiled as DEBUG -Test suite pass at GMT Thu Jan 05 13:43:13 2023 +Test suite pass at GMT Fri Apr 21 13:49:43 2023