Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 29 additions & 3 deletions Source/Foundation/bsfCore/Image/BsTexture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ namespace bs
Texture::Texture(const TEXTURE_DESC& desc)
:mProperties(desc)
{

}

Texture::Texture(const TEXTURE_DESC& desc, const SPtr<PixelData>& pixelData)
Expand Down Expand Up @@ -125,7 +125,26 @@ namespace bs
return gCoreThread().queueReturnCommand(std::bind(func, getCore(), face, mipLevel,
data, discardEntireBuffer, std::placeholders::_1));
}
AsyncOp Texture::writeSubData(const SPtr<PixelData>& data, Vector3I dstPosition, UINT32 face, UINT32 mipLevel)
{
UINT32 subresourceIdx = mProperties.mapToSubresourceIdx(face, mipLevel);
updateCPUBuffers(subresourceIdx, *data);

data->_lock();

std::function<void(const SPtr<ct::Texture>&, Vector3I, UINT32, UINT32, const SPtr<PixelData>&, AsyncOp&)> func =
[&](const SPtr<ct::Texture>& texture, Vector3I dstPos, UINT32 _face, UINT32 _mipLevel, const SPtr<PixelData>& _pixData,
AsyncOp& asyncOp)
{
texture->writeSubData(*_pixData, dstPos,_mipLevel, _face);
_pixData->_unlock();
asyncOp._completeOperation();

};

return gCoreThread().queueReturnCommand(std::bind(func, getCore(), dstPosition,face, mipLevel,
data, std::placeholders::_1));
}
AsyncOp Texture::readData(const SPtr<PixelData>& data, UINT32 face, UINT32 mipLevel)
{
data->_lock();
Expand Down Expand Up @@ -306,7 +325,7 @@ namespace bs

return static_resource_cast<Texture>(gResources()._createResourceHandle(texturePtr));
}

HTexture Texture::create(const SPtr<PixelData>& pixelData, int usage, bool hwGammaCorrection)
{
SPtr<Texture> texturePtr = _createPtr(pixelData, usage, hwGammaCorrection);
Expand Down Expand Up @@ -372,6 +391,13 @@ namespace bs
writeDataImpl(src, mipLevel, face, discardEntireBuffer, queueIdx);
}

void Texture::writeSubData(const PixelData& src, Vector3I dstPosition, UINT32 mipLevel, UINT32 face,
UINT32 queueIdx)
{
THROW_IF_NOT_CORE_THREAD;
writeSubDataImpl(src, dstPosition,mipLevel, face, queueIdx);
}

void Texture::readData(PixelData& dest, UINT32 mipLevel, UINT32 face, UINT32 deviceIdx, UINT32 queueIdx)
{
THROW_IF_NOT_CORE_THREAD;
Expand Down Expand Up @@ -555,7 +581,7 @@ namespace bs
{
SPtr<PixelData> data = mProperties.allocBuffer(face, mipLevel);
data->setColors(value);

writeData(*data, mipLevel, face, true, queueIdx);
}

Expand Down
47 changes: 38 additions & 9 deletions Source/Foundation/bsfCore/Image/BsTexture.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ namespace bs
* Allocates a buffer that exactly matches the format of the texture described by these properties, for the provided
* face and mip level. This is a helper function, primarily meant for creating buffers when reading from, or writing
* to a texture.
*
*
* @note Thread safe.
*/
SPtr<PixelData> allocBuffer(UINT32 face, UINT32 mipLevel) const;
Expand Down Expand Up @@ -221,6 +221,20 @@ namespace bs
AsyncOp writeData(const SPtr<PixelData>& data, UINT32 face = 0, UINT32 mipLevel = 0,
bool discardEntireBuffer = false);

/**
* Updates part of the texture with new data. Provided data buffer will be locked until the operation completes.
*
* @param[in] data Pixel data to write. User must ensure it is in format and size compatible with
* the texture.
* @param[in] dstPosition Position that will be overwritten by provided data.
* @param[in] face Texture face to write to.
* @param[in] mipLevel Mipmap level to write to.
* @return Async operation object you can use to track operation completion.
*
* @note This is an @ref asyncMethod "asynchronous method".
*/
AsyncOp writeSubData(const SPtr<PixelData>& data, Vector3I dstPosition, UINT32 face = 0, UINT32 mipLevel = 0);

/**
* Reads internal texture data to the provided previously allocated buffer. Provided data buffer will be locked
* until the operation completes.
Expand Down Expand Up @@ -250,13 +264,13 @@ namespace bs

/**
* Reads data from the cached system memory texture buffer into the provided buffer.
*
*
* @param[out] data Pre-allocated buffer of proper size and format where data will be read to. You can use
* TextureProperties::allocBuffer() to allocate a buffer of a correct format and size.
* @param[in] face Texture face to read from.
* @param[in] mipLevel Mipmap level to read from.
*
* @note
* @note
* The data read is the cached texture data. Any data written to the texture from the GPU or core thread will not
* be reflected in this data. Use readData() if you require those changes.
* @note
Expand Down Expand Up @@ -377,8 +391,8 @@ namespace bs
* @param[in] deviceIdx Index of the device whose memory to map. If the buffer doesn't exist on this device,
* the method returns null.
* @param[in] queueIdx Device queue to perform the read/write operations on. See @ref queuesDoc.
*
* @note
*
* @note
* If you are just reading or writing one block of data use readData()/writeData() methods as they can be much faster
* in certain situations.
*/
Expand Down Expand Up @@ -419,7 +433,7 @@ namespace bs

/**
* Reads data from the texture buffer into the provided buffer.
*
*
* @param[out] dest Previously allocated buffer to read data into.
* @param[in] mipLevel (optional) Mipmap level to read from.
* @param[in] face (optional) Texture face to read from.
Expand All @@ -428,11 +442,11 @@ namespace bs
* @param[in] queueIdx Device queue to perform the read operation on. See @ref queuesDoc.
*/
void readData(PixelData& dest, UINT32 mipLevel = 0, UINT32 face = 0, UINT32 deviceIdx = 0,
UINT32 queueIdx = 0);
UINT32 queueIdx = 0);

/**
* Writes data from the provided buffer into the texture buffer.
*
*
* @param[in] src Buffer to retrieve the data from.
* @param[in] mipLevel (optional) Mipmap level to write into.
* @param[in] face (optional) Texture face to write into.
Expand All @@ -441,7 +455,19 @@ namespace bs
* @param[in] queueIdx Device queue to perform the write operation on. See @ref queuesDoc.
*/
void writeData(const PixelData& src, UINT32 mipLevel = 0, UINT32 face = 0, bool discardWholeBuffer = false,
UINT32 queueIdx = 0);
UINT32 queueIdx = 0);

/**
* Writes data from the provided buffer into the specific location in texture buffer.
*
* @param[in] src Buffer to retrieve the data from.
* @param[in] dstPosition Position that will be overwritten by provided data.
* @param[in] mipLevel (optional) Mipmap level to write into.
* @param[in] face (optional) Texture face to write into.
* @param[in] queueIdx Device queue to perform the write operation on. See @ref queuesDoc.
*/
void writeSubData(const PixelData& src, Vector3I dstPosition, UINT32 mipLevel = 0, UINT32 face = 0,
UINT32 queueIdx = 0);

/** Returns properties that contain information about the texture. */
const TextureProperties& getProperties() const { return mProperties; }
Expand Down Expand Up @@ -504,6 +530,9 @@ namespace bs
virtual void writeDataImpl(const PixelData& src, UINT32 mipLevel = 0, UINT32 face = 0,
bool discardWholeBuffer = false, UINT32 queueIdx = 0) = 0;

/** @copydoc writeSubData */
virtual void writeSubDataImpl(const PixelData& src, Vector3I dstPosition, UINT32 mipLevel = 0, UINT32 face = 0,
UINT32 queueIdx = 0) = 0;
/** @copydoc clear */
virtual void clearImpl(const Color& value, UINT32 mipLevel = 0, UINT32 face = 0, UINT32 queueIdx = 0);

