diff options
| author | Tim Foley <tfoleyNV@users.noreply.github.com> | 2021-03-11 13:08:21 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-03-11 13:08:21 -0800 |
| commit | 4b74f994bf94217f174cf0fb02ed94abe62e9d7c (patch) | |
| tree | 9c6f4c771d1e962059c84047ccf96e0d891a5c80 /tools | |
| parent | a07455c175db33d8d95bc5cd83738808d74cd105 (diff) | |
Change representation of initial data for textures (#1747)
* Change representation of initial data for textures
Before this change, initial data for a texture has been provided with the `ITextureResource::Data` type, where a call to `IDevice::createTexture()` would take zero or one `Data` and, if present, use it to initialize all the subresources of a texture.
The organization of `Data` was not actually quite how its own documentation comment described it (the implementations didn't agree with the comment), and while it aggressively factored out redundancies (e.g., only storing the stride for each mip level once, instead of once per subresource for large arrays), the result was that setting up a `Data` correcty was a bit confusing.
This change makes the initial data for a texture using a `SubresourceData` type that is almost identical to what D3D11 uses, so that developers are more likely to be comfortable filling it in. All of the existing implementations were easily adapted to use the new type, so it seems like a net win.
Note: Both Vulkan and D3D11 do away with the idea of initializing a texture with data as part of allocating it, and we might eventually want to do the same given the complexity that this system entails. The main reason to preserve this detail is for better compatibility with D3D11, where immutable textures/buffers need to have their data specified at creation time. It seems good to preserve the ability to have immutable resources on target APIs where this distinction could affect performance (e.g., immutable resources do not need state/transition tracking on APIs like D3D11).
* fixup: CUDA
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/gfx/cuda/render-cuda.cpp | 8 | ||||
| -rw-r--r-- | tools/gfx/d3d11/render-d3d11.cpp | 17 | ||||
| -rw-r--r-- | tools/gfx/d3d12/render-d3d12.cpp | 31 | ||||
| -rw-r--r-- | tools/gfx/open-gl/render-gl.cpp | 21 | ||||
| -rw-r--r-- | tools/gfx/vulkan/render-vk.cpp | 33 | ||||
| -rw-r--r-- | tools/platform/gui.cpp | 11 | ||||
| -rw-r--r-- | tools/platform/model.cpp | 30 | ||||
| -rw-r--r-- | tools/render-test/shader-renderer-util.cpp | 44 |
8 files changed, 104 insertions, 91 deletions
diff --git a/tools/gfx/cuda/render-cuda.cpp b/tools/gfx/cuda/render-cuda.cpp index ec7edf00a..d13045359 100644 --- a/tools/gfx/cuda/render-cuda.cpp +++ b/tools/gfx/cuda/render-cuda.cpp @@ -1365,7 +1365,7 @@ public: virtual SLANG_NO_THROW Result SLANG_MCALL createTextureResource( IResource::Usage initialUsage, const ITextureResource::Desc& desc, - const ITextureResource::Data* initData, + const ITextureResource::SubresourceData* initData, ITextureResource** outResource) override { RefPtr<TextureCUDAResource> tex = new TextureCUDAResource(desc); @@ -1611,7 +1611,7 @@ public: { for (Index j = 0; j < faceCount; j++) { - const auto srcData = initData->subResources[mipLevel + j * desc.numMipLevels]; + const auto srcData = initData[mipLevel + j * desc.numMipLevels].data; // Copy over to the workspace to make contiguous ::memcpy( workspace.begin() + faceSizeInBytes * j, srcData, @@ -1633,7 +1633,7 @@ public: for (Index j = 0; j < 6; j++) { const auto srcData = - initData->subResources[mipLevel + j * desc.numMipLevels]; + initData[mipLevel + j * desc.numMipLevels].data; ::memcpy( workspace.getBuffer() + faceSizeInBytes * j, srcData, faceSizeInBytes); @@ -1643,7 +1643,7 @@ public: } else { - const auto srcData = initData->subResources[mipLevel]; + const auto srcData = initData[mipLevel].data; srcDataPtr = srcData; } } diff --git a/tools/gfx/d3d11/render-d3d11.cpp b/tools/gfx/d3d11/render-d3d11.cpp index b41169df2..1310e99ae 100644 --- a/tools/gfx/d3d11/render-d3d11.cpp +++ b/tools/gfx/d3d11/render-d3d11.cpp @@ -78,7 +78,7 @@ public: virtual SLANG_NO_THROW Result SLANG_MCALL createTextureResource( IResource::Usage initialUsage, const ITextureResource::Desc& desc, - const ITextureResource::Data* initData, + const ITextureResource::SubresourceData* initData, ITextureResource** outResource) override; virtual SLANG_NO_THROW Result SLANG_MCALL createBufferResource( IResource::Usage initialUsage, @@ -1057,18 +1057,13 @@ static int _calcResourceAccessFlags(int accessFlags) } } -Result D3D11Device::createTextureResource(IResource::Usage initialUsage, const ITextureResource::Desc& descIn, const ITextureResource::Data* initData, ITextureResource** outResource) +Result D3D11Device::createTextureResource(IResource::Usage initialUsage, const ITextureResource::Desc& descIn, const ITextureResource::SubresourceData* initData, ITextureResource** outResource) { TextureResource::Desc srcDesc(descIn); srcDesc.setDefaults(initialUsage); const int effectiveArraySize = srcDesc.calcEffectiveArraySize(); - if(initData) - { - assert(initData->numSubResources == srcDesc.numMipLevels * effectiveArraySize * srcDesc.size.depth); - } - const DXGI_FORMAT format = D3DUtil::getMapFormat(srcDesc.format); if (format == DXGI_FORMAT_UNKNOWN) { @@ -1092,11 +1087,11 @@ Result D3D11Device::createTextureResource(IResource::Usage initialUsage, const I const int mipHeight = ITextureResource::Size::calcMipSize(srcDesc.size.height, j); D3D11_SUBRESOURCE_DATA& data = subRes[subResourceIndex]; + auto& srcData = initData[subResourceIndex]; - data.pSysMem = initData->subResources[subResourceIndex]; - - data.SysMemPitch = UINT(initData->mipRowStrides[j]); - data.SysMemSlicePitch = UINT(initData->mipRowStrides[j] * mipHeight); + data.pSysMem = srcData.data; + data.SysMemPitch = UINT(srcData.strideY); + data.SysMemSlicePitch = UINT(srcData.strideZ); subResourceIndex++; } diff --git a/tools/gfx/d3d12/render-d3d12.cpp b/tools/gfx/d3d12/render-d3d12.cpp index f39baf4cc..3225ed208 100644 --- a/tools/gfx/d3d12/render-d3d12.cpp +++ b/tools/gfx/d3d12/render-d3d12.cpp @@ -81,7 +81,7 @@ public: virtual SLANG_NO_THROW Result SLANG_MCALL createTextureResource( IResource::Usage initialUsage, const ITextureResource::Desc& desc, - const ITextureResource::Data* initData, + const ITextureResource::SubresourceData* initData, ITextureResource** outResource) override; virtual SLANG_NO_THROW Result SLANG_MCALL createBufferResource( IResource::Usage initialUsage, @@ -2402,7 +2402,7 @@ static D3D12_RESOURCE_DIMENSION _calcResourceDimension(IResource::Type type) } } -Result D3D12Device::createTextureResource(IResource::Usage initialUsage, const ITextureResource::Desc& descIn, const ITextureResource::Data* initData, ITextureResource** outResource) +Result D3D12Device::createTextureResource(IResource::Usage initialUsage, const ITextureResource::Desc& descIn, const ITextureResource::SubresourceData* initData, ITextureResource** outResource) { // Description of uploading on Dx12 // https://msdn.microsoft.com/en-us/library/windows/desktop/dn899215%28v=vs.85%29.aspx @@ -2550,6 +2550,8 @@ Result D3D12Device::createTextureResource(IResource::Usage initialUsage, const I for (int j = 0; j < numMipMaps; ++j) { + auto srcSubresource = initData[j]; + const D3D12_PLACED_SUBRESOURCE_FOOTPRINT& layout = layouts[j]; const D3D12_SUBRESOURCE_FOOTPRINT& footprint = layout.Footprint; @@ -2557,25 +2559,34 @@ Result D3D12Device::createTextureResource(IResource::Usage initialUsage, const I assert(footprint.Width == mipSize.width && footprint.Height == mipSize.height && footprint.Depth == mipSize.depth); - const ptrdiff_t dstMipRowPitch = ptrdiff_t(layouts[j].Footprint.RowPitch); - const ptrdiff_t srcMipRowPitch = ptrdiff_t(initData->mipRowStrides[j]); + auto mipRowSize = mipRowSizeInBytes[j]; - assert(dstMipRowPitch >= srcMipRowPitch); + const ptrdiff_t dstMipRowPitch = ptrdiff_t(footprint.RowPitch); + const ptrdiff_t srcMipRowPitch = ptrdiff_t(srcSubresource.strideY); - const uint8_t* srcRow = (const uint8_t*)initData->subResources[subResourceIndex]; - uint8_t* dstRow = p + layouts[j].Offset; + const ptrdiff_t dstMipLayerPitch = ptrdiff_t(footprint.RowPitch*footprint.Height); + const ptrdiff_t srcMipLayerPitch = ptrdiff_t(srcSubresource.strideZ); - // Copy the depth each mip + // Our outer loop will copy the depth layers one at a time. + // + const uint8_t* srcLayer = (const uint8_t*) srcSubresource.data; + uint8_t* dstLayer = p + layouts[j].Offset; for (int l = 0; l < mipSize.depth; l++) { - // Copy rows + // Our inner loop will copy the rows one at a time. + // + const uint8_t* srcRow = srcLayer; + uint8_t* dstRow = dstLayer; for (int k = 0; k < mipSize.height; ++k) { - ::memcpy(dstRow, srcRow, srcMipRowPitch); + ::memcpy(dstRow, srcRow, mipRowSize); srcRow += srcMipRowPitch; dstRow += dstMipRowPitch; } + + srcLayer += srcMipLayerPitch; + dstLayer += dstMipLayerPitch; } //assert(srcRow == (const uint8_t*)(srcMip.getBuffer() + srcMip.getCount())); diff --git a/tools/gfx/open-gl/render-gl.cpp b/tools/gfx/open-gl/render-gl.cpp index cd17aee78..2f2071a42 100644 --- a/tools/gfx/open-gl/render-gl.cpp +++ b/tools/gfx/open-gl/render-gl.cpp @@ -106,7 +106,7 @@ public: virtual SLANG_NO_THROW Result SLANG_MCALL createTextureResource( IResource::Usage initialUsage, const ITextureResource::Desc& desc, - const ITextureResource::Data* initData, + const ITextureResource::SubresourceData* initData, ITextureResource** outResource) override; virtual SLANG_NO_THROW Result SLANG_MCALL createBufferResource( IResource::Usage initialUsage, @@ -1450,7 +1450,7 @@ SLANG_NO_THROW Result SLANG_MCALL GLDevice::readTextureResource( SLANG_NO_THROW Result SLANG_MCALL GLDevice::createTextureResource( IResource::Usage initialUsage, const ITextureResource::Desc& descIn, - const ITextureResource::Data* initData, + const ITextureResource::SubresourceData* initData, ITextureResource** outResource) { TextureResource::Desc srcDesc(descIn); @@ -1479,6 +1479,10 @@ SLANG_NO_THROW Result SLANG_MCALL GLDevice::createTextureResource( // Set on texture so will be freed if failure texture->m_handle = handle; + // TODO: The logic below seems to be ignoring the row/layer stride of + // the subresources that have been passed in, despite OpenGL having + // the ability to set the image unpack stride, etc. + switch (srcDesc.type) { case IResource::Type::Texture1D: @@ -1493,6 +1497,7 @@ SLANG_NO_THROW Result SLANG_MCALL GLDevice::createTextureResource( { for (int j = 0; j < srcDesc.numMipLevels; j++) { + // TODO: Double-check this logic - we are passing in `i` as the height? glTexImage2D( target, j, @@ -1502,7 +1507,7 @@ SLANG_NO_THROW Result SLANG_MCALL GLDevice::createTextureResource( 0, format, formatType, - initData ? initData->subResources[slice++] : nullptr); + initData ? initData[slice++].data : nullptr); } } } @@ -1520,7 +1525,7 @@ SLANG_NO_THROW Result SLANG_MCALL GLDevice::createTextureResource( 0, format, formatType, - initData ? initData->subResources[i] : nullptr); + initData ? initData[i].data : nullptr); } } break; @@ -1556,7 +1561,7 @@ SLANG_NO_THROW Result SLANG_MCALL GLDevice::createTextureResource( 0, format, formatType, - initData ? initData->subResources[slice++] : nullptr); + initData ? initData[slice++].data : nullptr); } } } @@ -1581,7 +1586,7 @@ SLANG_NO_THROW Result SLANG_MCALL GLDevice::createTextureResource( 0, format, formatType, - initData ? initData->subResources[slice++] : nullptr); + initData ? initData[slice++].data : nullptr); } } } @@ -1600,7 +1605,7 @@ SLANG_NO_THROW Result SLANG_MCALL GLDevice::createTextureResource( 0, format, formatType, - initData ? initData->subResources[i] : nullptr); + initData ? initData[i].data : nullptr); } } } @@ -1622,7 +1627,7 @@ SLANG_NO_THROW Result SLANG_MCALL GLDevice::createTextureResource( 0, format, formatType, - initData ? initData->subResources[i] : nullptr); + initData ? initData[i].data : nullptr); } break; } diff --git a/tools/gfx/vulkan/render-vk.cpp b/tools/gfx/vulkan/render-vk.cpp index ee494d4c8..1c263d505 100644 --- a/tools/gfx/vulkan/render-vk.cpp +++ b/tools/gfx/vulkan/render-vk.cpp @@ -65,7 +65,7 @@ public: virtual SLANG_NO_THROW Result SLANG_MCALL createTextureResource( IResource::Usage initialUsage, const ITextureResource::Desc& desc, - const ITextureResource::Data* initData, + const ITextureResource::SubresourceData* initData, ITextureResource** outResource) override; virtual SLANG_NO_THROW Result SLANG_MCALL createBufferResource( IResource::Usage initialUsage, @@ -3011,7 +3011,7 @@ size_t calcNumRows(Format format, int height) return (size_t)height; } -Result VKDevice::createTextureResource(IResource::Usage initialUsage, const ITextureResource::Desc& descIn, const ITextureResource::Data* initData, ITextureResource** outResource) +Result VKDevice::createTextureResource(IResource::Usage initialUsage, const ITextureResource::Desc& descIn, const ITextureResource::SubresourceData* initData, ITextureResource** outResource) { TextureResource::Desc desc(descIn); desc.setDefaults(initialUsage); @@ -3113,7 +3113,6 @@ Result VKDevice::createTextureResource(IResource::Usage initialUsage, const ITex VkCommandBuffer commandBuffer = m_deviceQueue.getCommandBuffer(); const int numMipMaps = desc.numMipLevels; - assert(initData->numMips == numMipMaps); // Calculate how large the buffer has to be size_t bufferSize = 0; @@ -3140,35 +3139,49 @@ Result VKDevice::createTextureResource(IResource::Usage initialUsage, const ITex // Copy into upload buffer { - int subResourceIndex = 0; + int subResourceCounter = 0; uint8_t* dstData; m_api.vkMapMemory(m_device, uploadBuffer.m_memory, 0, bufferSize, 0, (void**)&dstData); + size_t dstSubresourceOffset = 0; for (int i = 0; i < arraySize; ++i) { for (Index j = 0; j < mipSizes.getCount(); ++j) { const auto& mipSize = mipSizes[j]; - const ptrdiff_t srcRowStride = initData->mipRowStrides[j]; + int subResourceIndex = subResourceCounter++; + auto initSubresource = initData[subResourceIndex]; + + const ptrdiff_t srcRowStride = initSubresource.strideY; + const ptrdiff_t srcLayerStride = initSubresource.strideZ; + auto dstRowSizeInBytes = calcRowSize(desc.format, mipSize.width); auto numRows = calcNumRows(desc.format, mipSize.height); + auto dstLayerSizeInBytes = dstRowSizeInBytes * numRows; + + const uint8_t* srcLayer = (const uint8_t*) initSubresource.data; + uint8_t* dstLayer = dstData + dstSubresourceOffset; for (int k = 0; k < mipSize.depth; k++) { - const uint8_t* srcData = (const uint8_t*)(initData->subResources[subResourceIndex]); + const uint8_t* srcRow = srcLayer; + uint8_t* dstRow = dstLayer; for (uint32_t l = 0; l < numRows; l++) { - ::memcpy(dstData, srcData, dstRowSizeInBytes); + ::memcpy(dstRow, srcRow, dstRowSizeInBytes); - dstData += dstRowSizeInBytes; - srcData += srcRowStride; + dstRow += dstRowSizeInBytes; + srcRow += srcRowStride; } - subResourceIndex++; + dstLayer += dstLayerSizeInBytes; + srcLayer += srcLayerStride; } + + dstSubresourceOffset += dstLayerSizeInBytes * mipSize.depth; } } diff --git a/tools/platform/gui.cpp b/tools/platform/gui.cpp index f2f9561d5..8e455cd12 100644 --- a/tools/platform/gui.cpp +++ b/tools/platform/gui.cpp @@ -217,14 +217,9 @@ GUI::GUI( desc.init2D(IResource::Type::Texture2D, Format::RGBA_Unorm_UInt8, width, height, 1); desc.setDefaults(IResource::Usage::PixelShaderResource); - - ptrdiff_t mipRowStrides[] = { ptrdiff_t(width * 4 * sizeof(unsigned char)) }; - void* subResourceData[] = { pixels }; - ITextureResource::Data initData; - initData.mipRowStrides = mipRowStrides; - initData.numMips = 1; - initData.numSubResources = 1; - initData.subResources = subResourceData; + ITextureResource::SubresourceData initData = {}; + initData.data = pixels; + initData.strideY = width * 4 * sizeof(unsigned char); auto texture = device->createTextureResource(IResource::Usage::PixelShaderResource, desc, &initData); diff --git a/tools/platform/model.cpp b/tools/platform/model.cpp index 287f80958..54c171e54 100644 --- a/tools/platform/model.cpp +++ b/tools/platform/model.cpp @@ -128,13 +128,16 @@ ComPtr<ITextureResource> loadTextureImage( // results when loading the image with stb_image. } - std::vector<void*> subresourceInitData; - std::vector<ptrdiff_t> mipRowStrides; + std::vector<ITextureResource::SubresourceData> subresourceInitData; ptrdiff_t stride = extentX * channelCount * sizeof(stbi_uc); - subresourceInitData.push_back(data); - mipRowStrides.push_back(stride); + ITextureResource::SubresourceData baseInitData; + baseInitData.data = data; + baseInitData.strideY = stride; + baseInitData.strideZ = 0; + + subresourceInitData.push_back(baseInitData); // create down-sampled images for the different mip levels bool generateMips = true; @@ -166,8 +169,13 @@ ComPtr<ITextureResource> loadTextureImage( STBIR_ALPHA_CHANNEL_NONE, STBIR_FLAG_ALPHA_PREMULTIPLIED); - subresourceInitData.push_back(newData); - mipRowStrides.push_back(newStride); + + ITextureResource::SubresourceData mipInitData; + mipInitData.data = newData; + mipInitData.strideY = newStride; + mipInitData.strideZ = 0; + + subresourceInitData.push_back(mipInitData); prevExtentX = newExtentX; prevExtentY = newExtentY; @@ -176,19 +184,13 @@ ComPtr<ITextureResource> loadTextureImage( } } - int mipCount = (int) mipRowStrides.size(); + int mipCount = (int) subresourceInitData.size(); ITextureResource::Desc desc; desc.init2D(IResource::Type::Texture2D, format, extentX, extentY, mipCount); - ITextureResource::Data initData; - initData.numSubResources = mipCount; - initData.numMips = mipCount; - initData.subResources = &subresourceInitData[0]; - initData.mipRowStrides = &mipRowStrides[0]; - auto texture = - device->createTextureResource(IResource::Usage::PixelShaderResource, desc, &initData); + device->createTextureResource(IResource::Usage::PixelShaderResource, desc, subresourceInitData.data()); free(data); diff --git a/tools/render-test/shader-renderer-util.cpp b/tools/render-test/shader-renderer-util.cpp index 57187fc44..903164567 100644 --- a/tools/render-test/shader-renderer-util.cpp +++ b/tools/render-test/shader-renderer-util.cpp @@ -87,38 +87,30 @@ void BindingStateImpl::apply(ICommandEncoder* encoder, PipelineType pipelineType const int numSubResources = textureResourceDesc.calcNumSubResources(); IResource::Usage initialUsage = IResource::Usage::GenericRead; - ITextureResource::Data initData; - List<ptrdiff_t> mipRowStrides; - mipRowStrides.setCount(textureResourceDesc.numMipLevels); - List<const void*> subResources; - subResources.setCount(numSubResources); - - // Set up the src row strides - for (int i = 0; i < textureResourceDesc.numMipLevels; i++) - { - const int mipWidth = ITextureResource::Size::calcMipSize(textureResourceDesc.size.width, i); - mipRowStrides[i] = mipWidth * sizeof(uint32_t); - } - - // Set up pointers the the data + List<ITextureResource::SubresourceData> initSubresources; + int subResourceCounter = 0; + for( int a = 0; a < effectiveArraySize; ++a ) { - int subResourceIndex = 0; - const int numGen = int(texData.dataBuffer.getCount()); - for (int i = 0; i < numSubResources; i++) + for( int m = 0; m < textureResourceDesc.numMipLevels; ++m ) { - subResources[i] = texData.dataBuffer[subResourceIndex].getBuffer(); - // Wrap around - subResourceIndex = (subResourceIndex + 1 >= numGen) ? 0 : (subResourceIndex + 1); + int subResourceIndex = subResourceCounter++; + const int mipWidth = ITextureResource::Size::calcMipSize(textureResourceDesc.size.width, m); + const int mipHeight = ITextureResource::Size::calcMipSize(textureResourceDesc.size.width, m); + + auto strideY = mipWidth * sizeof(uint32_t); + auto strideZ = mipHeight * strideY; + + ITextureResource::SubresourceData subresourceData; + subresourceData.data = texData.dataBuffer[subResourceIndex].getBuffer(); + subresourceData.strideY = strideY; + subresourceData.strideZ = strideZ; + + initSubresources.add(subresourceData); } } - initData.mipRowStrides = mipRowStrides.getBuffer(); - initData.numMips = textureResourceDesc.numMipLevels; - initData.numSubResources = numSubResources; - initData.subResources = subResources.getBuffer(); - - textureOut = device->createTextureResource(IResource::Usage::GenericRead, textureResourceDesc, &initData); + textureOut = device->createTextureResource(IResource::Usage::GenericRead, textureResourceDesc, initSubresources.getBuffer()); return textureOut ? SLANG_OK : SLANG_FAIL; } |
