// Geometry-confirmed short-lived color history for locally separated thin silhouettes. #include "../../tools/d4r_wire_history.h" #pragma clang fp contract(off) #define WH_SYNC() do { __builtin_amdgcn_fence(__ATOMIC_RELEASE,"workgroup"); __builtin_amdgcn_s_barrier(); __builtin_amdgcn_fence(__ATOMIC_ACQUIRE,"workgroup"); } while(0) __attribute__((device,always_inline)) static inline int wh_clamp(int v,int lo,int hi) { return vhi ? hi : v; } __attribute__((device,always_inline)) static inline float wh_depth(const D4rWireHistoryParams& p,int x,int y) { x=wh_clamp(x,0,p.width-1);y=wh_clamp(y,0,p.height-1);return *(const float*)(p.native_depth+(uint64_t)y*p.depth_pitch+4*x); } template __attribute__((device,always_inline)) static inline bool wh_thin_axis(const D4rWireHistoryParams& p,int x,int y,int axis,Depth depth) { float center=depth(x,y);if(!(center>=0 && center<.99999f)) return false; if((p.reserved & D4R_WIRE_HISTORY_SKY_ONLY) && (!(depth(x-4*(axis==0),y-4*(axis==1))>=.99999f) || !(depth(x+4*(axis==0),y+4*(axis==1))>=.99999f))) return false; float epsilon=.25f*(1-center);if(epsilon<2e-6f) epsilon=2e-6f; float limit=center+epsilon; int run=1; for(int sign=-1;sign<=1;sign+=2) for(int step=1;step<5 && run<5;step++) { int tx=x+(axis==0 ? sign*step : 0),ty=y+(axis==1 ? sign*step : 0); if(tx<0 || ty<0 || tx>=(int)p.width || ty>=(int)p.height || !(depth(tx,ty)=5) return false; float gap=.5f*(1-center);if(gap<2e-6f) gap=2e-6f; bool sides[2]={false,false}; for(int sign=-1;sign<=1;sign+=2) for(int step=1;step<=4;step++) sides[(sign+1)/2]|=depth(x+sign*step*(axis==0),y+sign*step*(axis==1))>center+gap; return sides[0] && sides[1]; } // Interior specialization: fixed eight depth loads, bit scans for the first // non-near neighbour on each side, and the original strict separation test. // Edge samples keep the bounds-aware reference above. template __attribute__((device,always_inline)) static inline bool wh_thin_interior(const D4rWireHistoryParams& p,int x,int y,int axis,Depth depth) { if(x<4 || y<4 || x>=(int)p.width-4 || y>=(int)p.height-4) return wh_thin_axis(p,x,y,axis,depth); const float center=depth(x,y); if(!(center>=0 && center<.99999f)) return false; if((p.reserved & D4R_WIRE_HISTORY_SKY_ONLY) && (!(depth(x-4*(axis==0),y-4*(axis==1))>=.99999f) || !(depth(x+4*(axis==0),y+4*(axis==1))>=.99999f))) return false; float epsilon=.25f*(1-center);if(epsilon<2e-6f) epsilon=2e-6f; float gap=.5f*(1-center);if(gap<2e-6f) gap=2e-6f; const float limit=center+epsilon,far_limit=center+gap; unsigned negative=0,positive=0; bool far_negative=false,far_positive=false; #pragma unroll for(int step=1;step<=4;step++) { const float n=depth(x-(axis==0 ? step : 0),y-(axis==1 ? step : 0)); negative|=(unsigned)(!(nfar_limit; } // Four contiguous near neighbours already prove a run of at least five. // No positive-side depths or separation checks can make it thin. if(!negative) return false; #pragma unroll for(int step=1;step<=4;step++) { const float v=depth(x+(axis==0 ? step : 0),y+(axis==1 ? step : 0)); positive|=(unsigned)(!(vfar_limit; } if(!positive) return false; return __builtin_ctz(negative|16)+__builtin_ctz(positive|16)<4 && far_negative && far_positive; } __attribute__((device,always_inline)) static inline float wh_luma(uint64_t rgb,uint64_t pitch,int x,int y) { const _Float16* c=(const _Float16*)(rgb+(uint64_t)y*pitch+8*x); float l=(float)c[0]*.2126f+(float)c[1]*.7152f+(float)c[2]*.0722f; return l>1e-5f ? l : 1e-5f; } // Median in log space is the geometric mean of the two central luminances. __attribute__((device,always_inline)) static inline float wh_background(uint64_t rgb,uint64_t pitch,int x,int y,int ax,int ay,bool input) { float v[6];int count=input ? 4 : 6; const int offsets[6]={-12,-10,-8,8,10,12}; const int small[4]={-5,-4,4,5}; for(int i=0;i0 && v[j] __attribute__((device,always_inline)) static inline void wh_run(D4rWireHistoryParams p,uint64_t patch_mask,uint64_t prepared_axes=0) { uint32_t t=__builtin_amdgcn_workitem_id_x(); int x=__builtin_amdgcn_workgroup_id_x()*16+(t&15),y=__builtin_amdgcn_workgroup_id_y()*16+(t>>4); // Classify each nearby depth texel once, shared by the four bilinear samples // of adjacent output pixels. All lanes reach both barriers, including partial tiles. constexpr int span=26,margin=5; __attribute__((shared)) float tile[span*span]; __attribute__((shared)) uint8_t axes[span*span]; const int ox=(int)__builtin_amdgcn_workgroup_id_x()*16+(int)__builtin_floorf(p.jitter_x*p.width/p.render_width)-margin; const int oy=(int)__builtin_amdgcn_workgroup_id_y()*16+(int)__builtin_floorf(p.jitter_y*p.height/p.render_height)-margin; if constexpr(!CachedAxes) { for(int i=t;ifloat { int lx=tx-ox,ly=ty-oy; return (unsigned)lxfloat { return tile[(ty-oy)*span+tx-ox]; }; if constexpr(!CachedAxes) { for(int i=t;i=4 && lx=4 && lyuint8_t { if constexpr(CachedAxes) return *(const uint8_t*)(prepared_axes+(uint64_t)ty*p.width+tx); else { int lx=tx-ox,ly=ty-oy; if(lx>=4 && lx=4 && ly=(int)p.width || y>=(int)p.height) return; uint64_t offset=(uint64_t)y*p.output_pitch+8*x,index=(uint64_t)y*p.width+x; if constexpr(Sparse) *(uint8_t*)(patch_mask+index)=0; else *(uint64_t*)(p.output+offset)=*(const uint64_t*)(p.current+offset); // Age 255 makes this entry unreadable by the next frame. The prepared // path need not copy raw RGB or initialize depth for an unobserved entry. if constexpr(!CachedAxes) *(uint64_t*)(p.output_history+offset)=*(const uint64_t*)(p.current+offset); *(uint8_t*)(p.output_age+index)=255; if constexpr(!CachedAxes) *(float*)(p.output_depth+4*index)=1.f; if(x<16 || y<16 || x>=(int)p.width-16 || y>=(int)p.height-16) return; float nx=x+p.jitter_x*p.width/p.render_width,ny=y+p.jitter_y*p.height/p.render_height; int fx=(int)__builtin_floorf(nx),fy=(int)__builtin_floorf(ny),sx=0,sy=0; float coverage=0,best_weight=-1; for(int dy=0;dy<=1;dy++) for(int dx=0;dx<=1;dx++) { int tx=wh_clamp(fx+dx,0,p.width-1),ty=wh_clamp(fy+dy,0,p.height-1); if(!thin_axes(tx,ty)) continue; float weight=(1-__builtin_fabsf(nx-tx))*(1-__builtin_fabsf(ny-ty));coverage+=weight; if(weight>best_weight) { best_weight=weight;sx=tx;sy=ty; } } if(coverage<=.05f) return; int ay=(thin_axes(sx,sy)&2) ? 1 : 0,ax=1-ay; const bool conservative=(p.reserved & D4R_WIRE_HISTORY_CONSERVATIVE)!=0; const int radius=conservative ? 1 : 2,age_limit=conservative ? 4 : 16; float current_z=wh_depth(p,sx,sy); float tolerance=(conservative ? .01f : .02f)*(1-current_z); const float depth_floor=conservative ? 2e-7f : 2e-6f; if(tolerance=.99999f) && !(__builtin_fabsf(nearest_z-current_z)=16 && py>=16 && px=age_limit) continue; float previous_z=*(const float*)(p.previous_depth+4*previous_index),limit=(conservative ? .01f : .05f)*(1-current_z);if(limitthreshold) || (ratio>1.189207115f && current1) coverage=1; const _Float16* observed=(const _Float16*)target; const _Float16* now=(_Float16*)(p.current+offset);_Float16* out=(_Float16*)(p.output+offset); for(int c=0;c<3;c++) { float result=(float)now[c]*(1-coverage)+(float)observed[c]*coverage; if(result<0) result=0;if(result>65504) result=65504;out[c]=(_Float16)result; } } extern "C" __attribute__((global, amdgpu_flat_work_group_size(256,256))) void d4r_wire_history(D4rWireHistoryParams p) { wh_run(p,0); } extern "C" __attribute__((global, amdgpu_flat_work_group_size(256,256))) void d4r_wire_history_sparse(D4rWireHistorySparseParams p) { wh_run(p.base,p.patch_mask); } extern "C" __attribute__((global, amdgpu_flat_work_group_size(256,256))) void d4r_wire_history_apply(D4rWireHistorySparseParams p) { const unsigned t=__builtin_amdgcn_workitem_id_x(); const unsigned x=__builtin_amdgcn_workgroup_id_x()*16+(t&15),y=__builtin_amdgcn_workgroup_id_y()*16+(t>>4); if(x>=p.base.width || y>=p.base.height || !*(const uint8_t*)(p.patch_mask+(uint64_t)y*p.base.width+x)) return; const uint64_t offset=(uint64_t)y*p.base.output_pitch+8*x; *(uint64_t*)(p.base.current+offset)=*(const uint64_t*)(p.base.output+offset); } #undef WH_SYNC extern "C" __attribute__((global,amdgpu_flat_work_group_size(256,256))) void d4r_wire_history_preclassified(D4rWireHistoryPreparedParams p) { wh_run(p.sparse.base,p.sparse.patch_mask,p.axes); }