Expand Down
6 changes: 6 additions & 0 deletions Source/Plugins/bsfD3D11RenderAPI/BsD3D11Texture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,12 @@ namespace bs { namespace ct
}
}

void D3D11Texture::writeSubDataImpl(const PixelData& src,Vector3I dst, UINT32 mipLevel, UINT32 face,
UINT32 queueIdx)
{
BS_EXCEPT(RenderingAPIException, "D3D11Texture writeSubDataImpl has not been implementeted yet");
}

void D3D11Texture::create1DTex()
{
UINT32 width = mProperties.getWidth();
Expand Down
6 changes: 5 additions & 1 deletion Source/Plugins/bsfD3D11RenderAPI/BsD3D11Texture.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,11 @@ namespace bs { namespace ct

/** @copydoc Texture::writeData */
void writeDataImpl(const PixelData& src, UINT32 mipLevel = 0, UINT32 face = 0, bool discardWholeBuffer = false,
UINT32 queueIdx = 0) override;
UINT32 queueIdx = 0) override;

/** @copydoc Texture::writeSubData */
void writeSubDataImpl(const PixelData& src, Vector3I dstPosition, UINT32 mipLevel = 0, UINT32 face = 0,
UINT32 queueIdx = 0) override;

/** Creates a blank DX11 1D texture object. */
void create1DTex();
Expand Down
20 changes: 10 additions & 10 deletions Source/Plugins/bsfGLRenderAPI/BsGLPixelBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ namespace bs { namespace ct
void* GLPixelBuffer::lock(UINT32 offset, UINT32 length, GpuLockOptions options)
{
assert(!mIsLocked && "Cannot lock this buffer, it is already locked!");
assert(offset == 0 && length == mSizeInBytes && "Cannot lock memory region, most lock box or entire buffer");
assert(offset == 0 && length == mSizeInBytes && "Cannot lock memory region, must lock box or entire buffer");

PixelVolume volume(0, 0, 0, mWidth, mHeight, mDepth);
const PixelData& lockedData = lock(volume, options);
Expand Down Expand Up @@ -117,21 +117,21 @@ namespace bs { namespace ct
, mLevel(level), mMultisampleCount(multisampleCount), mHwGamma(hwGamma)
{
GLint value = 0;

glBindTexture(mTarget, mTextureID);
BS_CHECK_GL_ERROR();

// Get face identifier
mFaceTarget = mTarget;
if(mTarget == GL_TEXTURE_CUBE_MAP)
mFaceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + (face % 6);

// Get width
glGetTexLevelParameteriv(mFaceTarget, level, GL_TEXTURE_WIDTH, &value);
BS_CHECK_GL_ERROR();

mWidth = value;

// Get height
if(target == GL_TEXTURE_1D)
value = 1; // Height always 1 for 1D textures
Expand All @@ -142,7 +142,7 @@ namespace bs { namespace ct
}

mHeight = value;

// Get depth
if(target != GL_TEXTURE_3D)
value = 1; // Depth always 1 for non-3D textures
Expand All @@ -156,7 +156,7 @@ namespace bs { namespace ct

// Default
mSizeInBytes = PixelUtil::getMemorySize(mWidth, mHeight, mDepth, mFormat);

// Set up pixel box
mBuffer = PixelData(mWidth, mHeight, mDepth, mFormat);
}
Expand Down Expand Up @@ -220,7 +220,7 @@ namespace bs { namespace ct
default:
break;
}

}
else
{
Expand Down Expand Up @@ -282,7 +282,7 @@ namespace bs { namespace ct
data.getData());
BS_CHECK_GL_ERROR();
break;
}
}
}

// Restore defaults
Expand Down Expand Up @@ -535,7 +535,7 @@ namespace bs { namespace ct
mTextureID, mTarget, mLevel, dstBox.left, dstBox.top, mFace, srcBox.getWidth(), srcBox.getHeight(), 1);
BS_CHECK_GL_ERROR();
}
}
}
#endif
}
}}
35 changes: 32 additions & 3 deletions Source/Plugins/bsfGLRenderAPI/BsGLTexture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ namespace bs { namespace ct
if(height > 1)
height = height/2;

if(depth > 1)
if(depth > 1)
depth = depth/2;
}
}
Expand Down Expand Up @@ -449,6 +449,35 @@ namespace bs { namespace ct
getBuffer(face, mipLevel)->upload(src, src.getExtents());
}

