2026-02-27

Software is genuinely screwed by AI (I think)

It's 2AM. My recent interation with AI coding tools (to be specific Claude Code with Opus 4.6) genuinely makes me think most of software engineering will be dead. And I am down an entire can of beer.

I am the last one to join the AI hype. But the capablities of Claude Code is truly scary. No longer AI just tries to spit out response or code based on text approxmiation. But they can actually track down bugs, investigate, use system tools, read profile results and report next steps. This was unimaginable a year ago. And the code quality (at least in constrained cases) can be as good as many senior developers. See the following transcript of me asking Claude to update my old renderer project from using Embree 2 to Embree 4 - this would have taken a junior several days and senior who has experience half:

❯ Please upgrade the Embree accelerator code to use embree 4

● 2 agents finished (ctrl+o to expand)
   ├─ Explore (Explore Embree accelerator code) · 13 tool uses · 23.4k tokens
   │  ⎿  Done
   └─ Task (Research Embree 3 to 4 changes) · 16 tool uses · 29.2k tokens
      ⎿  Done

● Now I have a complete picture. The code is currently using Embree 2 and needs to jump to Embree 4. Let me read the files and make the changes.

● Read 4 files (ctrl+o to expand)

● Now I have the full picture. Let me make all the changes. The code uses Embree 2 API and needs to be upgraded to Embree 4.

  Key changes needed:
  1. Headers: embree2/rtcore.h + embree2/rtcore_ray.h → embree4/rtcore.h
  2. Scene creation: rtcDeviceNewScene(device, flags, aflags) → rtcNewScene(device) + flag setters
  3. Cleanup: rtcDeleteScene/rtcDeleteDevice → rtcReleaseScene/rtcReleaseDevice
  4. Geometry: rtcNewTriangleMesh + map/unmap → rtcNewGeometry + rtcSetSharedGeometryBuffer + attach
  5. Commit: rtcCommit → rtcCommitScene (plus rtcCommitGeometry)
  6. Ray structs: RTCRay (unified) → RTCRayHit with .ray and .hit sub-structs
  7. Intersection: rtcIntersect1M → rtcIntersect1 (stream variant removed in Embree 4)
  8. Context: RTCIntersectContext → pass NULL args (simple case)
  9. CMake: link embree4 instead of embree

