d3d12: Try implement mipmap

The mipmap level below 0 are currently wrong, find out why
This commit is contained in:
vlj 2015-06-16 21:38:08 +02:00 committed by Vincent Lejeune
parent d23cf861f1
commit 178d0e0e85
4 changed files with 103 additions and 62 deletions

View file

@ -88,7 +88,7 @@ D3D12_RESOURCE_DESC getBufferResourceDesc(size_t sizeInByte)
}
inline
D3D12_RESOURCE_DESC getTexture2DResourceDesc(size_t width, size_t height, DXGI_FORMAT dxgiFormat)
D3D12_RESOURCE_DESC getTexture2DResourceDesc(size_t width, size_t height, DXGI_FORMAT dxgiFormat, size_t mipmapLevels)
{
D3D12_RESOURCE_DESC result;
result = {};
@ -98,7 +98,7 @@ D3D12_RESOURCE_DESC getTexture2DResourceDesc(size_t width, size_t height, DXGI_F
result.Format = dxgiFormat;
result.DepthOrArraySize = 1;
result.SampleDesc.Count = 1;
result.MipLevels = 1;
result.MipLevels = mipmapLevels;
return result;
}

View file

@ -545,7 +545,7 @@ D3D12GSRender::D3D12GSRender()
m_device->CreateCommittedResource(
&hp,
D3D12_HEAP_FLAG_NONE,
&getTexture2DResourceDesc(2, 2, DXGI_FORMAT_R8G8B8A8_UNORM),
&getTexture2DResourceDesc(2, 2, DXGI_FORMAT_R8G8B8A8_UNORM, 1),
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&m_dummyTexture))
@ -1150,7 +1150,7 @@ void D3D12GSRender::semaphorePGRAPHBackendRelease(u32 offset, u32 value)
{
D3D12_HEAP_PROPERTIES heapProp = {};
heapProp.Type = D3D12_HEAP_TYPE_DEFAULT;
D3D12_RESOURCE_DESC resdesc = getTexture2DResourceDesc(m_surface_clip_w, m_surface_clip_h, DXGI_FORMAT_R8_UNORM);
D3D12_RESOURCE_DESC resdesc = getTexture2DResourceDesc(m_surface_clip_w, m_surface_clip_h, DXGI_FORMAT_R8_UNORM, 1);
resdesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
size_t sizeInByte = m_surface_clip_w * m_surface_clip_h * 2;

View file

@ -180,7 +180,7 @@ ID3D12Resource *RenderTargets::bindAddressAsRenderTargets(ID3D12Device *device,
D3D12_HEAP_PROPERTIES heapProp = {};
heapProp.Type = D3D12_HEAP_TYPE_DEFAULT;
D3D12_RESOURCE_DESC resourceDesc = getTexture2DResourceDesc(width, height, dxgiFormat);
D3D12_RESOURCE_DESC resourceDesc = getTexture2DResourceDesc(width, height, dxgiFormat, 1);
resourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
device->CreateCommittedResource(
@ -235,7 +235,7 @@ ID3D12Resource * RenderTargets::bindAddressAsDepthStencil(ID3D12Device * device,
assert(0);
}
D3D12_RESOURCE_DESC resourceDesc = getTexture2DResourceDesc(width, height, dxgiFormat);
D3D12_RESOURCE_DESC resourceDesc = getTexture2DResourceDesc(width, height, dxgiFormat, 1);
resourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
device->CreateCommittedResource(

View file

@ -136,6 +136,14 @@ D3D12_FILTER getSamplerFilter(u32 minFilter, u32 magFilter)
return D3D12_ENCODE_BASIC_FILTER(min, mag, mip, D3D12_FILTER_REDUCTION_TYPE_STANDARD);
}
struct MipmapLevelInfo
{
size_t offset;
size_t width;
size_t height;
size_t rowPitch;
};
/**
* Create a texture residing in default heap and generate uploads commands in commandList,
* using a temporary texture buffer.
@ -302,7 +310,7 @@ ID3D12Resource *uploadSingleTexture(
size_t rowPitch = powerOf2Align(blockSizeInByte * widthInBlocks, 256);
ID3D12Resource *Texture;
size_t textureSize = rowPitch * heightInBlocks;
size_t textureSize = rowPitch * heightInBlocks * 4; // * 3 for mipmap levels
assert(textureBuffersHeap.canAlloc(textureSize));
size_t heapOffset = textureBuffersHeap.alloc(textureSize);
@ -321,60 +329,85 @@ ID3D12Resource *uploadSingleTexture(
check(Texture->Map(0, nullptr, (void**)&textureData));
// Upload with correct rowpitch
for (unsigned row = 0; row < heightInBlocks; row++)
std::vector<MipmapLevelInfo> mipinfos;
size_t offsetInDst = 0, offsetInSrc = 0;
size_t currentHeight = heightInBlocks, currentWidth = widthInBlocks;
unsigned tmp = texture.GetMipmap();
if (tmp > 1)
printf("here");
for (unsigned mipLevel = 0; mipLevel < texture.GetMipmap(); mipLevel++)
{
switch (format)
MipmapLevelInfo currentMipmapLevelInfo = {};
currentMipmapLevelInfo.offset = offsetInDst;
currentMipmapLevelInfo.height = currentHeight;
currentMipmapLevelInfo.width = currentWidth;
for (unsigned row = 0; row < currentHeight; row++)
{
case CELL_GCM_TEXTURE_A8R8G8B8:
{
if (is_swizzled)
switch (format)
{
u32 *src, *dst;
u32 log2width, log2height;
case CELL_GCM_TEXTURE_A8R8G8B8:
{
currentMipmapLevelInfo.rowPitch = powerOf2Align(currentWidth * blockSizeInByte, 256);
if (is_swizzled)
{
u32 *src, *dst;
u32 log2width, log2height;
src = (u32*)pixels;
dst = (u32*)textureData;
src = (u32*)pixels + offsetInSrc;
dst = (u32*)textureData + offsetInDst;
log2width = (u32)(logf((float)w) / logf(2.f));
log2height = (u32)(logf((float)h) / logf(2.f));
log2width = (u32)(logf((float)currentWidth) / logf(2.f));
log2height = (u32)(logf((float)currentHeight) / logf(2.f));
#pragma omp parallel for
for (int j = 0; j < w; j++)
dst[(row * currentMipmapLevelInfo.rowPitch / 4) + j] = src[LinearToSwizzleAddress(j, row, 0, log2width, log2height, 0)];
}
else
memcpy((char*)textureData + offsetInDst + row * currentMipmapLevelInfo.rowPitch, (char*)pixels + offsetInSrc + row * currentWidth * blockSizeInByte, currentWidth * blockSizeInByte);
break;
}
case CELL_GCM_TEXTURE_A4R4G4B4:
case CELL_GCM_TEXTURE_R5G6B5:
{
currentMipmapLevelInfo.rowPitch = rowPitch;
unsigned short *dst = (unsigned short *)textureData, *src = (unsigned short *)pixels;
#pragma omp parallel for
for (int j = 0; j < w; j++)
dst[(row * rowPitch / 4) + j] = src[LinearToSwizzleAddress(j, row, 0, log2width, log2height, 0)];
{
u16 tmp = src[offsetInSrc / 2 + row * srcPitch / 2 + j];
dst[offsetInDst / 2 + row * rowPitch / 2 + j] = (tmp >> 8) | (tmp << 8);
}
break;
}
else
streamBuffer((char*)textureData + row * rowPitch, (char*)pixels + row * srcPitch, srcPitch);
break;
}
case CELL_GCM_TEXTURE_A4R4G4B4:
case CELL_GCM_TEXTURE_R5G6B5:
{
unsigned short *dst = (unsigned short *)textureData, *src = (unsigned short *)pixels;
for (int j = 0; j < w; j++)
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
{
u16 tmp = src[row * srcPitch / 2 + j];
dst[row * rowPitch / 2 + j] = (tmp >> 8) | (tmp << 8);
}
break;
}
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
{
unsigned short *dst = (unsigned short *)textureData, *src = (unsigned short *)pixels;
currentMipmapLevelInfo.rowPitch = rowPitch;
unsigned short *dst = (unsigned short *)textureData, *src = (unsigned short *)pixels;
for (int j = 0; j < w * 4; j++)
{
unsigned short tmp = src[row * w * 4 + j];
dst[row * w * 4 + j] = (tmp >> 8) | (tmp << 8);
for (int j = 0; j < w * 4; j++)
{
unsigned short tmp = src[offsetInSrc / 2 + row * w * 4 + j];
dst[offsetInDst / 2 + row * w * 4 + j] = (tmp >> 8) | (tmp << 8);
}
break;
}
default:
{
currentMipmapLevelInfo.rowPitch = rowPitch;
streamBuffer((char*)textureData + offsetInDst + row * rowPitch, (char*)pixels + offsetInSrc + row * srcPitch, srcPitch);
break;
}
}
break;
}
default:
{
streamBuffer((char*)textureData + row * rowPitch, (char*)pixels + row * srcPitch, srcPitch);
break;
}
}
offsetInDst += currentHeight * currentMipmapLevelInfo.rowPitch;
offsetInDst = powerOf2Align(offsetInDst, 256);
offsetInSrc += currentHeight * currentWidth * blockSizeInByte;
mipinfos.push_back(currentMipmapLevelInfo);
currentHeight /= 2;
currentWidth /= 2;
}
Texture->Unmap(0, nullptr);
@ -387,25 +420,33 @@ ID3D12Resource *uploadSingleTexture(
check(device->CreatePlacedResource(
textureHeap.m_heap,
heapOffset2,
&getTexture2DResourceDesc(w, h, dxgiFormat),
&getTexture2DResourceDesc(w, h, dxgiFormat, texture.GetMipmap()),
D3D12_RESOURCE_STATE_COPY_DEST,
nullptr,
IID_PPV_ARGS(&vramTexture)
));
textureHeap.m_resourceStoredSinceLastSync.push_back(std::make_tuple(heapOffset2, textureSize, vramTexture));
D3D12_TEXTURE_COPY_LOCATION dst = {}, src = {};
dst.pResource = vramTexture;
dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
src.pResource = Texture;
src.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
src.PlacedFootprint.Footprint.Depth = 1;
src.PlacedFootprint.Footprint.Width = (UINT)w;
src.PlacedFootprint.Footprint.Height = (UINT)h;
src.PlacedFootprint.Footprint.RowPitch = (UINT)rowPitch;
src.PlacedFootprint.Footprint.Format = dxgiFormat;
commandList->CopyTextureRegion(&dst, 0, 0, 0, &src, nullptr);
size_t miplevel = 0;
for (const MipmapLevelInfo mli : mipinfos)
{
D3D12_TEXTURE_COPY_LOCATION dst = {}, src = {};
dst.pResource = vramTexture;
dst.SubresourceIndex = miplevel;
dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
src.PlacedFootprint.Offset = mli.offset;
src.pResource = Texture;
src.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
src.PlacedFootprint.Footprint.Depth = 1;
src.PlacedFootprint.Footprint.Width = (UINT)mli.width;
src.PlacedFootprint.Footprint.Height = (UINT)mli.height;
src.PlacedFootprint.Footprint.RowPitch = (UINT)mli.rowPitch;
src.PlacedFootprint.Footprint.Format = dxgiFormat;
commandList->CopyTextureRegion(&dst, 0, 0, 0, &src, nullptr);
miplevel++;
}
D3D12_RESOURCE_BARRIER barrier = {};
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
@ -461,7 +502,7 @@ size_t D3D12GSRender::UploadTextures()
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
srvDesc.Format = dxgiFormat;
srvDesc.Texture2D.MipLevels = 1;
srvDesc.Texture2D.MipLevels = m_textures[i].GetMipmap();
switch (format)
{