void GLTexture::writeSubDataImpl(const PixelData& src,Vector3I dst, UINT32 mipLevel, UINT32 face,
UINT32 queueIdx)
{
if (mProperties.getNumSamples() > 1)
{
BS_LOG(Error, RenderBackend, "Multisampled textures cannot be accessed from the CPU directly.");
return;
}

PixelVolume src_vol = src.getExtents();
PixelVolume target_vol(
dst.x,dst.y,dst.z,
dst.x+src_vol.getWidth(),dst.y+src_vol.getHeight(),dst.z+src_vol.getDepth()
);
if (src.getFormat() != mInternalFormat)
{
PixelData temp(src.getExtents(), mInternalFormat);
temp.allocateInternalBuffer();

PixelUtil::bulkPixelConversion(src, temp);
getBuffer(face, mipLevel)->upload(temp, target_vol);
}
else
{

getBuffer(face, mipLevel)->upload(src, target_vol);
}
}

void GLTexture::copyImpl(const SPtr<Texture>& target, const TEXTURE_COPY_DESC& desc,
const SPtr<CommandBuffer>& commandBuffer)
{
Expand Down Expand Up @@ -503,7 +532,7 @@ namespace bs { namespace ct
void GLTexture::createSurfaceList()
{
mSurfaceList.clear();

for (UINT32 face = 0; face < mProperties.getNumFaces(); face++)
{
for (UINT32 mip = 0; mip <= mProperties.getNumMipmaps(); mip++)
Expand All @@ -523,7 +552,7 @@ namespace bs { namespace ct
}
}
}

SPtr<GLPixelBuffer> GLTexture::getBuffer(UINT32 face, UINT32 mipmap)
{
THROW_IF_NOT_CORE_THREAD;
Expand Down
6 changes: 5 additions & 1 deletion Source/Plugins/bsfGLRenderAPI/BsGLTexture.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ namespace bs { namespace ct
void writeDataImpl(const PixelData& src, UINT32 mipLevel = 0, UINT32 face = 0, bool discardWholeBuffer = false,
UINT32 queueIdx = 0) override;

/** @copydoc Texture::writeSubData */
void writeSubDataImpl(const PixelData& src, Vector3I dstPosition, UINT32 mipLevel = 0, UINT32 face = 0,
UINT32 queueIdx = 0) override;

/** Creates pixel buffers for each face and mip level. Texture must have been created previously. */
void createSurfaceList();

Expand All @@ -86,7 +90,7 @@ namespace bs { namespace ct
PixelFormat mInternalFormat = PF_UNKNOWN;
GLSupport& mGLSupport;
SPtr<GLPixelBuffer> mLockedBuffer;

Vector<SPtr<GLPixelBuffer>>mSurfaceList;
};

Expand Down
6 changes: 5 additions & 1 deletion Source/Plugins/bsfNullRenderAPI/BsNullTexture.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ namespace bs
/** @copydoc TextureManager::getNativeFormat */
PixelFormat getNativeFormat(TextureType ttype, PixelFormat format, int usage, bool hwGamma) override;

protected:
protected:
/** @copydoc TextureManager::createRenderTextureImpl */
SPtr<RenderTexture> createRenderTextureImpl(const RENDER_TEXTURE_DESC& desc) override;
};
Expand Down Expand Up @@ -66,6 +66,10 @@ namespace bs
void writeDataImpl(const PixelData& src, UINT32 mipLevel = 0, UINT32 face = 0, bool discardWholeBuffer = false,
UINT32 queueIdx = 0) override { }

/** @copydoc Texture::writeSubData */
void writeSubDataImpl(const PixelData& src, Vector3I dstPosition, UINT32 mipLevel = 0, UINT32 face = 0,
UINT32 queueIdx = 0) override {}

protected:
PixelData* mMappedBuffer = nullptr;
};
Expand Down
Loading