● Update(Incarnate/include/Accelerator.hpp)
  ⎿  Added 1 line, removed 2 lines
       7  #include <vector>
       8
       9  #ifdef INC_EMBREE_ACCELERATOR
      10 -#include <embree2/rtcore.h>
      11 -#include <embree2/rtcore_ray.h>
      10 +#include <embree4/rtcore.h>
      11  #endif
      12  namespace Incarnate
      13  {

● Update(Incarnate/CMakeLists.txt)
  ⎿  Added 1 line, removed 2 lines
      11  install(TARGETS Incarnate Incarnate DESTINATION /usr/lib)
      12  install(DIRECTORY include/ DESTINATION /usr/include/Incarnate)
      13
      14 -#HACK: don't find FineEmbree.cmake anywhere. So just link to it
      14  if(INC_EMBREE_ACCELERATOR)
      16 -  target_link_libraries(Incarnate embree)
      15 +  target_link_libraries(Incarnate embree4)
      16  endif()

● Now let me update the main implementation file with the Embree 4 API:

● Update(Incarnate/src/Accelerator.cpp)
  ⎿  Added 5 lines, removed 5 lines
      316  EmbreeAccelerator::EmbreeAccelerator()
      317  {
      318    device = rtcNewDevice(nullptr);
      319 -  //Since we don't support dymantic scene for now. Just use a static scene
      320 -  //RTC_SCENE_DYNAMIC for dynamic scenes
      321 -  embreeScene = rtcDeviceNewScene(device, RTC_SCENE_STATIC|RTC_SCENE_HIGH_QUALITY|RTC_SCENE_INCOHERENT, RTC_INTERSECT1|RTC_INTERSECT_STREAM);
      319 +  embreeScene = rtcNewScene(device);
      320 +  rtcSetSceneFlags(embreeScene, RTC_SCENE_FLAG_NONE);
      321 +  rtcSetSceneBuildQuality(embreeScene, RTC_BUILD_QUALITY_HIGH);
      322  }
      323  EmbreeAccelerator::~EmbreeAccelerator()
      324  {
      325 -  rtcDeleteScene(embreeScene);
      326 -  rtcDeleteDevice(device);
      325 +  rtcReleaseScene(embreeScene);
      326 +  rtcReleaseDevice(device);
      327  }
      328
      329  void EmbreeAccelerator::build()
  ⎿  Found 4 new diagnostic issues in 1 file (ctrl+o to expand)

● Those diagnostics are pre-existing (angled includes resolved via CMake include paths). Now let me update the build() method:

● Update(Incarnate/src/Accelerator.cpp)
  ⎿  Added 12 lines, removed 10 lines
      328
      329  void EmbreeAccelerator::build()
      330  {
      331 -  // struct EmbreeVertex   { float x, y, z, a; };
      332 -  // struct EmbreeTriangle { int v0, v1, v2; };
      331    int triangleCount = scene->getTriangleCount();
      334 -  unsigned int mesh = rtcNewTriangleMesh(embreeScene, RTC_GEOMETRY_STATIC, triangleCount, triangleCount*3);
      335 -  //glm::vec4 should have the same layout as Embree's Vec3fa
      336 -  float4* vertices = (float4*)rtcMapBuffer(embreeScene,mesh,RTC_VERTEX_BUFFER);
      337 -  int3* triangleIndices = (int3*)rtcMapBuffer(embreeScene,mesh,RTC_INDEX_BUFFER);
      332
      333 +  RTCGeometry geom = rtcNewGeometry(device, RTC_GEOMETRY_TYPE_TRIANGLE);
      334 +
      335 +  //float4 should have the same layout as Embree's Vec3fa (float3 + padding)
      336 +  float4* vertices = (float4*)rtcSetNewGeometryBuffer(geom, RTC_BUFFER_TYPE_VERTEX, 0,
      337 +    RTC_FORMAT_FLOAT3, sizeof(float4), triangleCount*3);
      338 +  int3* triangleIndices = (int3*)rtcSetNewGeometryBuffer(geom, RTC_BUFFER_TYPE_INDEX, 0,
      339 +    RTC_FORMAT_UINT3, sizeof(int3), triangleCount);
      340 +
      341    //Fill in the buffer in a lazy way
      342    #pragma omp parallel for
      343    for(int i=0;i<triangleCount;i++)
     ...
      350      }
      351    }
      352
      351 -  rtcUnmapBuffer(embreeScene, mesh, RTC_VERTEX_BUFFER);
      352 -  rtcUnmapBuffer(embreeScene, mesh, RTC_INDEX_BUFFER);
      353 -
      354 -  rtcCommit(embreeScene);
      353 +  rtcCommitGeometry(geom);
      354 +  rtcAttachGeometry(embreeScene, geom);
      355 +  rtcReleaseGeometry(geom);
      356 +  rtcCommitScene(embreeScene);
      357  }
      358
      359  RayHit EmbreeAccelerator::raycast(const Ray& ray)
  ⎿  Found 10 new diagnostic issues in 1 file (ctrl+o to expand)

● Those diagnostics are just the clang linter not having the include paths — they're pre-existing. Now let me update the raycast method:

