2014-02-09 55 views
1

我正在使用函數在CPU上生成mip映射。 我的目標是編寫適用於多種DXGI_FORMAT的通用函數。函數對所有DXGI_FORMAT組合進行相同的操作,唯一不同的是數據類型和XMMATH函數來加載和存儲它。定義使用此類型作爲模板參數的類型和功能

我嘗試很好的方式做到了 - 通過模板參數,像:

#define AVERAGE(p, q) (((p - q) * 0.5f) + q) 

template<typename XMATH_PIXEL_FORMAT, 
     typename XMVECTOR(*XMATH_LOAD_FUNC)(const XMATH_PIXEL_FORMAT*), 
     typename void(*XMATH_STORE_FUNC)(XMATH_PIXEL_FORMAT*, XMVECTOR)> 
void minifyMipMap(XMATH_PIXEL_FORMAT* dst, const XMATH_PIXEL_FORMAT* src, size_t src_x, size_t src_y) { 
    size_t x, y, x2, y2, dst_x = src_x >> 1, dst_y = src_y >> 1; 
    XMVECTOR out, p00, p10, p01, p11; // p:xy 

    for(y = 0; y < dst_y; ++y) { // for each dst line 
    y2 = y << 1; // y2 = y * 2 
    for(x = 0; x < dst_x; ++x) { // for each dst pixel 
     x2 = x << 1; // x2 = x * 2 

     // load 4 pixels 
     p00 = XMATH_LOAD_FUNC(src + y2 * src_x + x2); 
     p10 = XMATH_LOAD_FUNC(src + y2 * src_x + x2 + 1); 
     p01 = XMATH_LOAD_FUNC(src + (y2 + 1) * src_x + x2); 
     p11 = XMATH_LOAD_FUNC(src + (y2 + 1) * src_x + x2 + 1); 

     // blend 4 pixels into 1 
     out = AVERAGE(AVERAGE(p00, p10), AVERAGE(p01, p11)); 

     // store dest pixel 
     XMATH_STORE_FUNC(dst + y * dst_x + x, out); 
    } 
    } 
} 


void test() { 
    BYTE src[] = { 
    0, 0, 0, 255, // black 
    255, 255, 255, 255, // white 
    0, 0, 0, 255, // black 
    255, 255, 255, 255 // white 
    }; 
    XMUBYTE4 dst[1]; // gray ??? 

    minifyMipMap<XMUBYTE4, XMLoadUByte4, XMStoreUByte4>(dst, (const XMUBYTE4*)src, 2, 2); // 2x2 = > 1x1 
} 

MSVC說:C2893:無法專注函數模板「無效minifyMipMap(XMATH_PIXEL_FORMAT *,常量XMATH_PIXEL_FORMAT *,爲size_t,爲size_t )」 用下面的模板參數: ‘的DirectX :: PackedVector :: XMUBYTE4’

我試着編譯幾個組合這段代碼,但沒有成功(還我試圖定義類型的類模板和功能的靜態方法參數這個類,但它也失敗了)。 我希望以某種方式在C++中以不錯的方式編寫它 - 不使用#define的

+0

我犯了可怕的錯誤,這並不工作,因爲無效(* XMMATH_STORE_FUNC)(XMATH_PIXEL_FORMAT *,XMVECTOR)應FXMVECTOR在第二個參數 - 不XMVECTOR - 這是虛驚一場:>此模板代碼的工作下MSVC 2012 – crayze

回答

2

如果您想接受任意函數,請不要這樣做。接受每個不同功能的單個模板參數。如果一個函數傳遞不能在你的代碼中調用的方式被稱爲

template<typename Func> 
void foo(Func f) { 
    // call f in any way you need 
    f(); 
} 

// can be used like this with functions 
void bla() {} 
f(&bla); 
// Functors 
struct X { void operator()() {} } 
f(X()); 

編譯器會抱怨。

如果您想對您的用戶真正有幫助,您可以使用static_assert和一些元編程來提供一些有限概念檢查。

+0

感謝回答,現在我經常創建類似這樣的函數類 – crayze