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 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; D3D12_RESOURCE_DESC result;
result = {}; result = {};
@ -98,7 +98,7 @@ D3D12_RESOURCE_DESC getTexture2DResourceDesc(size_t width, size_t height, DXGI_F
result.Format = dxgiFormat; result.Format = dxgiFormat;
result.DepthOrArraySize = 1; result.DepthOrArraySize = 1;
result.SampleDesc.Count = 1; result.SampleDesc.Count = 1;
result.MipLevels = 1; result.MipLevels = mipmapLevels;
return result; return result;
} }

View file

@ -545,7 +545,7 @@ D3D12GSRender::D3D12GSRender()
m_device->CreateCommittedResource( m_device->CreateCommittedResource(
&hp, &hp,
D3D12_HEAP_FLAG_NONE, D3D12_HEAP_FLAG_NONE,
&getTexture2DResourceDesc(2, 2, DXGI_FORMAT_R8G8B8A8_UNORM), &getTexture2DResourceDesc(2, 2, DXGI_FORMAT_R8G8B8A8_UNORM, 1),
D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr, nullptr,
IID_PPV_ARGS(&m_dummyTexture)) IID_PPV_ARGS(&m_dummyTexture))
@ -1150,7 +1150,7 @@ void D3D12GSRender::semaphorePGRAPHBackendRelease(u32 offset, u32 value)
{ {
D3D12_HEAP_PROPERTIES heapProp = {}; D3D12_HEAP_PROPERTIES heapProp = {};
heapProp.Type = D3D12_HEAP_TYPE_DEFAULT; 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; resdesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
size_t sizeInByte = m_surface_clip_w * m_surface_clip_h * 2; 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 = {}; D3D12_HEAP_PROPERTIES heapProp = {};
heapProp.Type = D3D12_HEAP_TYPE_DEFAULT; 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; resourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
device->CreateCommittedResource( device->CreateCommittedResource(
@ -235,7 +235,7 @@ ID3D12Resource * RenderTargets::bindAddressAsDepthStencil(ID3D12Device * device,
assert(0); 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; resourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
device->CreateCommittedResource( 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); 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, * Create a texture residing in default heap and generate uploads commands in commandList,
* using a temporary texture buffer. * using a temporary texture buffer.
@ -302,7 +310,7 @@ ID3D12Resource *uploadSingleTexture(
size_t rowPitch = powerOf2Align(blockSizeInByte * widthInBlocks, 256); size_t rowPitch = powerOf2Align(blockSizeInByte * widthInBlocks, 256);
ID3D12Resource *Texture; ID3D12Resource *Texture;
size_t textureSize = rowPitch * heightInBlocks; size_t textureSize = rowPitch * heightInBlocks * 4; // * 3 for mipmap levels
assert(textureBuffersHeap.canAlloc(textureSize)); assert(textureBuffersHeap.canAlloc(textureSize));
size_t heapOffset = textureBuffersHeap.alloc(textureSize); size_t heapOffset = textureBuffersHeap.alloc(textureSize);
@ -321,61 +329,86 @@ ID3D12Resource *uploadSingleTexture(
check(Texture->Map(0, nullptr, (void**)&textureData)); check(Texture->Map(0, nullptr, (void**)&textureData));
// Upload with correct rowpitch // 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++)
{
MipmapLevelInfo currentMipmapLevelInfo = {};
currentMipmapLevelInfo.offset = offsetInDst;
currentMipmapLevelInfo.height = currentHeight;
currentMipmapLevelInfo.width = currentWidth;
for (unsigned row = 0; row < currentHeight; row++)
{ {
switch (format) switch (format)
{ {
case CELL_GCM_TEXTURE_A8R8G8B8: case CELL_GCM_TEXTURE_A8R8G8B8:
{ {
currentMipmapLevelInfo.rowPitch = powerOf2Align(currentWidth * blockSizeInByte, 256);
if (is_swizzled) if (is_swizzled)
{ {
u32 *src, *dst; u32 *src, *dst;
u32 log2width, log2height; u32 log2width, log2height;
src = (u32*)pixels; src = (u32*)pixels + offsetInSrc;
dst = (u32*)textureData; dst = (u32*)textureData + offsetInDst;
log2width = (u32)(logf((float)w) / logf(2.f)); log2width = (u32)(logf((float)currentWidth) / logf(2.f));
log2height = (u32)(logf((float)h) / logf(2.f)); log2height = (u32)(logf((float)currentHeight) / logf(2.f));
#pragma omp parallel for #pragma omp parallel for
for (int j = 0; j < w; j++) for (int j = 0; j < w; j++)
dst[(row * rowPitch / 4) + j] = src[LinearToSwizzleAddress(j, row, 0, log2width, log2height, 0)]; dst[(row * currentMipmapLevelInfo.rowPitch / 4) + j] = src[LinearToSwizzleAddress(j, row, 0, log2width, log2height, 0)];
} }
else else
streamBuffer((char*)textureData + row * rowPitch, (char*)pixels + row * srcPitch, srcPitch); memcpy((char*)textureData + offsetInDst + row * currentMipmapLevelInfo.rowPitch, (char*)pixels + offsetInSrc + row * currentWidth * blockSizeInByte, currentWidth * blockSizeInByte);
break; break;
} }
case CELL_GCM_TEXTURE_A4R4G4B4: case CELL_GCM_TEXTURE_A4R4G4B4:
case CELL_GCM_TEXTURE_R5G6B5: case CELL_GCM_TEXTURE_R5G6B5:
{ {
currentMipmapLevelInfo.rowPitch = rowPitch;
unsigned short *dst = (unsigned short *)textureData, *src = (unsigned short *)pixels; unsigned short *dst = (unsigned short *)textureData, *src = (unsigned short *)pixels;
for (int j = 0; j < w; j++) for (int j = 0; j < w; j++)
{ {
u16 tmp = src[row * srcPitch / 2 + j]; u16 tmp = src[offsetInSrc / 2 + row * srcPitch / 2 + j];
dst[row * rowPitch / 2 + j] = (tmp >> 8) | (tmp << 8); dst[offsetInDst / 2 + row * rowPitch / 2 + j] = (tmp >> 8) | (tmp << 8);
} }
break; break;
} }
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT: case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
{ {
currentMipmapLevelInfo.rowPitch = rowPitch;
unsigned short *dst = (unsigned short *)textureData, *src = (unsigned short *)pixels; unsigned short *dst = (unsigned short *)textureData, *src = (unsigned short *)pixels;
for (int j = 0; j < w * 4; j++) for (int j = 0; j < w * 4; j++)
{ {
unsigned short tmp = src[row * w * 4 + j]; unsigned short tmp = src[offsetInSrc / 2 + row * w * 4 + j];
dst[row * w * 4 + j] = (tmp >> 8) | (tmp << 8); dst[offsetInDst / 2 + row * w * 4 + j] = (tmp >> 8) | (tmp << 8);
} }
break; break;
} }
default: default:
{ {
streamBuffer((char*)textureData + row * rowPitch, (char*)pixels + row * srcPitch, srcPitch); currentMipmapLevelInfo.rowPitch = rowPitch;
streamBuffer((char*)textureData + offsetInDst + row * rowPitch, (char*)pixels + offsetInSrc + row * srcPitch, srcPitch);
break; 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); Texture->Unmap(0, nullptr);
size_t powerOf2Height = (size_t)log2f((float)heightInBlocks) + 1; size_t powerOf2Height = (size_t)log2f((float)heightInBlocks) + 1;
@ -387,25 +420,33 @@ ID3D12Resource *uploadSingleTexture(
check(device->CreatePlacedResource( check(device->CreatePlacedResource(
textureHeap.m_heap, textureHeap.m_heap,
heapOffset2, heapOffset2,
&getTexture2DResourceDesc(w, h, dxgiFormat), &getTexture2DResourceDesc(w, h, dxgiFormat, texture.GetMipmap()),
D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COPY_DEST,
nullptr, nullptr,
IID_PPV_ARGS(&vramTexture) IID_PPV_ARGS(&vramTexture)
)); ));
textureHeap.m_resourceStoredSinceLastSync.push_back(std::make_tuple(heapOffset2, textureSize, vramTexture)); textureHeap.m_resourceStoredSinceLastSync.push_back(std::make_tuple(heapOffset2, textureSize, vramTexture));
size_t miplevel = 0;
for (const MipmapLevelInfo mli : mipinfos)
{
D3D12_TEXTURE_COPY_LOCATION dst = {}, src = {}; D3D12_TEXTURE_COPY_LOCATION dst = {}, src = {};
dst.pResource = vramTexture; dst.pResource = vramTexture;
dst.SubresourceIndex = miplevel;
dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
src.PlacedFootprint.Offset = mli.offset;
src.pResource = Texture; src.pResource = Texture;
src.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; src.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
src.PlacedFootprint.Footprint.Depth = 1; src.PlacedFootprint.Footprint.Depth = 1;
src.PlacedFootprint.Footprint.Width = (UINT)w; src.PlacedFootprint.Footprint.Width = (UINT)mli.width;
src.PlacedFootprint.Footprint.Height = (UINT)h; src.PlacedFootprint.Footprint.Height = (UINT)mli.height;
src.PlacedFootprint.Footprint.RowPitch = (UINT)rowPitch; src.PlacedFootprint.Footprint.RowPitch = (UINT)mli.rowPitch;
src.PlacedFootprint.Footprint.Format = dxgiFormat; src.PlacedFootprint.Footprint.Format = dxgiFormat;
commandList->CopyTextureRegion(&dst, 0, 0, 0, &src, nullptr); commandList->CopyTextureRegion(&dst, 0, 0, 0, &src, nullptr);
miplevel++;
}
D3D12_RESOURCE_BARRIER barrier = {}; D3D12_RESOURCE_BARRIER barrier = {};
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
@ -461,7 +502,7 @@ size_t D3D12GSRender::UploadTextures()
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
srvDesc.Format = dxgiFormat; srvDesc.Format = dxgiFormat;
srvDesc.Texture2D.MipLevels = 1; srvDesc.Texture2D.MipLevels = m_textures[i].GetMipmap();
switch (format) switch (format)
{ {