Swapchain imageStore failing in HLSL

I’ve got two shaders that I think are equivalent, but clearly something is wrong. The GLSL one works fine; the HLSL one doesn’t seem to do anything. Debug printing shows that the dst_coords are cycling as expected.

Any advice would be apprecicated.

Thanks.

HLSL code:


#define CHUNK_SIZE_X 16
#define CHUNK_SIZE_Y 16

#define VARIABLE_ARRAY_ENTRIES 1

#define FILL_PATTERN_DIMENSIONS_X 16
#define FILL_PATTERN_DIMENSIONS_Y 16


struct PushData {
    uint2 dst_origin;
    uint dst_ww;
    uint dst_hh;
    uint u32_fill_pattern_index;
};

struct FillPatternBuffer {
    float4 px[VARIABLE_ARRAY_ENTRIES][FILL_PATTERN_DIMENSIONS_Y][FILL_PATTERN_DIMENSIONS_X];  // FIXME: CAREFUL!  Watch memory layouts
};


[[vk::push_constant]]
ConstantBuffer<PushData> pcb;
//ConstantBuffer<PushData> pcb : register(bX, spaceY);

// [[vk::binding(0, 0)]]
// ConstantBuffer<PushData> pdb;
// //ConstantBuffer<PushData> pdb : register(bX, spaceY);


// [[vk::binding(1, 0)]]
// ConstantBuffer<FillPatternBuffer> dp;
// //ConstantBuffer<FillPatternBuffer> dp : register(tX, spaceY);


[[vk::binding(2, 0)]]
[[vk::image_format("rgba8")]] RWTexture2D<float4> image_swapchain;

// [[vk::image_format("rgba8")]] RWTexture2D<float4> image_swapchain : register(u0, space0);


[numthreads(CHUNK_SIZE_X, CHUNK_SIZE_Y, 1)]  // equivalent to local_size
void main(uint3 Gid    : SV_GroupID,
            uint3 DTid : SV_DispatchThreadID, 
            uint3 GTid : SV_GroupThreadID, 
            uint GI    : SV_GroupIndex) {


    const uint2 CHUNK_SIZE_VEC = uint2(CHUNK_SIZE_X, CHUNK_SIZE_Y);

    const uint2 tile_coords = Gid.xy*CHUNK_SIZE_VEC+GTid.xy;
    
    const uint2 dst_coords = pcb.dst_origin + tile_coords;

    printf("%4v2d %4v2d\n", pcb.dst_origin, dst_coords);

    image_swapchain[dst_coords] = float4(0.0, 1.0, 0.0, 1.0);
}

GLSL code:

#version 460

#extension GL_EXT_debug_printf : enable
#extension GL_EXT_nonuniform_qualifier : require
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require
#extension GL_EXT_shader_explicit_arithmetic_types_int32 : require
#extension GL_EXT_scalar_block_layout : require

const uvec2 CHUNK_SIZE_VEC = uvec2(16, 16);  // FIXME: Possible to make this a specialization constant?

const uvec2 FILL_PATTERN_DIMENSIONS = uvec2(16, 16);

layout (local_size_x = CHUNK_SIZE_VEC.x, local_size_y = CHUNK_SIZE_VEC.y) in;  // Goes into gl_WorkGroupSize--iterates across gl_LocalInvocationID

struct PushData {
    uvec2 dst_origin;
    uint32_t dst_ww;
    uint32_t dst_hh;
    uint32_t u32_fill_pattern_index;
};

layout (push_constant, std430) uniform PushConstantBlock {
    PushData pd;
} pcb;

// layout (set = 0, binding = 0, std430) uniform PushDescriptorBlock {
//     PushData pd;
// } pdb;

// layout (set = 1, binding = 0, std430) readonly buffer FillPatternBuffer {
//     vec4 px[][FILL_PATTERN_DIMENSIONS.y][FILL_PATTERN_DIMENSIONS.x];  // NOTE ORDERING!  
// } dp;

layout (set = 2, binding = 0, rgba8) uniform image2D image_swapchain;  // RGBA8 matches the swapchain format VK_FORMAT_B8G8R8A8_UNORM

void main(){
    const uvec2 tile_coords = gl_WorkGroupID.xy*CHUNK_SIZE_VEC+gl_LocalInvocationID.xy;

    const ivec2 dst_coords = ivec2(pcb.pd.dst_origin + tile_coords);

    debugPrintfEXT("%4v2d %4v2d\n", pcb.pd.dst_origin, dst_coords);

    imageStore(image_swapchain, dst_coords, vec4(0.0, 1.0, 0.0, 1.0));
}

Do you have a difference between glsl to spirv and HLSL to spirv?
Do use glslang or DXC?