● Update(Incarnate/src/Accelerator.cpp)
  ⎿  Added 18 lines, removed 21 lines
      362    hit.t = -1.0f;
      363    hit.index = -1;
      364
      365 -  RTCRay embreeRay;
      366 -  embreeRay.org[0] = ray.origin.x;
      367 -  embreeRay.org[1] = ray.origin.y;
      368 -  embreeRay.org[2] = ray.origin.z;
      365 +  RTCRayHit embreeRayHit;
      366 +  embreeRayHit.ray.org_x = ray.origin.x;
      367 +  embreeRayHit.ray.org_y = ray.origin.y;
      368 +  embreeRayHit.ray.org_z = ray.origin.z;
      369
      370 -  embreeRay.dir[0] = ray.direction.x;
      371 -  embreeRay.dir[1] = ray.direction.y;
      372 -  embreeRay.dir[2] = ray.direction.z;
      370 +  embreeRayHit.ray.dir_x = ray.direction.x;
      371 +  embreeRayHit.ray.dir_y = ray.direction.y;
      372 +  embreeRayHit.ray.dir_z = ray.direction.z;
      373
      374 -  embreeRay.tnear = 0.0f;
      375 -  embreeRay.tfar = FLT_MAX;
      374 +  embreeRayHit.ray.tnear = 0.0f;
      375 +  embreeRayHit.ray.tfar = FLT_MAX;
      376 +  embreeRayHit.ray.mask = -1;
      377 +  embreeRayHit.ray.time = 0;
      378
      377 -  embreeRay.geomID = RTC_INVALID_GEOMETRY_ID;
      378 -  embreeRay.primID = RTC_INVALID_GEOMETRY_ID;
      379 -  embreeRay.mask = -1;
      380 -  embreeRay.time = 0;
      379 +  embreeRayHit.hit.geomID = RTC_INVALID_GEOMETRY_ID;
      380
      382 -  static RTCIntersectContext context = {RTC_INTERSECT_INCOHERENT, nullptr};
      381 +  rtcIntersect1(embreeScene, &embreeRayHit, nullptr);
      382
      384 -  rtcIntersect1M(embreeScene,&context,&embreeRay,1,0);
      385 -
      386 -  if(embreeRay.geomID != RTC_INVALID_GEOMETRY_ID)
      383 +  if(embreeRayHit.hit.geomID != RTC_INVALID_GEOMETRY_ID)
      384    {
      388 -    hit.t = embreeRay.tfar;
      389 -    hit.index = embreeRay.primID;
      390 -    hit.u = embreeRay.u;
      391 -    hit.v = embreeRay.v;
      385 +    hit.t = embreeRayHit.ray.tfar;
      386 +    hit.index = embreeRayHit.hit.primID;
      387 +    hit.u = embreeRayHit.hit.u;
      388 +    hit.v = embreeRayHit.hit.v;
      389    }
      390    return hit;
      391  }
  ⎿  Found 10 new diagnostic issues in 1 file (ctrl+o to expand)

● Now update the raycastStream method:

● Update(Incarnate/src/Accelerator.cpp)
  ⎿  Added 18 lines, removed 25 lines
      392
      393  void EmbreeAccelerator::raycastStream(const Ray* rays, RayHit* hits, int num)
      394  {
      395 -  RTCRay* embreeRays = new RTCRay[num];
      395    for(int i=0;i<num;i++)
      396    {
      398 -    RTCRay &embreeRay = embreeRays[i];
      399 -    embreeRay.org[0] = rays[i].origin.x;
      400 -    embreeRay.org[1] = rays[i].origin.y;
      401 -    embreeRay.org[2] = rays[i].origin.z;
      397 +    RTCRayHit embreeRayHit;
      398 +    embreeRayHit.ray.org_x = rays[i].origin.x;
      399 +    embreeRayHit.ray.org_y = rays[i].origin.y;
      400 +    embreeRayHit.ray.org_z = rays[i].origin.z;
      401
      403 -    embreeRay.dir[0] = rays[i].direction.x;
      404 -    embreeRay.dir[1] = rays[i].direction.y;
      405 -    embreeRay.dir[2] = rays[i].direction.z;
      402 +    embreeRayHit.ray.dir_x = rays[i].direction.x;
      403 +    embreeRayHit.ray.dir_y = rays[i].direction.y;
      404 +    embreeRayHit.ray.dir_z = rays[i].direction.z;
      405
      407 -    embreeRay.tnear = 0.0f;
      408 -    embreeRay.tfar = FLT_MAX;
      406 +    embreeRayHit.ray.tnear = 0.0f;
      407 +    embreeRayHit.ray.tfar = FLT_MAX;
      408 +    embreeRayHit.ray.mask = -1;
      409 +    embreeRayHit.ray.time = 0;
      410
      410 -    embreeRay.geomID = RTC_INVALID_GEOMETRY_ID;
      411 -    embreeRay.primID = RTC_INVALID_GEOMETRY_ID;
      412 -    embreeRay.mask = -1;
      413 -    embreeRay.time = 0;
      414 -  }
      411 +    embreeRayHit.hit.geomID = RTC_INVALID_GEOMETRY_ID;
      412
      416 -  const RTCIntersectContext context = {RTC_INTERSECT_INCOHERENT, nullptr};
      417 -  rtcIntersect1M(embreeScene,&context,embreeRays,num,sizeof(RTCRay));
      413 +    rtcIntersect1(embreeScene, &embreeRayHit, nullptr);
      414
      419 -  for(int i=0;i<num;i++)
      420 -  {
      421 -    if(embreeRays[i].geomID != RTC_INVALID_GEOMETRY_ID)
      415 +    if(embreeRayHit.hit.geomID != RTC_INVALID_GEOMETRY_ID)
      416      {
      423 -      hits[i].t = embreeRays[i].tfar;
      424 -      hits[i].index = embreeRays[i].primID;
      425 -      hits[i].u = embreeRays[i].u;
      426 -      hits[i].v = embreeRays[i].v;
      417 +      hits[i].t = embreeRayHit.ray.tfar;
      418 +      hits[i].index = embreeRayHit.hit.primID;
      419 +      hits[i].u = embreeRayHit.hit.u;
      420 +      hits[i].v = embreeRayHit.hit.v;
      421      }
      422      else
      423      {
     ...
      425        hits[i].index = -1;
      426      }
      427    }
      434 -  delete [] embreeRays;
      428  }
      429
      430  #endif
  ⎿  Found 1 new diagnostic issue in 1 file (ctrl+o to expand)

● All changes are complete. Here's a summary of what was updated:

  Incarnate/include/Accelerator.hpp

  - Changed #include <embree2/rtcore.h> + #include <embree2/rtcore_ray.h> → #include <embree4/rtcore.h>

  Incarnate/src/Accelerator.cpp

  Constructor:
  - rtcDeviceNewScene(device, flags, aflags) → rtcNewScene(device) + rtcSetSceneFlags() + rtcSetSceneBuildQuality(RTC_BUILD_QUALITY_HIGH)

  Destructor:
  - rtcDeleteScene / rtcDeleteDevice → rtcReleaseScene / rtcReleaseDevice

  build():
  - rtcNewTriangleMesh() → rtcNewGeometry(device, RTC_GEOMETRY_TYPE_TRIANGLE)
  - rtcMapBuffer/rtcUnmapBuffer → rtcSetNewGeometryBuffer() for both vertex and index buffers
  - Added rtcCommitGeometry() + rtcAttachGeometry() + rtcReleaseGeometry() workflow
  - rtcCommit() → rtcCommitScene()

  raycast():
  - RTCRay (unified struct) → RTCRayHit with .ray and .hit sub-structs
  - Field access: org[0] → org_x, dir[0] → dir_x, etc.
  - geomID/primID/u/v moved from ray to hit sub-struct
  - rtcIntersect1M() with context → rtcIntersect1() with nullptr args

  raycastStream():
  - Same struct/field changes as raycast()
  - rtcIntersect1M() batch call → loop of rtcIntersect1() calls (stream API was removed in Embree 4)
  - Eliminated dynamic allocation of ray array

  Incarnate/CMakeLists.txt

  - Link target: embree → embree4

The AI spent 5 minues. And it works. First try.

Let me be blunt. Fuck. Fuck. Fuck.

The entire hacker culture is built upon the fact that (programmers) hackers are the ultimate group whom makes things happen. Weather corpos or goverments like it or not. Hackers, whom are usually the morally better group has the ultimate power to make things happen. AI completely breaks the dynamics. Now, you can have a very good engineer just USD $100 a month, or less. Compare that to the tens of thousands needed to even train an engineer. This is a great qualizing force. Building software now is cheap. And the skill barrier is so low that everyone can do it. There'll likely very little reason to hire SWEs anymore.

Sure, professionals will have a better time working with AI agents. Claude still runs in loops, goes into the wrong direction and have terrible taste. But these are no longer unfixable problems. You can most likely fix them with mroe training, more compute and more self distillation. The only moat humans have now is really niche domain knowledge and much longer context that we can hold in our minds. But again, these are not totally unfixable provlems. The next archicture after transformers or thinking models, the next training run might just solve it. I work in the sector, I know the speed of improvment. And the gap of AI coordination is not unfixable with more AI just working together. The recent OpenCraw wave demonstrated that.

It is now cheaper for companies to just get AI, build some webapp and go with it. I might me narrow mineded. But the proof the demonstrated.

I hope I am wrong. But right now I don't think I am. Maybe HPC is a field AI never is able to do well. I don't think so. If not time to go into the trades.