-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
gcc anonymous globals relocation failure #53
Comments
Hello. |
And also, are you sure you've implemented |
Hello, yep I have noticed the gcc specifics, I dug in a little more, g++ -g -fPIC -c main.cpp && g++ -g -shared -o main.so main.o && objdump -g main.so | grep St for struct St1 {
int field = 0;
};
St1 St1Instance;
namespace {
struct St2 {
int field = 0;
};
St2 St2Instance;
}
int main() {
return 0;
} correctly returns the debug symbols sasha@sasha:~/gcc_bugs/symbols$ g++ -g -fPIC -c main.cpp && g++ -g -shared -o main.so main.o && objdump -g main.so | grep St
<2f> DW_AT_name : St1
<4b> DW_AT_name : (indirect string, offset: 0xad): St1Instance
<66> DW_AT_name : St2
<7b> DW_AT_name : (indirect string, offset: 0x0): St2Instance
Line Number Statements:
0x00000000 53743249 6e737461 6e636500 474e5520 St2Instance.GNU
0x000000a0 6e006669 656c6400 6d61696e 00537431 n.field.main.St1 Full related dump
I am not sure if I am looking at the correct thing, as I have little idea about all these things, but I don't think it is a gcc regression after the mentioned commit I will try and add debug traps into jet-live to see if it ever finds my global symbol (I'll give it a unique name) when I get the time! Please do let me know if there are more ways I could debug this |
You should look at symbols defined in .bss and .data sections, not debug symbols. For more context you can look into |
Ah, right, main.cppstruct St1 {
int field = 0;
};
St1 St1Instance;
namespace {
struct St2 {
int field = 0;
};
St2 St2Instance;
}
int main() {
St1Instance.field++;
St2Instance.field++;
return 0;
} Also as for logging - my bad, there actually were logs, I have not seen them because it takes another jetLive->update() to display them (because after the hot reload the logs of the hot reload are unprocessed events), but I could not previously reach that because of segfault immediately after hot reload, now I update() twice in a row, and see the logs, and there are a bunch of WTF-s: [JetLive Info]: Success: Render2D.cpp
[JetLive Debug]: Trying to reload code...
[JetLive Info]: Linking...
[JetLive Debug]: Link command:
/usr/local/gcc-14.2.0/bin/g++-14.2 -fPIC -shared -g -Wl,-Ttext-segment,0x10169000 -Wl,-z,max-page-size=0x1000 -Wl,-export-dynamic -Wl,-soname,lib_reload1.so -o lib_reload1.so "/home/sasha/se/cmake-build-debug/Core/CMakeFiles/SECore.dir/Modules/Render/Render2D.cpp.o"
[JetLive Info]: Linked successfully
[JetLive Debug]: Opening /home/sasha/se/cmake-build-debug/lib_reload1.so...
[JetLive Debug]: Library opened successfully
[JetLive Debug]: Loading symbols from /home/sasha/se/cmake-build-debug/lib_reload1.so...
[JetLive Debug]: Symbols loaded
[JetLive Debug]: Loading exported symbols list...
[JetLive Debug]: Done, total exported symbols: 485 in 1 files
[JetLive Debug]: Loading link-time relocations...
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: _ZN2SE12_GLOBAL__N_113StateRender2DE was relocated
[JetLive Debug]: _ZN2SE12_GLOBAL__N_113StateRender2DE was relocated
[JetLive Debug]: _ZN2SE12_GLOBAL__N_113StateRender2DE was relocated
[JetLive Debug]: _ZN2SE12_GLOBAL__N_113StateRender2DE was relocated
[JetLive Debug]: _ZN2SE12_GLOBAL__N_113StateRender2DE was relocated
[JetLive Debug]: _ZN2SE12_GLOBAL__N_113StateRender2DE was relocated
[JetLive Debug]: _ZN2SE12_GLOBAL__N_113StateRender2DE was relocated
[JetLive Debug]: _ZN2SE12_GLOBAL__N_113StateRender2DE was relocated
[JetLive Debug]: Done, relocated: 8/8
[JetLive Debug]: Hooking functions...
[JetLive Debug]: Done, hooked: 510/510
[JetLive Debug]: Copying statics from old code to new one...
[JetLive Debug]: Done, copied: 3/3
[JetLive Info]: Code reloaded
Signal: SIGSEGV (Segmentation fault) I hacked in some code to try to look up the symbols in other sections: ElfProgramInfoLoader.cppif (symFound == symbolsInSections[sectionIndex].end()) {
uint32_t k = 0;
for (; k < elfFile.sections.size(); k++) {
symFound = symbolsInSections[k].find(symRelAddr);
if(symFound != symbolsInSections[k].end()) {
context->events->addLog(LogSeverity::kDebug, std::string("Symbol is in ") + std::to_string(k) + " instead of " + std::to_string(sectionIndex) + " section");
break;
}
}
if(k == elfFile.sections.size()) {
context->events->addLog(LogSeverity::kError, "WTF");
}
continue;
} [JetLive Info]: Success: Render2D.cpp
[JetLive Debug]: Trying to reload code...
[JetLive Info]: Linking...
[JetLive Debug]: Link command:
/usr/local/gcc-14.2.0/bin/g++-14.2 -fPIC -shared -g -Wl,-Ttext-segment,0x10174000 -Wl,-z,max-page-size=0x1000 -Wl,-export-dynamic -Wl,-soname,lib_reload1.so -o lib_reload1.so "/home/sasha/se/cmake-build-debug/Core/CMakeFiles/SECore.dir/Modules/Render/Render2D.cpp.o"
[JetLive Info]: Linked successfully
[JetLive Debug]: Opening /home/sasha/se/cmake-build-debug/lib_reload1.so...
[JetLive Debug]: Library opened successfully
[JetLive Debug]: Loading symbols from /home/sasha/se/cmake-build-debug/lib_reload1.so...
[JetLive Debug]: Symbols loaded
[JetLive Debug]: Loading exported symbols list...
[JetLive Debug]: Done, total exported symbols: 485 in 1 files
[JetLive Debug]: Loading link-time relocations...
[JetLive Debug]: Symbol is in 1101 instead of 432 section
[JetLive Debug]: Symbol is in 1227 instead of 432 section
[JetLive Debug]: Symbol is in 722 instead of 432 section
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Debug]: Symbol is in 1227 instead of 432 section
[JetLive Debug]: Symbol is in 1227 instead of 432 section
[JetLive Debug]: Symbol is in 1227 instead of 432 section
[JetLive Debug]: Symbol is in 722 instead of 432 section
[JetLive Debug]: Symbol is in 1227 instead of 432 section
[JetLive Debug]: Symbol is in 1227 instead of 432 section
[JetLive Debug]: Symbol is in 1226 instead of 432 section
[JetLive Debug]: Symbol is in 1227 instead of 432 section
[JetLive Debug]: Symbol is in 1227 instead of 432 section
[JetLive Error]: WTF
[JetLive Debug]: Symbol is in 1227 instead of 432 section
[JetLive Debug]: Symbol is in 1227 instead of 432 section
[JetLive Debug]: Symbol is in 1227 instead of 432 section
[JetLive Debug]: Symbol is in 1227 instead of 432 section
[JetLive Error]: WTF
[JetLive Debug]: Symbol is in 1101 instead of 432 section
[JetLive Debug]: Symbol is in 1227 instead of 432 section
[JetLive Debug]: Symbol is in 1101 instead of 432 section
[JetLive Debug]: Symbol is in 1226 instead of 432 section
[JetLive Debug]: Symbol is in 1227 instead of 432 section
[JetLive Debug]: Symbol is in 1227 instead of 432 section
[JetLive Error]: WTF
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Symbol is in 1227 instead of 432 section
[JetLive Debug]: Symbol is in 1227 instead of 432 section
[JetLive Debug]: Symbol is in 1227 instead of 432 section
[JetLive Debug]: Symbol is in 1227 instead of 432 section
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Debug]: Symbol is in 1101 instead of 432 section
[JetLive Debug]: Symbol is in 1101 instead of 432 section
[JetLive Debug]: Symbol is in 1101 instead of 432 section
[JetLive Debug]: Symbol is in 1226 instead of 432 section
[JetLive Debug]: Symbol is in 1226 instead of 432 section
[JetLive Debug]: Symbol is in 1227 instead of 432 section
[JetLive Debug]: Symbol is in 1227 instead of 432 section
[JetLive Debug]: Symbol is in 1227 instead of 432 section
[JetLive Debug]: Symbol is in 1227 instead of 432 section
[JetLive Debug]: Symbol is in 722 instead of 432 section
[JetLive Debug]: Symbol is in 722 instead of 432 section
[JetLive Error]: WTF
[JetLive Error]: WTF
[JetLive Debug]: Symbol is in 1227 instead of 432 section
[JetLive Debug]: Symbol is in 1227 instead of 432 section
[JetLive Debug]: Symbol is in 1227 instead of 432 section
[JetLive Debug]: Symbol is in 1227 instead of 432 section
[JetLive Debug]: Symbol is in 1227 instead of 432 section
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: _ZN2SE12_GLOBAL__N_113StateRender2DE was relocated
[JetLive Debug]: _ZN2SE12_GLOBAL__N_113StateRender2DE was relocated
[JetLive Debug]: _ZN2SE12_GLOBAL__N_113StateRender2DE was relocated
[JetLive Debug]: _ZN2SE12_GLOBAL__N_113StateRender2DE was relocated
[JetLive Debug]: _ZN2SE12_GLOBAL__N_113StateRender2DE was relocated
[JetLive Debug]: _ZN2SE12_GLOBAL__N_113StateRender2DE was relocated
[JetLive Debug]: _ZN2SE12_GLOBAL__N_113StateRender2DE was relocated
[JetLive Debug]: _ZN2SE12_GLOBAL__N_113StateRender2DE was relocated
[JetLive Debug]: Done, relocated: 8/8
[JetLive Debug]: Hooking functions...
[JetLive Debug]: Done, hooked: 510/510
[JetLive Debug]: Copying statics from old code to new one...
[JetLive Debug]: Done, copied: 3/3
[JetLive Info]: Code reloaded
Signal: SIGSEGV (Segmentation fault) Lastly I tried this 0000000000000000 l F .text 00000000000000b7 _ZN2SE12_GLOBAL__N_120FRenderStateRender2DaSEOS1_
00000000000034e0 l F .text 00000000000000d4 _ZN2SE12_GLOBAL__N_120FRenderStateRender2DD2Ev
00000000000034e0 l F .text 00000000000000d4 _ZN2SE12_GLOBAL__N_120FRenderStateRender2DD1Ev
0000000000000000 l O .data 0000000000000058 _ZN2SE12_GLOBAL__N_113StateRender2DE if we do the same for my other global variable that is outside of anonymouse namespace in the same file: 0000000000000000 g O .bss 0000000000000010 _ZN2SE5Impll14IterationNodesE So this could be a gcc issue where it does not export the global variable into .bss, however I have not been able to come up with minimal reproducable example (when I try to assemble one, anonymous namespace does get exported), it could potentially be a compiler bug, I shall investigate it further. Please note that moving it outside of anonymous namespace fixes the issue, even though it still does not appear in .bss: 0000000000000000 l d .text._ZN2SE5Impll20FRenderStateRender2DaSEOS1_ 0000000000000000 .text._ZN2SE5Impll20FRenderStateRender2DaSEOS1_
0000000000000000 l d .text._ZN2SE5Impll20FRenderStateRender2DD2Ev 0000000000000000 .text._ZN2SE5Impll20FRenderStateRender2DD2Ev
0000000000000000 l .group 0000000000000000 _ZN2SE5Impll20FRenderStateRender2DD5Ev
0000000000000000 w F .text._ZN2SE5Impll20FRenderStateRender2DaSEOS1_ 00000000000000b7 _ZN2SE5Impll20FRenderStateRender2DaSEOS1_
0000000000000000 w F .text._ZN2SE5Impll20FRenderStateRender2DD2Ev 00000000000000d4 _ZN2SE5Impll20FRenderStateRender2DD2Ev
0000000000000000 w F .text._ZN2SE5Impll20FRenderStateRender2DD2Ev 00000000000000d4 _ZN2SE5Impll20FRenderStateRender2DD1Ev
0000000000000000 g O .data 0000000000000058 _ZN2SE5Impll13StateRender2DE However, the Jet-Live output changes from [JetLive Debug]: Done, relocated: 8/8 to [JetLive Debug]: Done, relocated: 0/0 - as if it no longer even tries to relocate (which might be correct, idk), and there is much more [JetLive Info]: Success: Render2D.cpp
[JetLive Debug]: Trying to reload code...
[JetLive Info]: Linking...
[JetLive Debug]: Link command:
/usr/local/gcc-14.2.0/bin/g++-14.2 -fPIC -shared -g -Wl,-Ttext-segment,0x10153000 -Wl,-z,max-page-size=0x1000 -Wl,-export-dynamic -Wl,-soname,lib_reload1.so -o lib_reload1.so "/home/sasha/se/cmake-build-debug/Core/CMakeFiles/SECore.dir/Modules/Render/Render2D.cpp.o"
[JetLive Info]: Linked successfully
[JetLive Debug]: Opening /home/sasha/se/cmake-build-debug/lib_reload1.so...
[JetLive Debug]: Library opened successfully
[JetLive Debug]: Loading symbols from /home/sasha/se/cmake-build-debug/lib_reload1.so...
[JetLive Debug]: Symbols loaded
[JetLive Debug]: Loading exported symbols list...
[JetLive Debug]: Done, total exported symbols: 489 in 1 files
[JetLive Debug]: Loading link-time relocations...
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Relocation UNKNOWN is not possible in PIC code
[JetLive Debug]: Done, relocated: 0/0
[JetLive Debug]: Hooking functions...
[JetLive Debug]: Done, hooked: 510/510
[JetLive Debug]: Copying statics from old code to new one...
[JetLive Debug]: Done, copied: 3/3
[JetLive Info]: Code reloaded This is objdump for clang file with struct in anonymous namespace (for clang it always works): 0000000000000000 l F .text 0000000000000305 _ZN2SE12_GLOBAL__N_120FRenderStateRender2DD2Ev
0000000000000000 l O .data 0000000000000058 _ZN2SE12_GLOBAL__N_113StateRender2DE
0000000000023280 l F .text 00000000000002eb _ZN2SE12_GLOBAL__N_120FRenderStateRender2DaSEOS1_ this is for clang with struct outside of anonymous namespace: 0000000000000000 l d .text._ZN2SE5Impll20FRenderStateRender2DD2Ev 0000000000000000 .text._ZN2SE5Impll20FRenderStateRender2DD2Ev
0000000000000000 l d .text._ZN2SE5Impll20FRenderStateRender2DaSEOS1_ 0000000000000000 .text._ZN2SE5Impll20FRenderStateRender2DaSEOS1_
0000000000000000 w F .text._ZN2SE5Impll20FRenderStateRender2DD2Ev 0000000000000305 _ZN2SE5Impll20FRenderStateRender2DD2Ev
0000000000000000 g O .data 0000000000000058 _ZN2SE5Impll13StateRender2DE
0000000000000000 w F .text._ZN2SE5Impll20FRenderStateRender2DaSEOS1_ 00000000000002eb _ZN2SE5Impll20FRenderStateRender2DaSEOS1_ Finally the code file in question, though it is of no interest Render2D.cpp#include "Render2D.h"
#include <ECS.h>
#include <Modules/HierarchyPanel/HierarchyPanel.h>
#include <Modules/Textures/TextureComponents.h>
#include "Modules/EntityBook/EntityBook.h"
#include "Modules/Fonts/FontGeom.h"
#include "Modules/Primitives/PrimitivesTypes.h"
#include "Modules/Primitives/PrivatePrimitiveTypes.h"
#include "Modules/Resources/Resources.h"
#include "Modules/Transform/TransformComponents.h"
#include "Render.h"
namespace SE {
namespace {
struct FRenderStateRender2D {
FUniqueBuffer QuadVB;
FUniqueBuffer QuadIB;
FUniqueBuffer InstanceVB;
FUniqueBuffer Constants;
FVersionedShader ShaderVS;
FVersionedShader ShaderFS;
FUniquePipelineState PipelineState;
FUniqueRenderTarget RenderTarget;
FUniqueDescriptor Descriptor;
FUniqueSampler Sampler;
FUniqueProfiler Profiler;
};
FRenderStateRender2D StateRender2D;
}
namespace Impll{
struct FInputVS {
f32vec2 Position;
f32vec2 UV;
};
struct FRenderConstants {
f32vec4 SwapchainHalfSizeInv;
};
struct FUIIterationNode {
entt Entity;
FUIIterationNode *Next = nullptr;
};
TStableHeapArray<FUIIterationNode> IterationNodes = Array::WithMaxSize<FUIIterationNode, FStableHeapAllocator>(65536);
void RenderUI();
void RenderEntityUI(
u32 WhiteTextureId, const CUITransform *UITransform, const CColoredRect *ColoredRect, const CTexturedRect *TexturedRect, const CColor *Color,
const CWorldColorTransform *WorldColorTransform, const CUIStyle *Style, const CUINode *Node, const CBorderColor *BorderColor,
const CTexture *Texture, const CDynamicText *Text);
void RenderEntity2D(
entt Entity, u32 InInstanceIndex, u32 WhiteTextureId, const CUITransform *UITransform, const CLocalTransform *LocalTransform,
const CWorldTransform *WorldTransform, const CColoredRect *ColoredRect, const CTexturedRect *TexturedRect, const CColor *Color,
const CWorldColorTransform *WorldColorTransform, const CTexture *Texture, const CDynamicText *Text);
} // namespace
using namespace Impll;
void MRender2DInit() {
StateRender2D.PipelineState = Rhi.CreatePipelineState();
StateRender2D.RenderTarget = Rhi.CreateRenderTarget();
StateRender2D.Profiler = Rhi.CreateProfiler("Render2D");
FRhiDepthStencilState DepthStencilState = {};
DepthStencilState.DepthTestEnable = false;
DepthStencilState.DepthWrite = false;
DepthStencilState.Compare = ERhiCompareOp::Always;
FRhiRasterizationState RasterizationState = {};
RasterizationState.CullMode = ERhiCullMode::None;
RasterizationState.PolygonMode = ERhiPolygonMode::Solid;
RasterizationState.FrontFace = ERhiFrontFace::Clockwise;
FRhiInputAssemblyState InputAssemblyState = {};
InputAssemblyState.Topology = ERhiPrimitiveTopology::Triangle;
FRhiBlendState BlendState = {};
BlendState.Enable = false;
BlendState.AttachmentStates.Add(FRhiAttachmentState{
FRhiColorMask().WithR().WithG().WithB().WithA(), true, ERhiBlendFactor::SrcAlpha, ERhiBlendFactor::OneMinusSrcAlpha, ERhiBlendOp::Add,
ERhiBlendFactor::One, ERhiBlendFactor::OneMinusSrcAlpha, ERhiBlendOp::Add});
FRhiVertexInputState VertexInputState = {};
VertexInputState.InputAttributes = {
FRhiInputAttribute{ERhiVertexSemantics::Position, 0, 0, ERhiFormat::R32G32_FLOAT, offsetof(FInputVS, Position)},
FRhiInputAttribute{ERhiVertexSemantics::Texcoord, 1, 0, ERhiFormat::R32G32_FLOAT, offsetof(FInputVS, UV)},
FRhiInputAttribute{ERhiVertexSemantics::Texcoord, 2, 1, ERhiFormat::R32G32B32A32_FLOAT, offsetof(FRender2DInstanceVS, PositionAndSize)},
FRhiInputAttribute{ERhiVertexSemantics::Texcoord, 3, 1, ERhiFormat::R32G32B32A32_FLOAT, offsetof(FRender2DInstanceVS, UVPositionAndSize)},
FRhiInputAttribute{ERhiVertexSemantics::Texcoord, 4, 1, ERhiFormat::R32_FLOAT, offsetof(FRender2DInstanceVS, Rotation)},
FRhiInputAttribute{ERhiVertexSemantics::Texcoord, 5, 1, ERhiFormat::R32_UINT, offsetof(FRender2DInstanceVS, TextureId)},
FRhiInputAttribute{ERhiVertexSemantics::Texcoord, 6, 1, ERhiFormat::R32_UINT, offsetof(FRender2DInstanceVS, SamplerId)},
// FRhiInputAttribute{ERhiVertexSemantics::Texcoord, 7, 1, ERhiFormat::R32_UINT, offsetof(FRender2DInstanceVS, EntityId)},
FRhiInputAttribute{ERhiVertexSemantics::Texcoord, 8, 1, ERhiFormat::R32G32B32A32_FLOAT, offsetof(FRender2DInstanceVS, Color)}};
VertexInputState.InputBindings = {
FRhiInputBinding{0, sizeof(FInputVS), ERhiVertexInputRate::Vertex},
FRhiInputBinding{1, sizeof(FRender2DInstanceVS), ERhiVertexInputRate::Instance}};
{
TFrameArray<FInputVS> Vertices = {
{{-0.5, -0.5}, {-0.5, 0.5}}, {{0.5, -0.5}, {0.5, 0.5}}, {{0.5, 0.5}, {0.5, -0.5}}, {{-0.5, 0.5}, {-0.5, -0.5}}};
TFrameArray<u32> Indices = {0, 1, 2, 0, 2, 3};
StateRender2D.QuadVB = Rhi.CreateBuffer(
FRhiBufferDesc{"UIQuadVB", FRhiBufferUsage().WithVertex(), ERhiBufferMemoryUsage::Rendering, ERhiTransferPriority::AlwaysRelevant});
StateRender2D.QuadVB->Update(ToBytes(Vertices));
StateRender2D.QuadIB = Rhi.CreateBuffer(
FRhiBufferDesc{"UIQuadIB", FRhiBufferUsage().WithIndex(), ERhiBufferMemoryUsage::Rendering, ERhiTransferPriority::AlwaysRelevant});
StateRender2D.QuadIB->Update(ToBytes(Indices));
}
StateRender2D.InstanceVB = Rhi.CreateBuffer(
FRhiBufferDesc{"UIInstanceVB", FRhiBufferUsage().WithVertex(), ERhiBufferMemoryUsage::Rendering, ERhiTransferPriority::PerFrame});
StateRender2D.Constants = Rhi.CreateBuffer(
FRhiBufferDesc{"UIConstants", FRhiBufferUsage().WithConstantBuffer(), ERhiBufferMemoryUsage::Rendering, ERhiTransferPriority::PerFrame});
StateRender2D.ShaderVS.Shader = ResourcesBook.Shader("Engine/Shader/UI/UI.hlsl", "MainVS", FRhiShaderStage().WithVertex(), {});
StateRender2D.ShaderFS.Shader = ResourcesBook.Shader("Engine/Shader/UI/UI.hlsl", "MainPS", FRhiShaderStage().WithFragment(), {});
StateRender2D.Sampler = Rhi.CreateSampler(RhiNearestClamp);
StateRender2D.PipelineState->SetDepthStencilState(DepthStencilState);
StateRender2D.PipelineState->SetRasterizationState(RasterizationState);
StateRender2D.PipelineState->SetVertexInputState(VertexInputState);
StateRender2D.PipelineState->SetBlendState(BlendState);
StateRender2D.PipelineState->SetInputAssemblyState(InputAssemblyState);
OnPreClearECS([] {
StateRender2D = {};
});
}
void PrintColoredTree(entt Entity, u32 Depth = 0) {
if(!Depth) {
Outputf("Tree:\n");
}
if(Entity.Has<CColoredRect>()) {
Outputf("{}{}\n", String::Repeat<FFrameAllocator>("-", Depth), Entity);
}
Entity.Children([&](entt Child) {
PrintColoredTree(Child, Depth + 1);
});
}
void MRender2DSubmitST() {
Profiled("MRender2DSubmitST");
var InstanceCount = Render2DInstanceCount.Raw();
Render2DInstanceCount.Raw() = 0;
if(!StateRender2D.QuadVB->IsRenderable() || !StateRender2D.QuadIB->IsRenderable()) {
return;
}
var[MetaVS, VersionVS] = ResourcesBook.ShaderMeta(StateRender2D.ShaderVS.Shader);
var[MetaFS, VersionFS] = ResourcesBook.ShaderMeta(StateRender2D.ShaderFS.Shader);
if(!MetaVS || !MetaFS) {
return;
}
if(VersionVS != StateRender2D.ShaderVS.Version || VersionFS != StateRender2D.ShaderFS.Version) {
StateRender2D.ShaderVS.Version = VersionVS;
StateRender2D.ShaderFS.Version = VersionFS;
var Meta = *MetaVS;
Meta += *MetaFS;
Meta.UpdateHash();
StateRender2D.Descriptor = Rhi.CreateDescriptor(Meta);
StateRender2D.PipelineState->SetShaders(
{FRhiShaderStage().WithVertex(), ResourcesBook.ShaderPointer(StateRender2D.ShaderVS.Shader)},
{FRhiShaderStage().WithFragment(), ResourcesBook.ShaderPointer(StateRender2D.ShaderFS.Shader)});
}
{
Profiled("Update");
alignas(16) FRenderConstants Constants;
var HalfSizeInv = Rhi.Swapchain()->Size32Inv * 2;
Constants.SwapchainHalfSizeInv.X = HalfSizeInv.X;
Constants.SwapchainHalfSizeInv.Y = HalfSizeInv.Y;
StateRender2D.Constants->Update(AsBytes(Constants));
StateRender2D.InstanceVB->Update(AsBytes(TArrayView<FRender2DInstanceVS>(*Render2DInstances, InstanceCount)));
}
{
StateRender2D.Descriptor->BindBuffer("Constants", StateRender2D.Constants);
TStaticArray<FRhiSampler *, 1> Samplers = {*StateRender2D.Sampler};
StateRender2D.Descriptor->BindSamplers("MaterialSamplers", View(Samplers));
StateRender2D.Descriptor->BindTextures("MaterialTextures", ResourcesBook.TextureSparse.ViewElements());
}
StateRender2D.RenderTarget->Clear();
StateRender2D.RenderTarget->Set(
0, Rhi.Swapchain()->GetCurrentTexture(), FRhiTextureRange{ERhiTextureDimension::Texture2D, 0, 1, 0, 1}, FRhiColorAttachment{});
var Commands = Rhi.CreateFrameCommand(ERhiQueueFamily::Graphics);
Commands->Begin(StateRender2D.Profiler);
Commands->BeginMarker("UI");
Commands->ResourceStateTransition(FRhiTextureStateTransition{
Rhi.Swapchain()->GetCurrentTexture(), *Rhi.Swapchain()->GetCurrentTexture()->GetRenderAllocationIndex(),
FRhiTextureRange{ERhiTextureDimension::Texture2D, 0, 1, 0, 1}, ERhiResourceState::Present, ERhiResourceState::RenderTarget});
StateRender2D.QuadVB->ConsumeOwnershipTransfer(Commands);
StateRender2D.QuadIB->ConsumeOwnershipTransfer(Commands);
for(ref Texture: ResourcesBook.TextureSparse) {
Texture->SyncPendingOps(Commands);
}
Commands->SetViewport(Rhi.Swapchain()->Size.X, Rhi.Swapchain()->Size.Y);
Commands->SetScissor(Rhi.Swapchain()->Size.X, Rhi.Swapchain()->Size.Y);
Commands->BeginRenderPass(StateRender2D.RenderTarget);
Commands->BindVertexBuffer(0, StateRender2D.QuadVB);
Commands->BindIndexBuffer(StateRender2D.QuadIB);
Commands->BindVertexBuffer(1, StateRender2D.InstanceVB);
Commands->BindDescriptor(StateRender2D.Descriptor);
Commands->BindPipelineState(StateRender2D.PipelineState);
Commands->DrawIndexed(6, InstanceCount);
Commands->EndRenderPass();
Commands->ResourceStateTransition(FRhiTextureStateTransition{
Rhi.Swapchain()->GetCurrentTexture(), *Rhi.Swapchain()->GetCurrentTexture()->GetRenderAllocationIndex(),
FRhiTextureRange{ERhiTextureDimension::Texture2D, 0, 1, 0, 1}, ERhiResourceState::RenderTarget, ERhiResourceState::Present});
Commands->EndMarker();
Commands->End(StateRender2D.Profiler);
{
Profiled("Submit");
Rhi.Queue()->Submit(ERhiQueueFamily::Graphics, FRhiSubmitInfo{.CmdBuffers = {Commands}});
}
}
void MRender2DWorldMT() {
u32 RenderCounter = 0;
var WhiteTextureId = ResourcesBook.TextureId(CommonResources.WhiteTexture);
EntityQuery<CRenderLayer>([&](entt Entity, const CRenderLayer &RenderLayer) {
if(Likely(RenderLayer.LayerIndex != Meta::MaxValue<u16>)) {
ref Layer = PrimitiveState.Layers[RenderLayer.LayerIndex];
ref SubLayer = Layer.SubLayers[RenderLayer.ToSubLayer()];
RenderCounter += RenderLayer.InstanceCount;
var[UITransform, LocalTransform, WorldTransform, ColoredRect, TexturedRect, Color, WorldColorTransform, Texture, Text] = Entity.Get<
const CUITransform, const CLocalTransform, const CWorldTransform, const CColoredRect, const CTexturedRect, const CColor,
const CWorldColorTransform, const CTexture, const CDynamicText>();
RenderEntity2D(
Entity, SubLayer.Counter->fetch_add(RenderLayer.InstanceCount, std::memory_order::relaxed), WhiteTextureId, UITransform,
LocalTransform, WorldTransform, ColoredRect, TexturedRect, Color, WorldColorTransform, Texture, Text);
}
});
Render2DInstanceCount->fetch_add(RenderCounter, std::memory_order::relaxed);
}
void MRender2DWorldFinalizeST() {
Profiled("MRender2DWorldFinalizeST");
for(ref Layer: PrimitiveState.Layers) {
for(ref SubLayer: Layer.SubLayers) {
VerboseAssert(SubLayer.Counter.Raw() >= SubLayer.InstanceCount);
var Offset = SubLayer.Counter.Raw() - SubLayer.InstanceCount;
var Slice = TArraySlice<FRender2DInstanceVS>(*Render2DInstances + Offset, SubLayer.InstanceCount);
// This is required to avoid order jittering due to table mutations.
Array::SortArray(Slice, [](const FRender2DInstanceVS &A, const FRender2DInstanceVS &B) {
return A.EntityId < B.EntityId;
});
}
}
}
void MRender2DUIST() {
Profiled("MRender2DUIST");
RenderUI();
}
namespace Impll{
void RenderUI() {
var WhiteTextureId = ResourcesBook.TextureId(CommonResources.WhiteTexture);
IterationNodes.Clear();
var Head = &IterationNodes.Add({EntityBook.UIRoot, nullptr});
while(Head) {
var Entity = Head->Entity;
Head = Head->Next;
var[UITransform, ColoredRect, TexturedRect, Color, WorldColorTransform, UIRenderNode, Style, Node, BorderColor, Texture, Text] = Entity.Get<
const CUITransform, const CColoredRect, const CTexturedRect, const CColor, const CWorldColorTransform, const CUIRenderNode,
const CUIStyle, const CUINode, const CBorderColor, const CTexture, const CDynamicText>();
RenderEntityUI(WhiteTextureId, UITransform, ColoredRect, TexturedRect, Color, WorldColorTransform, Style, Node, BorderColor, Texture, Text);
if(Entity == EntityBook.Editor.HierarchyPanel) {
MHierarchyPanelST();
}
for(var Index = (i32)UIRenderNode->Children.GetSize() - 1; Index >= 0; --Index) {
Head = &IterationNodes.Add({UIRenderNode->Children[Index], Head});
}
}
FatalCheckf(Render2DInstanceCount.Raw() <= MaxRender2DInstances, "MaxRender2DInstances must be increased");
}
void RenderEntityUI(
u32 WhiteTextureId, const CUITransform *UITransform, const CColoredRect *ColoredRect, const CTexturedRect *TexturedRect, const CColor *Color,
const CWorldColorTransform *WorldColorTransform, const CUIStyle *Style, const CUINode *Node, const CBorderColor *BorderColor,
const CTexture *Texture, const CDynamicText *Text) {
Profiled("RenderEntityUI");
// Shape.
if(!(ColoredRect || TexturedRect || Text || Style)) {
return;
}
var AABB = f64aabb ::FromPositionAndSize(UITransform->Position, UITransform->Size);
AABB.Clip(Node->AABB);
var AABBPosition = AABB.ComputePosition();
var AABBSize = AABB.ComputeSize();
if(Math::IsAlmostZeroAny(AABBSize)) {
return;
}
if(ColoredRect || TexturedRect) {
ref Instance = Render2DInstances[Render2DInstanceCount.Raw()++];
Instance.PositionAndSize.X = AABBPosition.X;
Instance.PositionAndSize.Y = AABBPosition.Y;
Instance.PositionAndSize.Z = AABBSize.X;
Instance.PositionAndSize.W = AABBSize.Y;
var UVPosition =
(f64vec2{AABBPosition.X - UITransform->Position.X, UITransform->Position.Y - AABBPosition.Y}) / UITransform->Size + f64vec2{0.5, 0.5};
var UVSize = AABBSize / UITransform->Size;
Instance.UVPositionAndSize.X = UVPosition.X;
Instance.UVPositionAndSize.Y = UVPosition.Y;
Instance.UVPositionAndSize.Z = UVSize.X;
Instance.UVPositionAndSize.W = UVSize.Y;
Instance.Rotation = UITransform->Rotation;
if(TexturedRect) {
Instance.TextureId = ResourcesBook.TextureId(Texture->Texture);
} else {
Instance.TextureId = WhiteTextureId;
}
Instance.SamplerId = 0;
var FinalColor = Color ? Color->Color : f64color4{1.0, 1.0, 1.0, 1.0};
if(WorldColorTransform) {
FinalColor *= WorldColorTransform->GetColor();
}
Instance.Color = Math::Crush(FinalColor);
}
// Text.
if(Text) {
for(ref Glyph: Text->FontText.Glyphs) {
var InGlyphPosition = UITransform->Position + Glyph.Position;
var InGlyphSize = Glyph.Size;
var GlyphAABB = f64aabb ::FromPositionAndSize(InGlyphPosition, InGlyphSize);
GlyphAABB.Clip(Node->AABB);
var Size = GlyphAABB.ComputeSize();
if(!Math::IsAlmostZeroAny(Size)) {
var Position = GlyphAABB.ComputePosition();
ref Instance = Render2DInstances[Render2DInstanceCount.Raw()++];
Instance.PositionAndSize.X = Position.X;
Instance.PositionAndSize.Y = Position.Y;
Instance.PositionAndSize.Z = Size.X;
Instance.PositionAndSize.W = Size.Y;
var UVPosition = (Position - InGlyphPosition) / InGlyphSize * Glyph.UVSize + Glyph.UVPosition;
var UVSize = Size / InGlyphSize * Glyph.UVSize;
Instance.UVPositionAndSize.X = UVPosition.X;
Instance.UVPositionAndSize.Y = UVPosition.Y;
Instance.UVPositionAndSize.Z = UVSize.X;
Instance.UVPositionAndSize.W = UVSize.Y;
Instance.Rotation = UITransform->Rotation;
var FinalColor = Glyph.Color;
if(Color) {
FinalColor *= Color->Color;
}
if(WorldColorTransform) {
FinalColor *= WorldColorTransform->GetColor();
}
Instance.TextureId = ResourcesBook.TextureId(Glyph.CustomTexture);
Instance.SamplerId = 0;
Instance.Color = Math::Crush(FinalColor);
}
}
}
// Borders.
if(Style) {
var InnerLeft = UI::ResolveValueIfPoints(Style->InnerBorder[EYGEdge::Left]);
var InnerTop = UI::ResolveValueIfPoints(Style->InnerBorder[EYGEdge::Top]);
var InnerRight = UI::ResolveValueIfPoints(Style->InnerBorder[EYGEdge::Right]);
var InnerBottom = UI::ResolveValueIfPoints(Style->InnerBorder[EYGEdge::Bottom]);
var OuterLeft = UI::ResolveValueIfPoints(Style->OuterBorder[EYGEdge::Left]);
var OuterTop = UI::ResolveValueIfPoints(Style->OuterBorder[EYGEdge::Top]);
var OuterRight = UI::ResolveValueIfPoints(Style->OuterBorder[EYGEdge::Right]);
var OuterBottom = UI::ResolveValueIfPoints(Style->OuterBorder[EYGEdge::Bottom]);
if(InnerLeft || InnerTop || InnerRight || InnerBottom || OuterLeft || OuterTop || OuterRight || OuterBottom) {
var FinalColor = BorderColor ? BorderColor->Color : f64color4{1.0, 1.0, 1.0, 1.0};
if(WorldColorTransform) {
FinalColor *= WorldColorTransform->GetColor();
}
var InstanceColor = Math::Crush(FinalColor);
var ProcessBorder = [&](f64 Value, f64vec2 HalfPositionDirection, f64vec2 SizeDirection, f64 LengthOffset, f64 PositionDirectionOffset,
f64 SizeDirectionOffset) {
if(!Math::IsAlmostZero(Value)) {
var InPosition = UITransform->Position
+ f64vec2{HalfPositionDirection.X * UITransform->Size.X, HalfPositionDirection.Y * UITransform->Size.Y}
+ (PositionDirectionOffset + Value) * HalfPositionDirection + (SizeDirection * SizeDirectionOffset);
var InSize =
Math::Abs(HalfPositionDirection) * Value * 2.0
+ f64vec2{SizeDirection.X * (UITransform->Size.X + LengthOffset), SizeDirection.Y * (UITransform->Size.Y + LengthOffset)};
if(Math::IsAboveZeroExclusive(InSize.X) && Math::IsAboveZeroExclusive(InSize.Y)) {
var AABB = f64aabb ::FromPositionAndSize(InPosition, InSize);
AABB.Clip(Node->AABB);
var Size = AABB.ComputeSize();
if(!Math::IsAlmostZeroAny(Size)) {
var Position = AABB.ComputePosition();
ref Instance = Render2DInstances[Render2DInstanceCount.Raw()++];
Instance.PositionAndSize.X = Position.X;
Instance.PositionAndSize.Y = Position.Y;
Instance.PositionAndSize.Z = Size.X;
Instance.PositionAndSize.W = Size.Y;
Instance.UVPositionAndSize.X = 0.0;
Instance.UVPositionAndSize.Y = 0.0;
Instance.UVPositionAndSize.Z = 0.0;
Instance.UVPositionAndSize.W = 0.0;
Instance.Rotation = 0.0;
Instance.TextureId = WhiteTextureId;
Instance.SamplerId = 0;
Instance.Color = InstanceColor;
}
}
}
};
var InnerHeightOffset = InnerTop + InnerBottom;
ProcessBorder(InnerLeft, {-0.5, 0.0}, {0.0, 1.0}, -InnerHeightOffset, -2.0 * InnerLeft, (InnerTop - InnerBottom) * -0.5);
ProcessBorder(InnerTop, {0.0, 0.5}, {1.0, 0.0}, 0.0, -2.0 * InnerTop, 0.0);
ProcessBorder(InnerRight, {0.5, 0.0}, {0.0, 1.0}, -InnerHeightOffset, -2.0 * InnerRight, (InnerTop - InnerBottom) * -0.5);
ProcessBorder(InnerBottom, {0.0, -0.5}, {1.0, 0.0}, 0.0, -2.0 * InnerBottom, 0.0);
var OuterWidthOffset = OuterLeft + OuterRight;
ProcessBorder(OuterLeft, {-0.5, 0.0}, {0.0, 1.0}, 0.0, 0.0, 0.0);
ProcessBorder(OuterTop, {0.0, 0.5}, {1.0, 0.0}, OuterWidthOffset, 0.0, (OuterRight - OuterLeft) * 0.5);
ProcessBorder(OuterRight, {0.5, 0.0}, {0.0, 1.0}, 0.0, 0.0, 0.0);
ProcessBorder(OuterBottom, {0.0, -0.5}, {1.0, 0.0}, OuterWidthOffset, 0.0, (OuterRight - OuterLeft) * 0.5);
}
}
}
void RenderEntity2D(
entt Entity, u32 InInstanceIndex, u32 WhiteTextureId, const CUITransform *UITransform, const CLocalTransform *LocalTransform,
const CWorldTransform *WorldTransform, const CColoredRect *ColoredRect, const CTexturedRect *TexturedRect, const CColor *Color,
const CWorldColorTransform *WorldColorTransform, const CTexture *Texture, const CDynamicText *Text) {
var InstanceIndex = InInstanceIndex;
// Shape.
if(ColoredRect || TexturedRect) {
ref Instance = Render2DInstances[InstanceIndex++];
if(UITransform) {
Instance.PositionAndSize.X = UITransform->Position.X;
Instance.PositionAndSize.Y = UITransform->Position.Y;
Instance.PositionAndSize.Z = UITransform->Size.X;
Instance.PositionAndSize.W = UITransform->Size.Y;
Instance.Rotation = UITransform->Rotation;
} else if(WorldTransform) {
Instance.PositionAndSize.X = WorldTransform->GetPosition().X;
Instance.PositionAndSize.Y = WorldTransform->GetPosition().Y;
if(LocalTransform) {
Instance.PositionAndSize.Z = LocalTransform->GetScale().X;
Instance.PositionAndSize.W = LocalTransform->GetScale().Y;
} else {
Instance.PositionAndSize.Z = 1.0;
Instance.PositionAndSize.W = 1.0;
}
Instance.Rotation = 0.0;
} else {
Prevent();
}
Instance.UVPositionAndSize.X = 0.5;
Instance.UVPositionAndSize.Y = 0.5;
Instance.UVPositionAndSize.Z = 1.0;
Instance.UVPositionAndSize.W = 1.0;
if(TexturedRect) {
Instance.TextureId = ResourcesBook.TextureId(Texture->Texture);
} else {
Instance.TextureId = WhiteTextureId;
}
Instance.SamplerId = 0;
Instance.EntityId = Entity.Id;
var FinalColor = Color ? Color->Color : f64color4{1.0, 1.0, 1.0, 1.0};
if(WorldColorTransform) {
FinalColor *= WorldColorTransform->GetColor();
}
Instance.Color = Math::Crush(FinalColor);
}
// Text.
if(Text) {
for(ref Glyph: Text->FontText.Glyphs) {
ref Instance = Render2DInstances[InstanceIndex++];
if(UITransform) {
Instance.PositionAndSize.X = UITransform->Position.X + Glyph.Position.X;
Instance.PositionAndSize.Y = UITransform->Position.Y + Glyph.Position.Y;
Instance.PositionAndSize.Z = Glyph.Size.X;
Instance.PositionAndSize.W = Glyph.Size.Y;
Instance.Rotation = UITransform->Rotation;
} else if(WorldTransform) {
Instance.PositionAndSize.X = WorldTransform->GetPosition().X + Glyph.Position.X;
Instance.PositionAndSize.Y = WorldTransform->GetPosition().Y + Glyph.Position.Y;
Instance.PositionAndSize.Z = Glyph.Size.X;
Instance.PositionAndSize.W = Glyph.Size.Y;
Instance.Rotation = 0.0;
} else {
Prevent();
}
Instance.UVPositionAndSize.X = Glyph.UVPosition.X;
Instance.UVPositionAndSize.Y = Glyph.UVPosition.Y;
Instance.UVPositionAndSize.Z = Glyph.UVSize.X;
Instance.UVPositionAndSize.W = Glyph.UVSize.Y;
Instance.TextureId = ResourcesBook.TextureId(Glyph.CustomTexture);
Instance.SamplerId = 0;
Instance.EntityId = Entity.Id;
var FinalColor = Glyph.Color;
if(Color) {
FinalColor *= Color->Color;
}
if(WorldColorTransform) {
FinalColor *= WorldColorTransform->GetColor();
}
Instance.Color = Math::Crush(FinalColor);
}
}
}
} // namespace
void RenderColoredRect2D(
u32 WhiteTextureId, const f64vec2 &InPosition, const f64vec2 &InSize, const f64vec2 &InAlignment, const f64color4 &InColor,
const f64aabb &InAABB) {
ref Instance = Render2DInstances[Render2DInstanceCount.Raw()++];
var AABB = f64aabb::FromPositionAndSize(InPosition + InSize * InAlignment, InSize);
AABB.Clip(InAABB);
var Position = AABB.ComputePosition();
var Size = AABB.ComputeSize();
Instance.PositionAndSize.X = Position.X;
Instance.PositionAndSize.Y = Position.Y;
Instance.PositionAndSize.Z = Size.X;
Instance.PositionAndSize.W = Size.Y;
Instance.Rotation = 0.0;
Instance.UVPositionAndSize.X = 0.0;
Instance.UVPositionAndSize.Y = 0.0;
Instance.UVPositionAndSize.Z = 0.0;
Instance.UVPositionAndSize.W = 0.0;
Instance.TextureId = WhiteTextureId;
Instance.SamplerId = 0;
Instance.Color = Math::Crush(InColor);
}
void RenderText2D(
const f64vec2 &InPosition, const f64aabb &InAABB, TArrayView<FFontTextGenerateResultInstance> Glyphs) {
for(ref Glyph: Glyphs) {
ref Instance = Render2DInstances[Render2DInstanceCount.Raw()++];
var GlyphPosition = InPosition + Glyph.Position;
var GlyphSize = Glyph.Size;
var AABB = f64aabb::FromPositionAndSize(GlyphPosition, GlyphSize);
AABB.Clip(InAABB);
var Position = AABB.ComputePosition();
var Size = AABB.ComputeSize();
Instance.PositionAndSize.X = Position.X;
Instance.PositionAndSize.Y = Position.Y;
Instance.PositionAndSize.Z = Size.X;
Instance.PositionAndSize.W = Size.Y;
var UVPosition = (Position - GlyphPosition) / GlyphSize * Glyph.UVSize + Glyph.UVPosition;
var UVSize = Size / GlyphSize * Glyph.UVSize;
Instance.UVPositionAndSize.X = UVPosition.X;
Instance.UVPositionAndSize.Y = UVPosition.Y;
Instance.UVPositionAndSize.Z = UVSize.X;
Instance.UVPositionAndSize.W = UVSize.Y;
Instance.Rotation = 0.0;
Instance.TextureId = ResourcesBook.TextureId(Glyph.CustomTexture);
Instance.SamplerId = 0;
Instance.Color = Math::Crush(Glyph.Color);
}
}
} // namespace SE Thanks a lot for the heads up on .bss section! I also tried playing around with shouldTransferElfSymbol (changing it here and there), but to no avail, I think if we are not in the .bss section there is nothing we can do after that |
Thank you for thorough investigation! The last thing that you could try is to compile the same sample code with gcc and with clang and check how it looks like under objdump and what are differences. I'm almost sure that this is some specifics of gcc, but following the common sense I assume that if there's some global variable (specifically in anon namespace), it should be stored somewhere, and if gcc is not storing it neither in .data nor in .bss sections, it should store is somewhere else, and if you'll manage to find this place (section name), you can adjust the code of jet-live and make it work as it should. And also you can try to run tests suite with both gcc and clang and check the difference between reports, this could probably help with investigations as well. I'll let you know if I eventually come up with more ideas |
In my case there are no static variables, unless they are qualified as such automatically when they are not getting used outside of CU, I have little idea, I will keep on the lookout for both sections then I will take a loot at the tests suite! Thank you for the quick response Yeah I have updated my comment, in fact both clang and gcc produce an equal .data symbol for the case of anonymous namespace: |
Probably yes, and probably there're some logic errors, so the minimal sample with error would be helpful here |
Ok so not a real repro (it does not corrupt memory), but if you modify the example like this: SimpleCommandInterpreter.cpp#include "SimpleCommandInterpreter.hpp"
namespace
{
struct FGlobal
{
void *A = nullptr;
void *B = nullptr;
};
FGlobal Global;
}
SimpleCommandInterpreter::SimpleCommandInterpreter(int currentCommandsCounter)
: m_currentCommandsCounter(currentCommandsCounter)
{
// Each of these two lines adds +1 WTF to the output
Global.A = (void *)1;
Global.B = (void *)2;
}
int SimpleCommandInterpreter::getCurrentCommandsCounter() const
{
return m_currentCommandsCounter;
}
std::string SimpleCommandInterpreter::runCommand(const std::string& command)
{
auto totalCommands = std::to_string(++m_currentCommandsCounter);
std::string result;
// Implement your commands here
if (command == "Hello") {
result = "Hi there! ";
// These three lines together add one WTF to the output
result += std::to_string((unsigned long long)Global.A);
result += " ";
result += std::to_string((unsigned long long)Global.B);
} else {
result = "Sorry, I don't know what '" + command
+ "' means. Fix it in runtime in 'SimpleCommandInterpreter::runCommand'";
}
return "ttl: " + totalCommands + " > " + result;
}
Hello
ttl: 1 > Hi there!
[I]: Compiling: SimpleCommandInterpreter.cpp
[I]: Success: SimpleCommandInterpreter.cpp
reload
[I]: Trying to reload code...
[I]: Linking...
[D]: Link command:
/usr/local/gcc-14.2.0/bin/g++-14.2 -fPIC -shared -g -Wl,-Ttext-segment,0xa48000 -Wl,-z,max-page-size=0x1000 -Wl,-export-dynamic -Wl,-soname,lib_reload1.so -o lib_reload1.so "/home/sasha/jet-live/cmake-build-debug-gcc/example/CMakeFiles/example.dir/src/SimpleCommandInterpreter.cpp.o"
[I]: Linked successfully
[D]: Opening /home/sasha/jet-live/cmake-build-debug-gcc/lib_reload1.so...
[D]: Library opened successfully
[D]: Loading symbols from /home/sasha/jet-live/cmake-build-debug-gcc/lib_reload1.so...
[D]: Symbols loaded
[D]: Loading exported symbols list...
[D]: Done, total exported symbols: 22 in 1 files
[D]: Loading link-time relocations...
[D]: Done, relocated: 0/0
[D]: Hooking functions...
[D]: Done, hooked: 22/22
[D]: Copying statics from old code to new one...
[D]: Done, copied: 3/3
[I]: Code reloaded Hello
ttl: 1 > Hi there! 1 2
[I]: Compiling: SimpleCommandInterpreter.cpp
[I]: Success: SimpleCommandInterpreter.cpp
reload
[I]: Trying to reload code...
[I]: Linking...
[D]: Link command:
/usr/local/gcc-14.2.0/bin/g++-14.2 -fPIC -shared -g -Wl,-Ttext-segment,0xa48000 -Wl,-z,max-page-size=0x1000 -Wl,-export-dynamic -Wl,-soname,lib_reload1.so -o lib_reload1.so "/home/sasha/jet-live/cmake-build-debug-gcc/example/CMakeFiles/example.dir/src/SimpleCommandInterpreter.cpp.o"
[I]: Linked successfully
[D]: Opening /home/sasha/jet-live/cmake-build-debug-gcc/lib_reload1.so...
[D]: Library opened successfully
[D]: Loading symbols from /home/sasha/jet-live/cmake-build-debug-gcc/lib_reload1.so...
[D]: Symbols loaded
[D]: Loading exported symbols list...
[D]: Done, total exported symbols: 30 in 1 files
[D]: Loading link-time relocations...
[E]: WTF
[E]: WTF
[E]: WTF
[D]: _ZN12_GLOBAL__N_16GlobalE was relocated
[D]: Done, relocated: 1/1
[D]: Hooking functions...
[D]: Done, hooked: 30/30
[D]: Copying statics from old code to new one...
[D]: Done, copied: 3/3
[I]: Code reloaded Then after hot-reload with gcc you will see 3x WTF outputs But after we add -mcmodel=large, we get Hello
ttl: 1 > Hi there! 1 2
[I]: Compiling: SimpleCommandInterpreter.cpp
[I]: Success: SimpleCommandInterpreter.cpp
reload
[I]: Trying to reload code...
[I]: Linking...
[D]: Link command:
/usr/local/gcc-14.2.0/bin/g++-14.2 -fPIC -shared -g -Wl,-Ttext-segment,0xa49000 -Wl,-z,max-page-size=0x1000 -Wl,-export-dynamic -Wl,-soname,lib_reload1.so -o lib_reload1.so "/home/sasha/jet-live/cmake-build-debug-gcc/example/CMakeFiles/example.dir/src/SimpleCommandInterpreter.cpp.o"
[I]: Linked successfully
[D]: Opening /home/sasha/jet-live/cmake-build-debug-gcc/lib_reload1.so...
[D]: Library opened successfully
[D]: Loading symbols from /home/sasha/jet-live/cmake-build-debug-gcc/lib_reload1.so...
[D]: Symbols loaded
[D]: Loading exported symbols list...
[D]: Done, total exported symbols: 30 in 1 files
[D]: Loading link-time relocations...
[E]: Relocation R_X86_64_GOTOFF64 is not possible in PIC code
[E]: Relocation R_X86_64_GOTOFF64 is not possible in PIC code
[E]: Relocation R_X86_64_GOTOFF64 is not possible in PIC code
[E]: Relocation R_X86_64_GOTOFF64 is not possible in PIC code
[D]: Done, relocated: 0/0
[D]: Hooking functions...
[D]: Done, hooked: 30/30
[D]: Copying statics from old code to new one...
[D]: Done, copied: 4/4
[I]: Code reloaded So basically setting this for the application fixes the issue set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mcmodel=large")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mcmodel=large") I discovered that flag when I was debugging by clang issue with jet live long ago, I think it was a compile error of some sorts due to linking with big libraries I could make a pr for it if you wish, but I am not sure if this is a true fix, it could just happen to fix it for my use cases |
That's interesting and could make sense. |
It seems that gcc, unlike clang, does not export symbols from anonymous namespaces with -Wl,-export-dynamic, or does it in a way that jet-live does not recognize
Would love to investigate what causes this, but there are no jet-live logs coming out related to this, so any pointers are appreciated!
Upd.: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=31462 seems to be the old change in gcc that caused this
The text was updated successfully, but these errors were encountered: