diff --git a/Makefile.am b/Makefile.am index 9624485b..5cdccc52 100644 --- a/Makefile.am +++ b/Makefile.am @@ -173,6 +173,7 @@ libvkd3d_shader_la_SOURCES = \ libs/vkd3d-shader/hlsl.h \ libs/vkd3d-shader/hlsl_codegen.c \ libs/vkd3d-shader/hlsl_sm1.c \ + libs/vkd3d-shader/hlsl_sm4.c \ libs/vkd3d-shader/preproc.h \ libs/vkd3d-shader/sm4.h \ libs/vkd3d-shader/spirv.c \ diff --git a/libs/vkd3d-shader/dxbc.c b/libs/vkd3d-shader/dxbc.c index 5dfe9295..83f91960 100644 --- a/libs/vkd3d-shader/dxbc.c +++ b/libs/vkd3d-shader/dxbc.c @@ -1,5 +1,6 @@ /* * Copyright 2008-2009 Henri Verbeet for CodeWeavers + * Copyright 2010 Rico Schüller * Copyright 2017 Józef Kucia for CodeWeavers * * This library is free software; you can redistribute it and/or @@ -20,6 +21,64 @@ #include "vkd3d_shader_private.h" #include "sm4.h" +void dxbc_writer_init(struct dxbc_writer *dxbc) +{ + memset(dxbc, 0, sizeof(*dxbc)); +} + +void dxbc_writer_add_section(struct dxbc_writer *dxbc, uint32_t tag, const void *data, size_t size) +{ + struct dxbc_writer_section *section; + + assert(dxbc->section_count < ARRAY_SIZE(dxbc->sections)); + + section = &dxbc->sections[dxbc->section_count++]; + section->tag = tag; + section->data = data; + section->size = size; +} + +int dxbc_writer_write(struct dxbc_writer *dxbc, struct vkd3d_shader_code *out) +{ + size_t size_position, offsets_position, checksum_position, i; + struct vkd3d_bytecode_buffer buffer = {0}; + uint32_t checksum[4]; + + put_u32(&buffer, TAG_DXBC); + + checksum_position = bytecode_get_size(&buffer); + for (i = 0; i < 4; ++i) + put_u32(&buffer, 0); + + put_u32(&buffer, 1); /* version */ + size_position = put_u32(&buffer, 0); + put_u32(&buffer, dxbc->section_count); + + offsets_position = bytecode_get_size(&buffer); + for (i = 0; i < dxbc->section_count; ++i) + put_u32(&buffer, 0); + + for (i = 0; i < dxbc->section_count; ++i) + { + set_u32(&buffer, offsets_position + i * sizeof(uint32_t), bytecode_get_size(&buffer)); + put_u32(&buffer, dxbc->sections[i].tag); + put_u32(&buffer, dxbc->sections[i].size); + bytecode_put_bytes(&buffer, dxbc->sections[i].data, dxbc->sections[i].size); + } + set_u32(&buffer, size_position, bytecode_get_size(&buffer)); + + vkd3d_compute_dxbc_checksum(buffer.data, buffer.size, checksum); + for (i = 0; i < 4; ++i) + set_u32(&buffer, checksum_position + i * sizeof(uint32_t), checksum[i]); + + if (!buffer.status) + { + out->code = buffer.data; + out->size = buffer.size; + } + return buffer.status; +} + struct vkd3d_shader_src_param_entry { struct list entry; @@ -1592,22 +1651,6 @@ bool shader_sm4_is_end(void *data, const DWORD **ptr) return *ptr == priv->end; } -#define MAKE_TAG(ch0, ch1, ch2, ch3) \ - ((DWORD)(ch0) | ((DWORD)(ch1) << 8) | \ - ((DWORD)(ch2) << 16) | ((DWORD)(ch3) << 24 )) -#define TAG_DXBC MAKE_TAG('D', 'X', 'B', 'C') -#define TAG_ISGN MAKE_TAG('I', 'S', 'G', 'N') -#define TAG_ISG1 MAKE_TAG('I', 'S', 'G', '1') -#define TAG_OSGN MAKE_TAG('O', 'S', 'G', 'N') -#define TAG_OSG5 MAKE_TAG('O', 'S', 'G', '5') -#define TAG_OSG1 MAKE_TAG('O', 'S', 'G', '1') -#define TAG_PCSG MAKE_TAG('P', 'C', 'S', 'G') -#define TAG_PSG1 MAKE_TAG('P', 'S', 'G', '1') -#define TAG_SHDR MAKE_TAG('S', 'H', 'D', 'R') -#define TAG_SHEX MAKE_TAG('S', 'H', 'E', 'X') -#define TAG_AON9 MAKE_TAG('A', 'o', 'n', '9') -#define TAG_RTS0 MAKE_TAG('R', 'T', 'S', '0') - static bool require_space(size_t offset, size_t count, size_t size, size_t data_size) { return !count || (data_size - offset) / count >= size; diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index da309a6b..41c16b07 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -683,6 +683,8 @@ bool hlsl_sm1_register_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_sem bool hlsl_sm1_usage_from_semantic(const struct hlsl_semantic *semantic, D3DDECLUSAGE *usage, uint32_t *usage_idx); int hlsl_sm1_write(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, struct vkd3d_shader_code *out); +int hlsl_sm4_write(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, struct vkd3d_shader_code *out); + int hlsl_lexer_compile(struct hlsl_ctx *ctx, const struct vkd3d_shader_code *hlsl); #endif diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index db340a78..b5f7832f 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -1272,5 +1272,5 @@ int hlsl_emit_dxbc(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_fun if (ctx->profile->major_version < 4) return hlsl_sm1_write(ctx, entry_func, out); else - return VKD3D_ERROR_NOT_IMPLEMENTED; + return hlsl_sm4_write(ctx, entry_func, out); } diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c new file mode 100644 index 00000000..977b8395 --- /dev/null +++ b/libs/vkd3d-shader/hlsl_sm4.c @@ -0,0 +1,31 @@ +/* + * HLSL code generation for DXBC shader models 4-5 + * + * Copyright 2019-2020 Zebediah Figura for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "hlsl.h" +#include + +int hlsl_sm4_write(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, struct vkd3d_shader_code *out) +{ + struct dxbc_writer dxbc; + + dxbc_writer_init(&dxbc); + + return dxbc_writer_write(&dxbc, out); +} diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index b490b9ca..ad2d3d18 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -1137,4 +1137,39 @@ static inline void *vkd3d_find_struct_(const struct vkd3d_struct *chain, #define VKD3D_DXBC_MAX_SOURCE_COUNT 6 #define VKD3D_DXBC_HEADER_SIZE (8 * sizeof(uint32_t)) +#define MAKE_TAG(ch0, ch1, ch2, ch3) \ + ((DWORD)(ch0) | ((DWORD)(ch1) << 8) | \ + ((DWORD)(ch2) << 16) | ((DWORD)(ch3) << 24 )) +#define TAG_AON9 MAKE_TAG('A', 'o', 'n', '9') +#define TAG_DXBC MAKE_TAG('D', 'X', 'B', 'C') +#define TAG_ISG1 MAKE_TAG('I', 'S', 'G', '1') +#define TAG_ISGN MAKE_TAG('I', 'S', 'G', 'N') +#define TAG_OSG1 MAKE_TAG('O', 'S', 'G', '1') +#define TAG_OSG5 MAKE_TAG('O', 'S', 'G', '5') +#define TAG_OSGN MAKE_TAG('O', 'S', 'G', 'N') +#define TAG_PCSG MAKE_TAG('P', 'C', 'S', 'G') +#define TAG_PSG1 MAKE_TAG('P', 'S', 'G', '1') +#define TAG_RTS0 MAKE_TAG('R', 'T', 'S', '0') +#define TAG_SHDR MAKE_TAG('S', 'H', 'D', 'R') +#define TAG_SHEX MAKE_TAG('S', 'H', 'E', 'X') + +struct dxbc_writer_section +{ + uint32_t tag; + const uint8_t *data; + size_t size; +}; + +#define DXBC_MAX_SECTION_COUNT 5 + +struct dxbc_writer +{ + unsigned int section_count; + struct dxbc_writer_section sections[DXBC_MAX_SECTION_COUNT]; +}; + +void dxbc_writer_add_section(struct dxbc_writer *dxbc, uint32_t tag, const void *data, size_t size); +void dxbc_writer_init(struct dxbc_writer *dxbc); +int dxbc_writer_write(struct dxbc_writer *dxbc, struct vkd3d_shader_code *code); + #endif /* __VKD3D_SHADER_PRIVATE_H */ diff --git a/tests/d3d12_test_utils.h b/tests/d3d12_test_utils.h index 5fe6f1ef..0374d8d1 100644 --- a/tests/d3d12_test_utils.h +++ b/tests/d3d12_test_utils.h @@ -844,7 +844,7 @@ static ID3D12PipelineState *create_pipeline_state_(unsigned int line, ID3D12Devi &IID_ID3D12PipelineState, (void **)&pipeline_state); ok_(line)(SUCCEEDED(hr), "Failed to create graphics pipeline state, hr %#x.\n", hr); - return pipeline_state; + return SUCCEEDED(hr) ? pipeline_state : NULL; } struct test_context_desc diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c index 353e42c7..3cc859ab 100644 --- a/tests/shader_runner_d3d12.c +++ b/tests/shader_runner_d3d12.c @@ -141,6 +141,8 @@ static void parse_test_directive(struct shader_context *context, const char *lin pso = create_pipeline_state(context->c.device, context->c.root_signature, context->c.render_target_desc.Format, NULL, &ps, NULL); + if (!pso) + return; ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context->c.root_signature); ID3D12GraphicsCommandList_SetGraphicsRoot32BitConstants(command_list, 0,