#[FIXED] pass 3 dimensional array to frag with storage buffer

40 messages · Page 1 of 1 (latest)

arctic surge
#

Hi I'm tiring to pass a 3 dimensional array to fragment shader with a storage buffer but the data are corrupted
Is it a problem with alignment ?

The struct of the buffer data:

struct Pos {
    glm::uint32 position;

    static VkVertexInputBindingDescription getBindingDescription() {
        VkVertexInputBindingDescription bindingDescription{};
        bindingDescription.binding = 0;
        bindingDescription.stride = sizeof(Pos);
        bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;

        return bindingDescription;
    }

    static std::array<VkVertexInputAttributeDescription, 2> getAttributeDescriptions() {
        std::array<VkVertexInputAttributeDescription, 2> attributeDescriptions{};

        attributeDescriptions[0].binding = 0;
        attributeDescriptions[0].location = 0;
        attributeDescriptions[0].format = VK_FORMAT_R64_SINT;
        attributeDescriptions[0].offset = offsetof(Pos, position);

        return attributeDescriptions;
    }
};
#

How I create the buffer:

std::vector<std::vector<std::vector<Pos > > > cubeCoos(MAP_SIZE, std::vector<std::vector<Pos> >(MAP_SIZE, std::vector<Pos>(MAP_SIZE)));
        for (auto& x : cubeCoos) {
            for (auto& y : x) {
                for (auto& z : y) {
                    z.position = glm::uint32(0);
                }
            }
        }

        cubeCoos[0][0][0].position = 1;
        cubeCoos[0][4][0].position = 2;
        cubeCoos[4][0][0].position = 3;

        std::cout << sizeof(Pos) << std::endl;

        std::cout << sizeof(Pos) * MAP_SIZE * MAP_SIZE * MAP_SIZE << std::endl;

        VkDeviceSize bufferSize = sizeof(Pos) * MAP_SIZE * MAP_SIZE * MAP_SIZE;

        VkBuffer stagingBuffer;
        VkDeviceMemory stagingBufferMemory;
        createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory);

        void* data;
        vkMapMemory(device, stagingBufferMemory, 0, bufferSize, 0, &data);
        memcpy(data, cubeCoos.data(), (size_t)bufferSize);
        vkUnmapMemory(device, stagingBufferMemory);

        storageBuffers.resize(MAX_FRAMES_IN_FLIGHT);
        storageBuffersMemory.resize(MAX_FRAMES_IN_FLIGHT);

        // Copy initial cube data to all storage buffers
        for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
            createBuffer(bufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, storageBuffers[i], storageBuffersMemory[i]);
            copyBuffer(stagingBuffer, storageBuffers[i], bufferSize);
        }

        vkDestroyBuffer(device, stagingBuffer, nullptr);
        vkFreeMemory(device, stagingBufferMemory, nullptr);
#

the glsl frag:

struct Cube {
  uint type;
};

const int gridSize = 8;

layout(std140, binding = 1) readonly buffer cubesSSBOIn {
   Cube cubesIn[gridSize][gridSize][gridSize];
};

layout(std140, binding = 2) buffer cubesSSBOOut {
   Cube cubesOut[gridSize][gridSize][gridSize];
};

...

uint getVoxel(ivec3 rayPos) {
    if ((0 > rayPos.x) || (gridSize <= rayPos.x)) {
        return 0;
    }
    if ((0 > rayPos.y) || (gridSize <= rayPos.y)) {
        return 0;
    }
    if ((0 > rayPos.z) || (gridSize <= rayPos.z)) {
        return 0;
    }

    return cubesIn[rayPos.x][rayPos.y][rayPos.z].type;
}
harsh turret
#

Probably a problem with packing, see std140 rules. Any reason to use that memory layout instead of std430?

#

And also: Is Pos (host) = uint? If not you have a type-mismatch in your shader

#

It looks like on the host you have a 3-dimensional array of vectors and in the shader a 3-dimenasional arrray of unsigned integers instead

arctic surge
#

You're right with std430 the data have the good size but are always random

#

I used std::vector to create an array of an array of an array of Pos and Pos.type is an uint

harsh turret
#

are you sure it's always random? Did you check buffer contents in RenderDoc?

arctic surge
#

I'm checking that but my renderdoc has a problem

#

i need to reinstall it

arctic surge
#

You are right it's not random
1760013776, 295, 1760013968, 295, 1760013968, 295, 1760021056, 295, 1760021248, 295, 1760021248

#

Isn't this an alignment problem?

harsh turret
#

Most probably yes. But hard to judge without knowing more details.

#

If you suspect an alignment problem, make sure host and device structures/datatypes use the same alignment

#

alignas on the host side may help

arctic surge
#

yes thank you I will try tomorrow

arctic surge
#

there is the format provided by renderdoc

#pack(std430)

struct Cube
{
    uint type;
}

struct Cube_8_8
{
    Cube _0[8];
    Cube _1[8];
    Cube _2[8];
    Cube _3[8];
    Cube _4[8];
    Cube _5[8];
    Cube _6[8];
    Cube _7[8];
}

struct Cube_8_8_8
{
    Cube_8_8 _0;
    Cube_8_8 _1;
    Cube_8_8 _2;
    Cube_8_8 _3;
    Cube_8_8 _4;
    Cube_8_8 _5;
    Cube_8_8 _6;
    Cube_8_8 _7;
}

struct cubesSSBOIn
{
    Cube_8_8_8 cubesIn;
}
graceful kernel
harsh turret
graceful kernel
#

ahh

graceful kernel
arctic surge
#

nothing

#

what do you mean

#

the data

graceful kernel
#

I mean your renderdoc should be looking like this

arctic surge
harsh turret
#

alignment issues. Did you make sure that the strctures on host and device have the same alignments/paddings?

#

should be easy to check, esp. with simple data types

graceful kernel
#

and where do you write to it? the C code you've shown does not contain

struct Cube {
  uint type;
};
harsh turret
#

See above, it's all there

arctic surge
#

it is pos

harsh turret
#

It still looks kinda wrong for me, as if shader and c++ ode use wrong types, but OP said that it's correct

arctic surge
graceful kernel
#

std::vector<std::vector<std::vector<Pos > > > cubeCoos(MAP_SIZE, std::vector<std::vector<Pos> >(MAP_SIZE, std::vector<Pos>(MAP_SIZE)));

memcpy(data, cubeCoos.data(), (size_t)bufferSize);
you cannot memcpy a 3D vector like that

harsh turret
#

Good catch. Guess my C++ is not good enough to catch stuff like that ^^

graceful kernel
#

nah I'm just used to finding all the stilly places people mess up

arctic surge
#

I'm fixing it

arctic surge
#

tanks you for the help it work now
Didn't know how to memcpy a 3D array so I do it with a 1D array in c++ and 3D array in the shader
and for it to work I put std140 back

#

[FIXED] pass 3 dimensional array to frag with storage buffer