From 696fc120613114638535a71d47b300f1589a1cb3 Mon Sep 17 00:00:00 2001 From: Conor McCarthy Date: Wed, 10 Apr 2024 13:51:06 +1000 Subject: [PATCH] tests/hlsl: Add tests for GetSamplePosition() and GetSampleCount(). --- Makefile.am | 2 + tests/d3d12_test_utils.h | 10 ++--- tests/hlsl/get-sample-pos.shader_test | 19 +++++++++ tests/hlsl/rt-get-sample-info.shader_test | 34 +++++++++++++++ tests/shader_runner.c | 35 ++++++++++++--- tests/shader_runner.h | 4 ++ tests/shader_runner_d3d11.c | 52 ++++++++++++++++++++--- tests/shader_runner_d3d12.c | 42 ++++++++++++------ tests/shader_runner_gl.c | 24 +++++++++-- 9 files changed, 188 insertions(+), 34 deletions(-) create mode 100644 tests/hlsl/get-sample-pos.shader_test create mode 100644 tests/hlsl/rt-get-sample-info.shader_test diff --git a/Makefile.am b/Makefile.am index 2ad556c7..c5838e6f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -115,6 +115,7 @@ vkd3d_shader_tests = \ tests/hlsl/fxgroup-syntax.shader_test \ tests/hlsl/gather-offset.shader_test \ tests/hlsl/gather.shader_test \ + tests/hlsl/get-sample-pos.shader_test \ tests/hlsl/getdimensions.shader_test \ tests/hlsl/half.shader_test \ tests/hlsl/hard-copy-prop.shader_test \ @@ -171,6 +172,7 @@ vkd3d_shader_tests = \ tests/hlsl/return-implicit-conversion.shader_test \ tests/hlsl/return.shader_test \ tests/hlsl/round.shader_test \ + tests/hlsl/rt-get-sample-info.shader_test \ tests/hlsl/sample-bias.shader_test \ tests/hlsl/sample-cmp.shader_test \ tests/hlsl/sample-grad.shader_test \ diff --git a/tests/d3d12_test_utils.h b/tests/d3d12_test_utils.h index 4fe6fa71..85747297 100644 --- a/tests/d3d12_test_utils.h +++ b/tests/d3d12_test_utils.h @@ -582,8 +582,8 @@ static inline ID3D12Resource *create_default_buffer_(unsigned int line, ID3D12De static ID3D12Resource *create_default_texture_(unsigned int line, ID3D12Device *device, D3D12_RESOURCE_DIMENSION dimension, unsigned int width, unsigned int height, - unsigned int depth_or_array_size, unsigned int miplevel_count, DXGI_FORMAT format, - D3D12_RESOURCE_FLAGS flags, D3D12_RESOURCE_STATES initial_state) + unsigned int depth_or_array_size, unsigned int miplevel_count, unsigned int sample_count, + DXGI_FORMAT format, D3D12_RESOURCE_FLAGS flags, D3D12_RESOURCE_STATES initial_state) { D3D12_HEAP_PROPERTIES heap_properties; D3D12_RESOURCE_DESC resource_desc; @@ -602,7 +602,7 @@ static ID3D12Resource *create_default_texture_(unsigned int line, ID3D12Device * resource_desc.DepthOrArraySize = depth_or_array_size; resource_desc.MipLevels = miplevel_count; resource_desc.Format = format; - resource_desc.SampleDesc.Count = 1; + resource_desc.SampleDesc.Count = max(sample_count, 1); resource_desc.Flags = flags; hr = ID3D12Device_CreateCommittedResource(device, &heap_properties, D3D12_HEAP_FLAG_NONE, &resource_desc, initial_state, NULL, &IID_ID3D12Resource, (void **)&texture); @@ -618,7 +618,7 @@ static inline ID3D12Resource *create_default_texture2d_(unsigned int line, ID3D1 DXGI_FORMAT format, D3D12_RESOURCE_FLAGS flags, D3D12_RESOURCE_STATES initial_state) { return create_default_texture_(line, device, D3D12_RESOURCE_DIMENSION_TEXTURE2D, - width, height, array_size, miplevel_count, format, flags, initial_state); + width, height, array_size, miplevel_count, 1, format, flags, initial_state); } #define create_default_texture3d(a, b, c, d, e, f, g, h) create_default_texture3d_(__LINE__, a, b, c, d, e, f, g, h) @@ -627,7 +627,7 @@ static inline ID3D12Resource *create_default_texture3d_(unsigned int line, ID3D1 DXGI_FORMAT format, D3D12_RESOURCE_FLAGS flags, D3D12_RESOURCE_STATES initial_state) { return create_default_texture_(line, device, D3D12_RESOURCE_DIMENSION_TEXTURE3D, - width, height, depth, miplevel_count, format, flags, initial_state); + width, height, depth, miplevel_count, 1, format, flags, initial_state); } static void copy_sub_resource_data(const D3D12_MEMCPY_DEST *dst, const D3D12_SUBRESOURCE_DATA *src, diff --git a/tests/hlsl/get-sample-pos.shader_test b/tests/hlsl/get-sample-pos.shader_test new file mode 100644 index 00000000..23dbba67 --- /dev/null +++ b/tests/hlsl/get-sample-pos.shader_test @@ -0,0 +1,19 @@ +[require] +shader model >= 4.1 + + +[srv 0] +format r32g32b32a32 float +size (2dms, 4, 2, 2) + +[pixel shader todo] +Texture2DMS t; + +float4 main() : sv_target +{ + return float4(t.GetSamplePosition(0), t.GetSamplePosition(1)); +} + +[test] +todo draw quad +probe all rgba (-0.125, -0.375, 0.375, -0.125) diff --git a/tests/hlsl/rt-get-sample-info.shader_test b/tests/hlsl/rt-get-sample-info.shader_test new file mode 100644 index 00000000..52353f29 --- /dev/null +++ b/tests/hlsl/rt-get-sample-info.shader_test @@ -0,0 +1,34 @@ +[require] +shader model >= 4.1 + + +[rtv 0] +format r32g32b32a32 float +size (2dms, 4, 640, 480) + +[pixel shader todo] +float4 main() : sv_target +{ + return float4(GetRenderTargetSampleCount(), 0, 0, 0); +} + +[test] +todo draw quad +probe all rgba (4.0, 0.0, 0.0, 0.0) + + +[pixel shader todo] +uniform uint u; + +float4 main() : sv_target +{ + return float4(GetRenderTargetSamplePosition(u), GetRenderTargetSamplePosition(u + 1)); +} + +[test] +uniform 0 uint 0 +todo draw quad +probe all rgba (-0.125, -0.375, 0.375, -0.125) +uniform 0 uint 2 +todo draw quad +probe all rgba (-0.375, 0.125, 0.125, 0.375) diff --git a/tests/shader_runner.c b/tests/shader_runner.c index 359eafb9..2dc0b0df 100644 --- a/tests/shader_runner.c +++ b/tests/shader_runner.c @@ -513,6 +513,10 @@ static void parse_resource_directive(struct resource_params *resource, const cha { resource->dimension = RESOURCE_DIMENSION_2D; } + else if (sscanf(line, "( 2dms , %u , %u , %u ) ", &resource->sample_count, &resource->width, &resource->height) == 3) + { + resource->dimension = RESOURCE_DIMENSION_2D; + } else { fatal_error("Malformed resource size '%s'.\n", line); @@ -604,6 +608,7 @@ void init_resource(struct resource *resource, const struct resource_params *para resource->texel_size = params->texel_size; resource->width = params->width; resource->height = params->height; + resource->sample_count = params->sample_count; } struct resource *shader_runner_get_resource(struct shader_runner *runner, enum resource_type type, unsigned int slot) @@ -622,10 +627,28 @@ struct resource *shader_runner_get_resource(struct shader_runner *runner, enum r return NULL; } -static void set_resource(struct shader_runner *runner, struct resource *resource) +static void set_resource(struct shader_runner *runner, const struct resource_params *params) { + struct resource *resource; size_t i; + if (!(resource = runner->ops->create_resource(runner, params))) + { + if (!bitmap_is_set(runner->failed_resources[params->type], params->slot)) + { + ++runner->failed_resource_count; + bitmap_set(runner->failed_resources[params->type], params->slot); + } + return; + } + + if (bitmap_is_set(runner->failed_resources[params->type], params->slot)) + { + assert(runner->failed_resource_count); + --runner->failed_resource_count; + bitmap_clear(runner->failed_resources[params->type], params->slot); + } + for (i = 0; i < runner->resource_count; ++i) { if (runner->resources[i]->slot == resource->slot && runner->resources[i]->type == resource->type) @@ -838,7 +861,7 @@ static void parse_test_directive(struct shader_runner *runner, const char *line) params.height = RENDER_TARGET_HEIGHT; params.level_count = 1; - set_resource(runner, runner->ops->create_resource(runner, ¶ms)); + set_resource(runner, ¶ms); } for (i = 0; i < runner->input_element_count; ++i) @@ -861,7 +884,7 @@ static void parse_test_directive(struct shader_runner *runner, const char *line) params.data = malloc(sizeof(quad)); memcpy(params.data, quad, sizeof(quad)); params.data_size = sizeof(quad); - set_resource(runner, runner->ops->create_resource(runner, ¶ms)); + set_resource(runner, ¶ms); free(params.data); if (!runner->vs_source) @@ -891,7 +914,7 @@ static void parse_test_directive(struct shader_runner *runner, const char *line) params.height = RENDER_TARGET_HEIGHT; params.level_count = 1; - set_resource(runner, runner->ops->create_resource(runner, ¶ms)); + set_resource(runner, ¶ms); } if (match_string(line, "triangle list", &line)) @@ -1574,7 +1597,7 @@ void run_shader_tests(struct shader_runner *runner, const struct shader_runner_c * textures with data type other than float). */ if (!skip_tests) { - set_resource(runner, runner->ops->create_resource(runner, ¤t_resource)); + set_resource(runner, ¤t_resource); } free(current_resource.data); break; @@ -1922,7 +1945,7 @@ void run_shader_tests(struct shader_runner *runner, const struct shader_runner_c case STATE_TEST: /* Compilation which fails with dxcompiler is not 'todo', therefore the tests are * not 'todo' either. They cannot run, so skip them entirely. */ - if (!skip_tests && SUCCEEDED(expect_hr)) + if (!runner->failed_resource_count && !skip_tests && SUCCEEDED(expect_hr)) parse_test_directive(runner, line); break; } diff --git a/tests/shader_runner.h b/tests/shader_runner.h index dd92048f..73cec54d 100644 --- a/tests/shader_runner.h +++ b/tests/shader_runner.h @@ -96,6 +96,7 @@ struct resource_params unsigned int stride; unsigned int width, height; unsigned int level_count; + unsigned int sample_count; uint8_t *data; size_t data_size, data_capacity; }; @@ -110,6 +111,7 @@ struct resource unsigned int size; unsigned int texel_size; unsigned int width, height; + unsigned int sample_count; }; struct input_element @@ -174,6 +176,8 @@ struct shader_runner struct resource *resources[MAX_RESOURCES]; size_t resource_count; + uint32_t failed_resources[RESOURCE_TYPE_VERTEX_BUFFER + 1][(MAX_RESOURCES + 0x1f) / 0x20]; + unsigned int failed_resource_count; struct sampler samplers[MAX_SAMPLERS]; size_t sampler_count; diff --git a/tests/shader_runner_d3d11.c b/tests/shader_runner_d3d11.c index bc1c5c5f..395b7ef2 100644 --- a/tests/shader_runner_d3d11.c +++ b/tests/shader_runner_d3d11.c @@ -355,23 +355,37 @@ static ID3D11Buffer *create_buffer(ID3D11Device *device, unsigned int bind_flags return buffer; } -static void init_resource_2d(struct d3d11_shader_runner *runner, struct d3d11_resource *resource, +static bool init_resource_2d(struct d3d11_shader_runner *runner, struct d3d11_resource *resource, const struct resource_params *params) { D3D11_SUBRESOURCE_DATA resource_data[3]; ID3D11Device *device = runner->device; D3D11_TEXTURE2D_DESC desc = {0}; + UINT quality_levels; HRESULT hr; if (params->level_count > ARRAY_SIZE(resource_data)) fatal_error("Level count %u is too high.\n", params->level_count); + if (params->sample_count > 1) + { + if (params->level_count > 1) + fatal_error("Multisampled texture has multiple levels.\n"); + + if (FAILED(ID3D11Device_CheckMultisampleQualityLevels(device, + params->format, params->sample_count, &quality_levels)) || !quality_levels) + { + trace("Format #%x with sample count %u is not supported; skipping.\n", params->format, params->sample_count); + return false; + } + } + desc.Width = params->width; desc.Height = params->height; desc.MipLevels = params->level_count; desc.ArraySize = 1; desc.Format = params->format; - desc.SampleDesc.Count = 1; + desc.SampleDesc.Count = max(params->sample_count, 1); desc.Usage = D3D11_USAGE_DEFAULT; if (params->type == RESOURCE_TYPE_UAV) desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS; @@ -384,6 +398,9 @@ static void init_resource_2d(struct d3d11_shader_runner *runner, struct d3d11_re { unsigned int buffer_offset = 0; + if (params->sample_count > 1) + fatal_error("Cannot upload data to a multisampled texture.\n"); + for (unsigned int level = 0; level < params->level_count; ++level) { unsigned int level_width = get_level_dimension(params->width, level); @@ -410,6 +427,8 @@ static void init_resource_2d(struct d3d11_shader_runner *runner, struct d3d11_re else hr = ID3D11Device_CreateShaderResourceView(device, resource->resource, NULL, &resource->srv); ok(hr == S_OK, "Failed to create view, hr %#lx.\n", hr); + + return true; } static void init_resource_srv_buffer(struct d3d11_shader_runner *runner, struct d3d11_resource *resource, @@ -465,15 +484,15 @@ static struct resource *d3d11_runner_create_resource(struct shader_runner *r, co case RESOURCE_TYPE_TEXTURE: if (params->dimension == RESOURCE_DIMENSION_BUFFER) init_resource_srv_buffer(runner, resource, params); - else - init_resource_2d(runner, resource, params); + else if (!init_resource_2d(runner, resource, params)) + return NULL; break; case RESOURCE_TYPE_UAV: if (params->dimension == RESOURCE_DIMENSION_BUFFER) init_resource_uav_buffer(runner, resource, params); - else - init_resource_2d(runner, resource, params); + else if (!init_resource_2d(runner, resource, params)) + return NULL; break; case RESOURCE_TYPE_VERTEX_BUFFER: @@ -774,12 +793,15 @@ static struct resource_readback *d3d11_runner_get_resource_readback(struct shade { struct d3d11_shader_runner *runner = d3d11_shader_runner(r); struct d3d11_resource_readback *rb = malloc(sizeof(*rb)); + ID3D11Resource *resolved_resource = NULL, *src_resource; struct d3d11_resource *resource = d3d11_resource(res); D3D11_TEXTURE2D_DESC texture_desc; D3D11_MAPPED_SUBRESOURCE map_desc; D3D11_BUFFER_DESC buffer_desc; + bool is_ms = false; HRESULT hr; + src_resource = resource->resource; switch (resource->r.type) { case RESOURCE_TYPE_RENDER_TARGET: @@ -797,12 +819,25 @@ static struct resource_readback *d3d11_runner_get_resource_readback(struct shade else { ID3D11Texture2D_GetDesc(resource->texture, &texture_desc); + is_ms = texture_desc.SampleDesc.Count > 1; + texture_desc.SampleDesc.Count = 1; + texture_desc.SampleDesc.Quality = 0; texture_desc.Usage = D3D11_USAGE_STAGING; texture_desc.BindFlags = 0; texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; texture_desc.MiscFlags = 0; hr = ID3D11Device_CreateTexture2D(runner->device, &texture_desc, NULL, (ID3D11Texture2D **)&rb->resource); ok(hr == S_OK, "Failed to create texture, hr %#lx.\n", hr); + if (is_ms) + { + texture_desc.Usage = D3D11_USAGE_DEFAULT; + hr = ID3D11Device_CreateTexture2D(runner->device, &texture_desc, NULL, + (ID3D11Texture2D **)&resolved_resource); + ok(hr == S_OK, "Failed to create multisampled texture, hr %#lx.\n", hr); + ID3D11DeviceContext_ResolveSubresource(runner->immediate_context, resolved_resource, 0, + resource->resource, 0, texture_desc.Format); + src_resource = resolved_resource; + } } break; @@ -814,10 +849,13 @@ static struct resource_readback *d3d11_runner_get_resource_readback(struct shade if (resource->is_uav_counter) ID3D11DeviceContext_CopyStructureCount(runner->immediate_context, (ID3D11Buffer *)rb->resource, 0, resource->uav); else - ID3D11DeviceContext_CopyResource(runner->immediate_context, rb->resource, resource->resource); + ID3D11DeviceContext_CopyResource(runner->immediate_context, rb->resource, src_resource); hr = ID3D11DeviceContext_Map(runner->immediate_context, rb->resource, 0, D3D11_MAP_READ, 0, &map_desc); ok(hr == S_OK, "Failed to map texture, hr %#lx.\n", hr); + if (resolved_resource) + ID3D11Resource_Release(resolved_resource); + rb->rb.data = map_desc.pData; rb->rb.row_pitch = map_desc.RowPitch; rb->rb.width = resource->r.width; diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c index 48792fa7..eab3c61f 100644 --- a/tests/shader_runner_d3d12.c +++ b/tests/shader_runner_d3d12.c @@ -135,9 +135,12 @@ static struct resource *d3d12_runner_create_resource(struct shader_runner *r, co if (params->slot >= D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT) fatal_error("RTV slot %u is too high.\n", params->slot); + if (params->sample_count > 1 && params->level_count > 1) + fatal_error("Multisampled texture has multiple levels.\n"); - resource->resource = create_default_texture2d(device, params->width, params->height, 1, params->level_count, - params->format, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET, D3D12_RESOURCE_STATE_RENDER_TARGET); + resource->resource = create_default_texture_(__LINE__, device, D3D12_RESOURCE_DIMENSION_TEXTURE2D, + params->width, params->height, 1, params->level_count, params->sample_count, params->format, + D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET, D3D12_RESOURCE_STATE_RENDER_TARGET); ID3D12Device_CreateRenderTargetView(device, resource->resource, NULL, get_cpu_rtv_handle(test_context, runner->rtv_heap, resource->r.slot)); break; @@ -169,13 +172,26 @@ static struct resource *d3d12_runner_create_resource(struct shader_runner *r, co } else { - resource->resource = create_default_texture2d(device, params->width, params->height, 1, params->level_count, - params->format, 0, D3D12_RESOURCE_STATE_COPY_DEST); - upload_texture_data_with_states(resource->resource, resource_data, - params->level_count, test_context->queue, test_context->list, - RESOURCE_STATE_DO_NOT_CHANGE, - D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); - reset_command_list(test_context->list, test_context->allocator); + if (params->sample_count > 1 && params->level_count > 1) + fatal_error("Multisampled texture has multiple levels.\n"); + + resource->resource = create_default_texture_(__LINE__, device, D3D12_RESOURCE_DIMENSION_TEXTURE2D, + params->width, params->height, 1, params->level_count, params->sample_count, params->format, + /* Multisampled textures must have ALLOW_RENDER_TARGET set. */ + (params->sample_count > 1) ? D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET : 0, + D3D12_RESOURCE_STATE_COPY_DEST); + + if (params->data) + { + if (params->sample_count > 1) + fatal_error("Cannot upload data to a multisampled texture.\n"); + upload_texture_data_with_states(resource->resource, resource_data, + params->level_count, test_context->queue, test_context->list, + RESOURCE_STATE_DO_NOT_CHANGE, + D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); + reset_command_list(test_context->list, test_context->allocator); + } + ID3D12Device_CreateShaderResourceView(device, resource->resource, NULL, get_cpu_descriptor_handle(test_context, runner->heap, resource->r.slot)); } @@ -440,7 +456,7 @@ static bool d3d12_runner_draw(struct shader_runner *r, ID3D12CommandQueue *queue = test_context->queue; D3D12_INPUT_ELEMENT_DESC *input_element_descs; ID3D12Device *device = test_context->device; - unsigned int uniform_index; + unsigned int uniform_index, sample_count; unsigned int rtv_count = 0; ID3D12PipelineState *pso; bool succeeded; @@ -483,7 +499,7 @@ static bool d3d12_runner_draw(struct shader_runner *r, test_context->root_signature = d3d12_runner_create_root_signature(runner, queue, test_context->allocator, command_list, &uniform_index); - for (i = 0; i < runner->r.resource_count; ++i) + for (i = 0, sample_count = 1; i < runner->r.resource_count; ++i) { struct d3d12_resource *resource = d3d12_resource(runner->r.resources[i]); @@ -492,6 +508,8 @@ static bool d3d12_runner_draw(struct shader_runner *r, pso_desc.RTVFormats[resource->r.slot] = resource->r.format; pso_desc.NumRenderTargets = max(pso_desc.NumRenderTargets, resource->r.slot + 1); pso_desc.BlendState.RenderTarget[resource->r.slot].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; + if (resource->r.sample_count) + sample_count = resource->r.sample_count; } } @@ -513,7 +531,7 @@ static bool d3d12_runner_draw(struct shader_runner *r, } pso_desc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID; pso_desc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE; - pso_desc.SampleDesc.Count = 1; + pso_desc.SampleDesc.Count = sample_count; pso_desc.SampleMask = ~(UINT)0; pso_desc.pRootSignature = test_context->root_signature; diff --git a/tests/shader_runner_gl.c b/tests/shader_runner_gl.c index 221f3564..3b0a77e8 100644 --- a/tests/shader_runner_gl.c +++ b/tests/shader_runner_gl.c @@ -112,6 +112,7 @@ static bool check_gl_extensions(struct gl_runner *runner) "GL_ARB_sampler_objects", "GL_ARB_shader_image_load_store", "GL_ARB_texture_storage", + "GL_ARB_internalformat_query", }; glGetIntegerv(GL_NUM_EXTENSIONS, &count); @@ -347,11 +348,24 @@ static const struct format_info *get_format_info(enum DXGI_FORMAT format, bool i fatal_error("Failed to find format info for format %#x.\n", format); } -static void init_resource_2d(struct gl_resource *resource, const struct resource_params *params) +static bool init_resource_2d(struct gl_resource *resource, const struct resource_params *params) { unsigned int offset, w, h, i; resource->format = get_format_info(params->format, params->is_shadow); + + if (params->sample_count > 1) + { + GLint max_sample_count; + + glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, resource->format->internal_format, GL_SAMPLES, 1, &max_sample_count); + if (max_sample_count < params->sample_count) + { + trace("Format #%x with sample count %u is not supported; skipping.\n", params->format, params->sample_count); + return false; + } + } + glGenTextures(1, &resource->id); glBindTexture(GL_TEXTURE_2D, resource->id); glTexStorage2D(GL_TEXTURE_2D, params->level_count, @@ -359,7 +373,7 @@ static void init_resource_2d(struct gl_resource *resource, const struct resource glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); if (!params->data) - return; + return true; for (i = 0, offset = 0; i < params->level_count; ++i) { @@ -369,6 +383,8 @@ static void init_resource_2d(struct gl_resource *resource, const struct resource resource->format->type, params->data + offset); offset += w * h * params->texel_size; } + + return true; } static void init_resource_buffer(struct gl_resource *resource, const struct resource_params *params) @@ -398,8 +414,8 @@ static struct resource *gl_runner_create_resource(struct shader_runner *r, const case RESOURCE_TYPE_UAV: if (params->dimension == RESOURCE_DIMENSION_BUFFER) init_resource_buffer(resource, params); - else - init_resource_2d(resource, params); + else if (!init_resource_2d(resource, params)) + return NULL; break; case RESOURCE_TYPE_VERTEX_BUFFER: