Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make setting a stride of the ImageView data possible #150

Open
wants to merge 11 commits into
base: master
Choose a base branch
from

Conversation

st0rmbtw
Copy link
Contributor

@st0rmbtw st0rmbtw commented Jan 22, 2025

I was implementing the chunked lightmap rendering in my project.
The idea is that instead of one huge lightmap texture, I create multiple smaller ones and render them only if they are visible.
But I ran into a problem when I needed to update the lightmap on the intersection of multiple chunks.
Because I had to calculate proper offsets and size for each chunk's texture.

As the size of the texture of a chunk and the size of the lightmap buffer on CPU are different, I had to do the following:

  1. Allocate a buffer with the size of the chunk's texture.
  2. Copy the specific portion of data from the CPU lightmap to the bufer.
  3. Update the GPU texture with the data from the buffer.
  4. Deallocate the buffer.

It was quite slow to do all of that. I could have only the third step if there was an option to set custom stride for the source data of the image view.

But then I noticed that ID3D11DeviceContext::UpdateSubresource function has a parameter just for what I need, so I made this PR to expose that parameter in the public interface.

Copy link
Owner

@LukasBanana LukasBanana left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm glad to see you getting acquainted with the inner workings of LLGL :-) I started with a concept for rowStride and layerStride in this struct earlier of last year but never took the time to start on the implementation because I had no need for this feature so far.

I'm happy to help with the Metal backend, but we can add this a bit later. It would make sense to also add this field to MutableImageView at some point, but that's maybe something for another time.

include/LLGL/ImageFlags.h Outdated Show resolved Hide resolved
include/LLGL-C/LLGLWrapper.h Outdated Show resolved Hide resolved
sources/Renderer/TextureUtils.h Outdated Show resolved Hide resolved
{
const FormatAttributes& formatAttribs = GetFormatAttribs(format);
if (formatAttribs.blockWidth > 0 && formatAttribs.blockHeight > 0)
{
outLayout.rowStride = (extent.width * formatAttribs.bitSize) / formatAttribs.blockWidth / 8;
outLayout.rowStride = ((srcDataStride > 0 ? srcDataStride : extent.width) * formatAttribs.bitSize) / formatAttribs.blockWidth / 8;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How should LLGL behave when the row stride is smaller than the width of the source image? Should this be undefined behavior or be defined as an invalid argument? Either way, it should be documented in the ImageView struct for this field. If we consider it an invalid argument we should probably also add max(srcDataStride, extent.width) here to clamp it to the largest value or add an assertion LLGL_ASSERT(srcDataStride == 0 || srcDataStride >= extent.width).

Copy link
Contributor Author

@st0rmbtw st0rmbtw Jan 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why it is an issue. Isn't the extent there describes the size of the destination subresource? If so then it doesn't matter if the row stride is bigger or smaller than extent.width. Correct me if I'm wrong, please.

sources/Renderer/Vulkan/VKRenderSystem.cpp Outdated Show resolved Hide resolved
sources/Renderer/Vulkan/VKRenderSystem.cpp Outdated Show resolved Hide resolved
sources/Renderer/OpenGL/Texture/GLTexSubImage.cpp Outdated Show resolved Hide resolved
@LukasBanana LukasBanana self-assigned this Jan 23, 2025
@LukasBanana LukasBanana added the feature request Requested features and TODO lists label Jan 23, 2025
@@ -477,7 +477,7 @@ void VKRenderSystem::WriteTexture(Texture& texture, const TextureRegion& texture
VK_BUFFER_USAGE_TRANSFER_SRC_BIT // <-- TODO: support read/write mapping //GetStagingVkBufferUsageFlags(bufferDesc.cpuAccessFlags)
);

VKDeviceBuffer stagingBuffer = CreateStagingBufferAndInitialize(stagingCreateInfo, imageData, imageDataSize);
VKDeviceBuffer stagingBuffer = CreateTextureStagingBufferAndInitialize(stagingCreateInfo, srcImageView, extent);
Copy link
Owner

@LukasBanana LukasBanana Jan 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this change ignores imageData. This function must not use the input parameter directly in case the image format and data type had to be converted (see intermediateData). That's what all the code above is for. Oh, and the convert functions such as ConvertImageBuffer() will also have to handle the new stride. Yeah, this features goes wide I'm afraid 😬

Copy link
Contributor Author

@st0rmbtw st0rmbtw Jan 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fixed the ignoring of imageData, but I'm not sure about ConvertImageBuffer because I can't figure out how to take the stride into account in ConvertImageBufferFormatWorker

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll see to also update the image conversion functions over the weekend. The work distribution likely needs to be adjusted.

@st0rmbtw
Copy link
Contributor Author

st0rmbtw commented Jan 23, 2025

It was a quick and a low effort solution just to get it working, and also I was sleepy 😅. I just wanted to get your feedback on the idea and implementation.

I'm glad to see you getting acquainted with the inner workings of LLGL :-)

Yeah, now I understand it a little better :). I wish I had more knowledge of graphics programming to help you with the bigger problems.

I'm happy to help with the Metal backend

Yes, please help me if you have the time, I'm scared of Objective-C. If you don't have time I can try to do it myself.

@st0rmbtw st0rmbtw requested a review from LukasBanana January 23, 2025 08:42
@LukasBanana
Copy link
Owner

I'll take another look over the weekend since this is a bit more involved and I'll come up with a unit test for this feature.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request Requested features and TODO lists
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants