Skip to content

Instantly share code, notes, and snippets.

@yorung
Last active August 21, 2016 12:31
Show Gist options
  • Save yorung/9d900576c48464d4dc93b4252bc198c5 to your computer and use it in GitHub Desktop.
Save yorung/9d900576c48464d4dc93b4252bc198c5 to your computer and use it in GitHub Desktop.
[DX12] Create texture from dds files.
struct DDSHeader {
uint32_t h3[3];
int h, w;
uint32_t h2[2];
int mipCnt;
uint32_t h13[13];
uint32_t fourcc, bitsPerPixel, rMask, gMask, bMask, aMask, caps1, caps2;
bool IsCubeMap() const { return caps2 == 0xFE00; }
int GetArraySize() const { return IsCubeMap() ? 6 : 1; }
int GetMipCnt() const { return std::max(mipCnt, 1); }
};
struct TexDesc {
IVec2 size;
int arraySize = 1;
bool isCubeMap = false;
};
struct AFTexSubresourceData
{
const void* ptr;
uint32_t pitch;
uint32_t pitchSlice;
};
static ComPtr<ID3D12Resource> LoadDDSTexture(const char* name, TexDesc& texDesc)
{
int size;
void* img = LoadFile(name, &size);
if (!img) {
aflog("LoadDDSTexture failed! %s", name);
return nullptr;
}
const DDSHeader* hdr = (DDSHeader*)img;
AFDTFormat format = AFDT_INVALID;
int(*pitchCalcurator)(int, int) = nullptr;
switch (hdr->fourcc) {
case 0x31545844: //'1TXD':
format = AFDT_BC1_UNORM;
pitchCalcurator = [](int w, int h) { return ((w + 3) / 4) * ((h + 3) / 4) * 8; };
break;
case 0x33545844: //'3TXD':
format = AFDT_BC2_UNORM;
pitchCalcurator = [](int w, int h) { return ((w + 3) / 4) * ((h + 3) / 4) * 16; };
break;
case 0x35545844: //'5TXD':
format = AFDT_BC3_UNORM;
pitchCalcurator = [](int w, int h) { return ((w + 3) / 4) * ((h + 3) / 4) * 16; };
break;
default:
ArrangeRawDDS(img, size);
format = AFDT_R8G8B8A8_UNORM;
pitchCalcurator = [](int w, int h) { return w * h * 4; };
break;
}
texDesc.size.x = hdr->w;
texDesc.size.y = hdr->h;
texDesc.arraySize = hdr->GetArraySize();
texDesc.isCubeMap = hdr->IsCubeMap();
int arraySize = hdr->GetArraySize();
int mipCnt = hdr->GetMipCnt();
std::vector<AFTexSubresourceData> r;
int offset = 128;
for (int a = 0; a < arraySize; a++) {
for (int m = 0; m < mipCnt; m++) {
int w = std::max(1, hdr->w >> m);
int h = std::max(1, hdr->h >> m);
int size = pitchCalcurator(w, h);
r.push_back({ (char*)img + offset, (uint32_t)pitchCalcurator(w, 1), (uint32_t)size });
offset += size;
}
}
ComPtr<ID3D12Resource> tex = afCreateTexture2D(format, texDesc, mipCnt, &r[0]);
assert(tex);
free(img);
return tex;
}
static const D3D12_HEAP_PROPERTIES defaultHeapProperties = { D3D12_HEAP_TYPE_DEFAULT, D3D12_CPU_PAGE_PROPERTY_UNKNOWN, D3D12_MEMORY_POOL_UNKNOWN, 1, 1 };
ComPtr<ID3D12Resource> afCreateTexture2D(AFDTFormat format, const struct TexDesc& desc, int mipCount, const AFTexSubresourceData datas[])
{
D3D12_RESOURCE_DESC resourceDesc = { D3D12_RESOURCE_DIMENSION_TEXTURE2D, 0, (UINT64)desc.size.x, (UINT)desc.size.y, (UINT16)desc.arraySize, (UINT16)mipCount, format, {1, 0} };
ComPtr<ID3D12Resource> tex;
HRESULT hr = deviceMan.GetDevice()->CreateCommittedResource(&defaultHeapProperties, D3D12_HEAP_FLAG_NONE, &resourceDesc, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, nullptr, IID_PPV_ARGS(&tex));
afWriteTexture(tex, desc, mipCount, datas);
return tex;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment