diff --git a/include/boo/graphicsdev/Vulkan.hpp b/include/boo/graphicsdev/Vulkan.hpp index 08dba13..b20a7e1 100644 --- a/include/boo/graphicsdev/Vulkan.hpp +++ b/include/boo/graphicsdev/Vulkan.hpp @@ -119,8 +119,8 @@ public: ITextureS* newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, const void* data, size_t sz); - ITextureSA* newStaticArrayTexture(size_t width, size_t height, size_t layers, TextureFormat fmt, - const void* data, size_t sz); + ITextureSA* newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips, + TextureFormat fmt, const void* data, size_t sz); ITextureD* newDynamicTexture(size_t width, size_t height, TextureFormat fmt); ITextureR* newRenderTexture(size_t width, size_t height, bool enableShaderColorBinding, bool enableShaderDepthBinding); diff --git a/lib/graphicsdev/D3D11.cpp b/lib/graphicsdev/D3D11.cpp index c76eb15..205ff99 100644 --- a/lib/graphicsdev/D3D11.cpp +++ b/lib/graphicsdev/D3D11.cpp @@ -152,8 +152,10 @@ class D3D11TextureS : public ITextureS upData[i].SysMemPitch = width * pxPitchNum / pxPitchDenom; upData[i].SysMemSlicePitch = upData[i].SysMemPitch * height; dataIt += upData[i].SysMemSlicePitch; - width /= 2; - height /= 2; + if (width > 1) + width /= 2; + if (height > 1) + height /= 2; } ThrowIfFailed(ctx->m_dev->CreateTexture2D(&desc, upData, &m_tex)); @@ -172,7 +174,7 @@ class D3D11TextureSA : public ITextureSA size_t m_sz; D3D11TextureSA(D3D11Context* ctx, size_t width, size_t height, size_t layers, - TextureFormat fmt, const void* data, size_t sz) + size_t mips, TextureFormat fmt, const void* data, size_t sz) : m_sz(sz) { size_t pixelPitch; @@ -188,34 +190,28 @@ class D3D11TextureSA : public ITextureSA pixelFmt = DXGI_FORMAT_R8_UNORM; } - CD3D11_TEXTURE2D_DESC desc(pixelFmt, width, height, layers, 1, + CD3D11_TEXTURE2D_DESC desc(pixelFmt, width, height, layers, mips, D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_IMMUTABLE); const uint8_t* dataIt = static_cast(data); - if (layers > 16) + std::unique_ptr upData(new D3D11_SUBRESOURCE_DATA[layers * mips]); + D3D11_SUBRESOURCE_DATA* outIt = upData.get(); + for (size_t i=0 ; i upData(new D3D11_SUBRESOURCE_DATA[layers]); - for (size_t i=0 ; ipSysMem = dataIt; + outIt->SysMemPitch = width * pixelPitch; + outIt->SysMemSlicePitch = outIt->SysMemPitch * height; + dataIt += outIt->SysMemSlicePitch; + ++outIt; } - ThrowIfFailed(ctx->m_dev->CreateTexture2D(&desc, upData.get(), &m_tex)); - } - else - { - D3D11_SUBRESOURCE_DATA upData[16] = {}; - for (size_t i=0 ; im_dev->CreateTexture2D(&desc, upData, &m_tex)); + if (width > 1) + width /= 2; + if (height > 1) + height /= 2; } + ThrowIfFailed(ctx->m_dev->CreateTexture2D(&desc, upData.get(), &m_tex)); ThrowIfFailed(ctx->m_dev->CreateShaderResourceView(m_tex.Get(), &CD3D11_SHADER_RESOURCE_VIEW_DESC(m_tex.Get(), D3D_SRV_DIMENSION_TEXTURE2DARRAY, pixelFmt), &m_srv)); @@ -1218,11 +1214,11 @@ public: return retval; } - ITextureSA* newStaticArrayTexture(size_t width, size_t height, size_t layers, TextureFormat fmt, - const void* data, size_t sz) + ITextureSA* newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips, + TextureFormat fmt, const void* data, size_t sz) { D3D11Data* d = static_cast(m_deferredData); - D3D11TextureSA* retval = new D3D11TextureSA(m_parent.m_ctx, width, height, layers, fmt, data, sz); + D3D11TextureSA* retval = new D3D11TextureSA(m_parent.m_ctx, width, height, layers, mips, fmt, data, sz); d->m_SATexs.emplace_back(retval); return retval; } diff --git a/lib/graphicsdev/D3D12.cpp b/lib/graphicsdev/D3D12.cpp index 34e7028..bd87620 100644 --- a/lib/graphicsdev/D3D12.cpp +++ b/lib/graphicsdev/D3D12.cpp @@ -218,8 +218,10 @@ class D3D12TextureS : public ITextureS upData[i].RowPitch = width * pxPitchNum / pxPitchDenom; upData[i].SlicePitch = upData[i].RowPitch * height; dataIt += upData[i].SlicePitch; - width /= 2; - height /= 2; + if (width > 1) + width /= 2; + if (height > 1) + height /= 2; } if (!PrepSubresources<16>(ctx->m_dev.Get(), &m_gpuDesc, m_tex.Get(), 0, 0, m_gpuDesc.MipLevels, upData)) @@ -256,7 +258,7 @@ class D3D12TextureSA : public ITextureSA size_t m_sz; D3D12_RESOURCE_DESC m_gpuDesc; D3D12TextureSA(D3D12Context* ctx, size_t width, size_t height, size_t layers, - TextureFormat fmt, const void* data, size_t sz) + size_t mips, TextureFormat fmt, const void* data, size_t sz) : m_fmt(fmt), m_layers(layers), m_sz(sz) { size_t pxPitch; @@ -275,41 +277,33 @@ class D3D12TextureSA : public ITextureSA Log.report(logvisor::Fatal, "unsupported tex format"); } - m_gpuDesc = CD3DX12_RESOURCE_DESC::Tex2D(pixelFmt, width, height, layers, 1); - size_t reqSz = GetRequiredIntermediateSize(ctx->m_dev.Get(), &m_gpuDesc, 0, layers); + m_gpuDesc = CD3DX12_RESOURCE_DESC::Tex2D(pixelFmt, width, height, layers, mips); + size_t reqSz = GetRequiredIntermediateSize(ctx->m_dev.Get(), &m_gpuDesc, 0, layers * mips); ThrowIfFailed(ctx->m_dev->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(reqSz), D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, __uuidof(ID3D12Resource), &m_tex)); const uint8_t* dataIt = static_cast(data); - - if (layers > 16) + std::unique_ptr upData(new D3D12_SUBRESOURCE_DATA[layers * mips]); + D3D12_SUBRESOURCE_DATA* outIt = upData.get(); + for (size_t i=0 ; i upData(new D3D12_SUBRESOURCE_DATA[layers]); - for (size_t i=0 ; ipData = dataIt; + outIt->RowPitch = width * pxPitch; + outIt->SlicePitch = outIt->RowPitch * height; + dataIt += outIt->SlicePitch; + ++outIt; } - if (!PrepSubresources(ctx->m_dev.Get(), &m_gpuDesc, m_tex.Get(), 0, 0, layers, upData.get())) - Log.report(logvisor::Fatal, "error preparing resource for upload"); - } - else - { - D3D12_SUBRESOURCE_DATA upData[16] = {}; - for (size_t i=0 ; i(ctx->m_dev.Get(), &m_gpuDesc, m_tex.Get(), 0, 0, layers, upData)) - Log.report(logvisor::Fatal, "error preparing resource for upload"); + if (width > 1) + width /= 2; + if (height > 1) + height /= 2; } + if (!PrepSubresources(ctx->m_dev.Get(), &m_gpuDesc, m_tex.Get(), 0, 0, layers * mips, upData.get())) + Log.report(logvisor::Fatal, "error preparing resource for upload"); } public: ComPtr m_tex; @@ -322,18 +316,10 @@ public: D3D12_RESOURCE_STATE_COPY_DEST, nullptr, __uuidof(ID3D12Resource), &m_gpuTex)); - if (m_gpuDesc.DepthOrArraySize > 16) - { - CommandSubresourcesTransfer(ctx->m_dev.Get(), ctx->m_loadlist.Get(), m_gpuTex.Get(), m_tex.Get(), 0, 0, m_gpuDesc.DepthOrArraySize); - ctx->m_loadlist->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_gpuTex.Get(), - D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE)); - } - else - { - CommandSubresourcesTransfer<16>(ctx->m_dev.Get(), ctx->m_loadlist.Get(), m_gpuTex.Get(), m_tex.Get(), 0, 0, m_gpuDesc.DepthOrArraySize); - ctx->m_loadlist->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_gpuTex.Get(), - D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE)); - } + CommandSubresourcesTransfer(ctx->m_dev.Get(), ctx->m_loadlist.Get(), m_gpuTex.Get(), + m_tex.Get(), 0, 0, m_gpuDesc.DepthOrArraySize * m_gpuDesc.MipLevels); + ctx->m_loadlist->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_gpuTex.Get(), + D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE)); return NextHeapOffset(offset, ctx->m_dev->GetResourceAllocationInfo(0, 1, &m_gpuDesc)); } @@ -1658,10 +1644,10 @@ public: return retval; } - ITextureSA* newStaticArrayTexture(size_t width, size_t height, size_t layers, TextureFormat fmt, - const void* data, size_t sz) + ITextureSA* newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips, + TextureFormat fmt, const void* data, size_t sz) { - D3D12TextureSA* retval = new D3D12TextureSA(m_parent.m_ctx, width, height, layers, fmt, data, sz); + D3D12TextureSA* retval = new D3D12TextureSA(m_parent.m_ctx, width, height, layers, mips, fmt, data, sz); static_cast(m_deferredData)->m_SATexs.emplace_back(retval); return retval; } diff --git a/lib/graphicsdev/Vulkan.cpp b/lib/graphicsdev/Vulkan.cpp index bde5b15..eddf735 100644 --- a/lib/graphicsdev/Vulkan.cpp +++ b/lib/graphicsdev/Vulkan.cpp @@ -1050,14 +1050,14 @@ class VulkanTextureSA : public ITextureSA VulkanContext* m_ctx; TextureFormat m_fmt; size_t m_sz; - size_t m_width, m_height, m_layers; + size_t m_width, m_height, m_layers, m_mips; VkFormat m_vkFmt; int m_pixelPitchNum = 1; int m_pixelPitchDenom = 1; VulkanTextureSA(VulkanContext* ctx, size_t width, size_t height, size_t layers, - TextureFormat fmt, const void* data, size_t sz) - : m_ctx(ctx), m_fmt(fmt), m_width(width), m_height(height), m_layers(layers), m_sz(sz) + size_t mips, TextureFormat fmt, const void* data, size_t sz) + : m_ctx(ctx), m_fmt(fmt), m_width(width), m_height(height), m_layers(layers), m_mips(mips), m_sz(sz) { VkFormat pfmt; switch (fmt) @@ -1111,7 +1111,7 @@ class VulkanTextureSA : public ITextureSA texCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; texCreateInfo.imageType = VK_IMAGE_TYPE_2D; texCreateInfo.format = pfmt; - texCreateInfo.mipLevels = 1; + texCreateInfo.mipLevels = mips; texCreateInfo.arrayLayers = layers; texCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; texCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; @@ -1181,7 +1181,7 @@ public: viewInfo.components.a = VK_COMPONENT_SWIZZLE_A; viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; viewInfo.subresourceRange.baseMipLevel = 0; - viewInfo.subresourceRange.levelCount = 1; + viewInfo.subresourceRange.levelCount = m_mips; viewInfo.subresourceRange.baseArrayLayer = 0; viewInfo.subresourceRange.layerCount = m_layers; @@ -1192,31 +1192,46 @@ public: * DESTINATION_OPTIMAL */ SetImageLayout(ctx->m_loadCmdBuf, m_gpuTex, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, m_layers); + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, m_mips, m_layers); - VkBufferImageCopy copyRegion = {}; - copyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copyRegion.imageSubresource.mipLevel = 0; - copyRegion.imageSubresource.baseArrayLayer = 0; - copyRegion.imageSubresource.layerCount = m_layers; - copyRegion.imageExtent.width = m_width; - copyRegion.imageExtent.height = m_height; - copyRegion.imageExtent.depth = 1; - copyRegion.bufferOffset = 0; + VkBufferImageCopy copyRegions[16] = {}; + size_t width = m_width; + size_t height = m_height; + size_t regionCount = std::min(size_t(16), m_mips); + size_t offset = 0; + for (int i=0 ; i 1) + width /= 2; + if (height > 1) + height /= 2; + offset += srcRowPitch; + } /* Put the copy command into the command buffer */ vk::CmdCopyBufferToImage(ctx->m_loadCmdBuf, m_cpuBuf, m_gpuTex, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, - ©Region); + regionCount, + copyRegions); /* Set the layout for the texture image from DESTINATION_OPTIMAL to * SHADER_READ_ONLY */ SetImageLayout(ctx->m_loadCmdBuf, m_gpuTex, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 1, m_layers); + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, m_mips, m_layers); } TextureFormat format() const {return m_fmt;} @@ -3022,10 +3037,10 @@ ITextureS* VulkanDataFactory::Context::newStaticTexture(size_t width, size_t hei return retval; } -ITextureSA* VulkanDataFactory::Context::newStaticArrayTexture(size_t width, size_t height, size_t layers, +ITextureSA* VulkanDataFactory::Context::newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips, TextureFormat fmt, const void* data, size_t sz) { - VulkanTextureSA* retval = new VulkanTextureSA(m_parent.m_ctx, width, height, layers, fmt, data, sz); + VulkanTextureSA* retval = new VulkanTextureSA(m_parent.m_ctx, width, height, layers, mips, fmt, data, sz); static_cast(m_deferredData.get())->m_SATexs.emplace_back(retval); return retval; }