~~This one's marked as a draft, as there seems to be a blocker with the method parameters.~~
~~The first commit totally works, _if_ the ddx/ddy parameters are literals - they do _not_ work when passing a variable of any kind. The test comes from tests/d3d12.c, so I'm mostly just trying to migrate that to the HLSL test suite, but it currently hits an assert before we get to the resource load (which does eventually work) and I'm not sure what's causing it:~~
``` vkd3d-compiler: libs/vkd3d-shader/tpf.c:3190: sm4_register_from_node: Assertion `instr->reg.allocated' failed. ```
~~Seems like it's surprised when we try to load from the constant buffer maybe?~~ Fixed!
-- v8: vkd3d-shader/hlsl: Add support for SampleGrad() method tests: Add a test for SampleGrad() method tests: Add a test for SampleBias() with multiple mipmap levels. tests: Add a test for sampling from nonzero mipmap levels. tests: Add a test for loading from nonzero mipmap levels. tests/shader_runner: Add support for creating mipmapped textures.
From: Zebediah Figura zfigura@codeweavers.com
--- tests/shader_runner.c | 13 ++++++++++++ tests/shader_runner.h | 2 ++ tests/shader_runner_d3d11.c | 21 +++++++++++++------ tests/shader_runner_d3d12.c | 31 +++++++++++++++++++--------- tests/shader_runner_d3d9.c | 31 +++++++++++++++++++--------- tests/shader_runner_vulkan.c | 39 +++++++++++++++++++++++------------- 6 files changed, 98 insertions(+), 39 deletions(-)
diff --git a/tests/shader_runner.c b/tests/shader_runner.c index 8c66ff5e..8c0f59dc 100644 --- a/tests/shader_runner.c +++ b/tests/shader_runner.c @@ -251,6 +251,14 @@ static void parse_resource_directive(struct resource_params *resource, const cha if (ret < 2) fatal_error("Malformed texture size '%s'.\n", line); } + else if (match_string(line, "levels", &line)) + { + char *rest; + + resource->level_count = strtoul(line, &rest, 10); + if (rest == line) + fatal_error("Malformed texture directive '%s'.\n", line); + } else { union @@ -474,6 +482,7 @@ static void parse_test_directive(struct shader_runner *runner, const char *line) params.texel_size = 16; params.width = RENDER_TARGET_WIDTH; params.height = RENDER_TARGET_HEIGHT; + params.level_count = 1;
set_resource(runner, runner->ops->create_resource(runner, ¶ms)); } @@ -518,6 +527,7 @@ static void parse_test_directive(struct shader_runner *runner, const char *line) params.texel_size = 16; params.width = RENDER_TARGET_WIDTH; params.height = RENDER_TARGET_HEIGHT; + params.level_count = 1;
set_resource(runner, runner->ops->create_resource(runner, ¶ms)); } @@ -995,6 +1005,7 @@ void run_shader_tests(struct shader_runner *runner, const struct shader_runner_o current_resource.format = DXGI_FORMAT_R32G32B32A32_FLOAT; current_resource.data_type = TEXTURE_DATA_FLOAT; current_resource.texel_size = 16; + current_resource.level_count = 1; } else if (sscanf(line, "[texture %u]\n", &index)) { @@ -1007,6 +1018,7 @@ void run_shader_tests(struct shader_runner *runner, const struct shader_runner_o current_resource.format = DXGI_FORMAT_R32G32B32A32_FLOAT; current_resource.data_type = TEXTURE_DATA_FLOAT; current_resource.texel_size = 16; + current_resource.level_count = 1; } else if (sscanf(line, "[uav %u]\n", &index)) { @@ -1019,6 +1031,7 @@ void run_shader_tests(struct shader_runner *runner, const struct shader_runner_o current_resource.format = DXGI_FORMAT_R32G32B32A32_FLOAT; current_resource.data_type = TEXTURE_DATA_FLOAT; current_resource.texel_size = 16; + current_resource.level_count = 1; } else if (sscanf(line, "[vertex buffer %u]\n", &index)) { diff --git a/tests/shader_runner.h b/tests/shader_runner.h index ba42d7bf..b3333ac4 100644 --- a/tests/shader_runner.h +++ b/tests/shader_runner.h @@ -16,6 +16,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
+#include <float.h> #include <stdint.h> #include "vkd3d_windows.h" #include "vkd3d_d3dcommon.h" @@ -68,6 +69,7 @@ struct resource_params enum texture_data_type data_type; unsigned int texel_size; unsigned int width, height; + unsigned int level_count; uint8_t *data; size_t data_size, data_capacity; }; diff --git a/tests/shader_runner_d3d11.c b/tests/shader_runner_d3d11.c index 2954cab8..b9d782b2 100644 --- a/tests/shader_runner_d3d11.c +++ b/tests/shader_runner_d3d11.c @@ -338,7 +338,6 @@ static struct resource *d3d11_runner_create_resource(struct shader_runner *r, co { struct d3d11_shader_runner *runner = d3d11_shader_runner(r); ID3D11Device *device = runner->device; - D3D11_SUBRESOURCE_DATA resource_data; struct d3d11_resource *resource; HRESULT hr;
@@ -351,11 +350,15 @@ static struct resource *d3d11_runner_create_resource(struct shader_runner *r, co case RESOURCE_TYPE_TEXTURE: case RESOURCE_TYPE_UAV: { + D3D11_SUBRESOURCE_DATA resource_data[2]; D3D11_TEXTURE2D_DESC desc = {0};
+ if (params->level_count > ARRAY_SIZE(resource_data)) + fatal_error("Level count %u is too high.\n", params->level_count); + desc.Width = params->width; desc.Height = params->height; - desc.MipLevels = 1; + desc.MipLevels = params->level_count; desc.ArraySize = 1; desc.Format = params->format; desc.SampleDesc.Count = 1; @@ -369,10 +372,16 @@ static struct resource *d3d11_runner_create_resource(struct shader_runner *r, co
if (params->data) { - resource_data.pSysMem = params->data; - resource_data.SysMemPitch = params->width * params->texel_size; - resource_data.SysMemSlicePitch = params->height * resource_data.SysMemPitch; - hr = ID3D11Device_CreateTexture2D(device, &desc, &resource_data, &resource->texture); + unsigned int buffer_offset = 0; + + for (unsigned int level = 0; level < params->level_count; ++level) + { + resource_data[level].pSysMem = params->data + buffer_offset; + resource_data[level].SysMemPitch = (params->width >> level) * params->texel_size; + resource_data[level].SysMemSlicePitch = (params->height >> level) * resource_data[level].SysMemPitch; + buffer_offset += resource_data[level].SysMemSlicePitch; + } + hr = ID3D11Device_CreateTexture2D(device, &desc, resource_data, &resource->texture); } else { diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c index 7e9fed25..07cc5b7b 100644 --- a/tests/shader_runner_d3d12.c +++ b/tests/shader_runner_d3d12.c @@ -90,12 +90,24 @@ static struct resource *d3d12_runner_create_resource(struct shader_runner *r, co struct d3d12_shader_runner *runner = d3d12_shader_runner(r); struct test_context *test_context = &runner->test_context; ID3D12Device *device = test_context->device; - D3D12_SUBRESOURCE_DATA resource_data; + D3D12_SUBRESOURCE_DATA resource_data[2]; struct d3d12_resource *resource; + unsigned int buffer_offset = 0; + + if (params->level_count > ARRAY_SIZE(resource_data)) + fatal_error("Level count %u is too high.\n", params->level_count);
resource = calloc(1, sizeof(*resource)); init_resource(&resource->r, params);
+ for (unsigned int level = 0; level < params->level_count; ++level) + { + resource_data[level].pData = params->data + buffer_offset; + resource_data[level].RowPitch = (params->width >> level) * params->texel_size; + resource_data[level].SlicePitch = (params->height >> level) * resource_data[level].RowPitch; + buffer_offset += resource_data[level].SlicePitch; + } + switch (params->type) { case RESOURCE_TYPE_RENDER_TARGET: @@ -106,7 +118,7 @@ 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);
- resource->resource = create_default_texture(device, params->width, params->height, + 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); ID3D12Device_CreateRenderTargetView(device, resource->resource, NULL, get_cpu_rtv_handle(test_context, runner->rtv_heap, resource->r.slot)); @@ -117,11 +129,10 @@ static struct resource *d3d12_runner_create_resource(struct shader_runner *r, co runner->heap = create_gpu_descriptor_heap(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, MAX_RESOURCE_DESCRIPTORS);
- resource->resource = create_default_texture(device, params->width, params->height, + resource->resource = create_default_texture2d(device, params->width, params->height, 1, params->level_count, params->format, 0, D3D12_RESOURCE_STATE_COPY_DEST); - resource_data.pData = params->data; - resource_data.SlicePitch = resource_data.RowPitch = params->width * params->texel_size; - upload_texture_data(resource->resource, &resource_data, 1, test_context->queue, test_context->list); + upload_texture_data(resource->resource, resource_data, + params->level_count, test_context->queue, test_context->list); reset_command_list(test_context->list, test_context->allocator); transition_resource_state(test_context->list, resource->resource, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); @@ -134,11 +145,10 @@ static struct resource *d3d12_runner_create_resource(struct shader_runner *r, co runner->heap = create_gpu_descriptor_heap(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, MAX_RESOURCE_DESCRIPTORS);
- resource->resource = create_default_texture(device, params->width, params->height, + resource->resource = create_default_texture2d(device, params->width, params->height, 1, params->level_count, params->format, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_DEST); - resource_data.pData = params->data; - resource_data.SlicePitch = resource_data.RowPitch = params->width * params->texel_size; - upload_texture_data(resource->resource, &resource_data, 1, test_context->queue, test_context->list); + upload_texture_data(resource->resource, resource_data, + params->level_count, test_context->queue, test_context->list); reset_command_list(test_context->list, test_context->allocator); transition_resource_state(test_context->list, resource->resource, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); @@ -236,6 +246,7 @@ static ID3D12RootSignature *d3d12_runner_create_root_signature(struct d3d12_shad sampler_desc->AddressU = sampler->u_address; sampler_desc->AddressV = sampler->v_address; sampler_desc->AddressW = sampler->w_address; + sampler_desc->MaxLOD = FLT_MAX; sampler_desc->ShaderRegister = sampler->slot; sampler_desc->RegisterSpace = 0; sampler_desc->ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; diff --git a/tests/shader_runner_d3d9.c b/tests/shader_runner_d3d9.c index b983dc08..7d31f228 100644 --- a/tests/shader_runner_d3d9.c +++ b/tests/shader_runner_d3d9.c @@ -190,7 +190,6 @@ static struct resource *d3d9_runner_create_resource(struct shader_runner *r, con struct d3d9_shader_runner *runner = d3d9_shader_runner(r); IDirect3DDevice9 *device = runner->device; struct d3d9_resource *resource; - unsigned int src_pitch, y; D3DLOCKED_RECT map_desc; D3DFORMAT format; HRESULT hr; @@ -223,18 +222,32 @@ static struct resource *d3d9_runner_create_resource(struct shader_runner *r, con break;
case RESOURCE_TYPE_TEXTURE: + { + unsigned int src_buffer_offset = 0; + hr = IDirect3DDevice9_CreateTexture(device, params->width, params->height, - 1, D3DUSAGE_DYNAMIC, format, D3DPOOL_DEFAULT, &resource->texture, NULL); + params->level_count, D3DUSAGE_DYNAMIC, format, D3DPOOL_DEFAULT, &resource->texture, NULL); ok(hr == D3D_OK, "Failed to create texture, hr %#lx.\n", hr);
- hr = IDirect3DTexture9_LockRect(resource->texture, 0, &map_desc, NULL, D3DLOCK_DISCARD); - ok(hr == D3D_OK, "Failed to map texture, hr %#lx.\n", hr); - src_pitch = params->width * params->texel_size; - for (y = 0; y < params->height; ++y) - memcpy((char *)map_desc.pBits + y * map_desc.Pitch, params->data + y * src_pitch, src_pitch); - hr = IDirect3DTexture9_UnlockRect(resource->texture, 0); - ok(hr == D3D_OK, "Failed to unmap texture, hr %#lx.\n", hr); + for (unsigned int level = 0; level < params->level_count; ++level) + { + unsigned int level_width = params->width >> level; + unsigned int level_height = params->height >> level; + unsigned int src_row_pitch = level_width * params->texel_size; + unsigned int src_slice_pitch = level_height * src_row_pitch; + + hr = IDirect3DTexture9_LockRect(resource->texture, level, &map_desc, NULL, D3DLOCK_DISCARD); + ok(hr == D3D_OK, "Failed to map texture, hr %#lx.\n", hr); + for (unsigned int y = 0; y < level_height; ++y) + memcpy((char *)map_desc.pBits + y * map_desc.Pitch, + params->data + src_buffer_offset + y * src_row_pitch, src_row_pitch); + hr = IDirect3DTexture9_UnlockRect(resource->texture, level); + ok(hr == D3D_OK, "Failed to unmap texture, hr %#lx.\n", hr); + + src_buffer_offset += src_slice_pitch; + } break; + }
case RESOURCE_TYPE_UAV: fatal_error("UAVs are not supported.\n"); diff --git a/tests/shader_runner_vulkan.c b/tests/shader_runner_vulkan.c index c47dc19c..1e8d79bd 100644 --- a/tests/shader_runner_vulkan.c +++ b/tests/shader_runner_vulkan.c @@ -114,7 +114,7 @@ static void transition_image_layout(struct vulkan_shader_runner *runner, barrier.image = image; barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; barrier.subresourceRange.baseMipLevel = 0; - barrier.subresourceRange.levelCount = 1; + barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; barrier.subresourceRange.baseArrayLayer = 0; barrier.subresourceRange.layerCount = 1;
@@ -178,7 +178,7 @@ static VkBuffer create_buffer(const struct vulkan_shader_runner *runner, VkDevic }
static VkImage create_2d_image(const struct vulkan_shader_runner *runner, uint32_t width, uint32_t height, - VkImageUsageFlags usage, VkFormat format, VkDeviceMemory *memory) + uint32_t level_count, VkImageUsageFlags usage, VkFormat format, VkDeviceMemory *memory) { VkImageCreateInfo image_info = {.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO}; VkMemoryRequirements memory_reqs; @@ -189,7 +189,7 @@ static VkImage create_2d_image(const struct vulkan_shader_runner *runner, uint32 image_info.extent.width = width; image_info.extent.height = height; image_info.extent.depth = 1; - image_info.mipLevels = 1; + image_info.mipLevels = level_count; image_info.arrayLayers = 1; image_info.samples = VK_SAMPLE_COUNT_1_BIT; image_info.tiling = VK_IMAGE_TILING_OPTIMAL; @@ -220,7 +220,7 @@ static VkImageView create_2d_image_view(const struct vulkan_shader_runner *runne view_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; view_info.subresourceRange.baseMipLevel = 0; - view_info.subresourceRange.levelCount = 1; + view_info.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; view_info.subresourceRange.baseArrayLayer = 0; view_info.subresourceRange.layerCount = 1;
@@ -234,7 +234,6 @@ static struct resource *vulkan_runner_create_resource(struct shader_runner *r, c
struct vulkan_resource *resource; VkDevice device = runner->device; - VkBufferImageCopy region = {0}; VkDeviceMemory staging_memory; VkBuffer staging_buffer; VkFormat format; @@ -248,7 +247,7 @@ static struct resource *vulkan_runner_create_resource(struct shader_runner *r, c case RESOURCE_TYPE_RENDER_TARGET: format = vkd3d_get_vk_format(params->format);
- resource->image = create_2d_image(runner, params->width, params->height, + resource->image = create_2d_image(runner, params->width, params->height, params->level_count, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, format, &resource->memory); resource->view = create_2d_image_view(runner, resource->image, format);
@@ -263,6 +262,7 @@ static struct resource *vulkan_runner_create_resource(struct shader_runner *r, c { VkImageUsageFlagBits usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + unsigned int buffer_offset = 0;
format = vkd3d_get_vk_format(params->format);
@@ -272,7 +272,8 @@ static struct resource *vulkan_runner_create_resource(struct shader_runner *r, c usage |= VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; }
- resource->image = create_2d_image(runner, params->width, params->height, usage, format, &resource->memory); + resource->image = create_2d_image(runner, params->width, params->height, params->level_count, + usage, format, &resource->memory); resource->view = create_2d_image_view(runner, resource->image, format);
staging_buffer = create_buffer(runner, params->data_size, @@ -286,13 +287,22 @@ static struct resource *vulkan_runner_create_resource(struct shader_runner *r, c transition_image_layout(runner, resource->image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
- region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - region.imageSubresource.layerCount = 1; - region.imageExtent.width = params->width; - region.imageExtent.height = params->height; - region.imageExtent.depth = 1; - VK_CALL(vkCmdCopyBufferToImage(runner->cmd_buffer, staging_buffer, resource->image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion)); + for (unsigned int level = 0; level < params->level_count; ++level) + { + VkBufferImageCopy region = {0}; + + region.bufferOffset = buffer_offset; + region.imageSubresource.mipLevel = level; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.layerCount = 1; + region.imageExtent.width = (params->width >> level); + region.imageExtent.height = (params->height >> level); + region.imageExtent.depth = 1; + VK_CALL(vkCmdCopyBufferToImage(runner->cmd_buffer, staging_buffer, resource->image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion)); + + buffer_offset += (params->width >> level) * (params->height >> level) * params->texel_size; + }
transition_image_layout(runner, resource->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, layout);
@@ -739,6 +749,7 @@ static VkDescriptorSetLayout create_descriptor_set_layout(struct vulkan_shader_r sampler_desc.addressModeU = vk_address_mode_from_d3d12(sampler->u_address); sampler_desc.addressModeV = vk_address_mode_from_d3d12(sampler->v_address); sampler_desc.addressModeW = vk_address_mode_from_d3d12(sampler->w_address); + sampler_desc.maxLod = FLT_MAX;
VK_CALL(vkCreateSampler(runner->device, &sampler_desc, NULL, &vulkan_sampler->vk_sampler)); vulkan_sampler->binding = binding_index++;
From: Zebediah Figura zfigura@codeweavers.com
--- Makefile.am | 1 + tests/load-level.shader_test | 51 ++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 tests/load-level.shader_test
diff --git a/Makefile.am b/Makefile.am index e3d52ac5..64e65b06 100644 --- a/Makefile.am +++ b/Makefile.am @@ -130,6 +130,7 @@ vkd3d_shader_tests = \ tests/hlsl-vector-indexing.shader_test \ tests/hlsl-vector-indexing-uniform.shader_test \ tests/lit.shader_test \ + tests/load-level.shader_test \ tests/log.shader_test \ tests/logic-operations.shader_test \ tests/majority-syntax.shader_test \ diff --git a/tests/load-level.shader_test b/tests/load-level.shader_test new file mode 100644 index 00000000..0f64bd5d --- /dev/null +++ b/tests/load-level.shader_test @@ -0,0 +1,51 @@ +[require] +shader model >= 4.0 + +[texture 0] +size (2, 2) +levels 2 + +1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0 +1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0 + +0.0 0.0 1.0 0.0 + +[pixel shader] +sampler s; +Texture2D t; +uniform uint level; + +float4 main() : sv_target +{ + return t.Load(uint3(0, 0, level)); +} + +[test] +uniform 0 uint 0 +draw quad +probe all rgba (1.0, 0.0, 1.0, 0.0) +uniform 0 uint 1 +draw quad +probe all rgba (0.0, 0.0, 1.0, 0.0) + +[pixel shader fail] +sampler s; +Texture2D t; + +float4 main() : sv_target +{ + return t[uint3(0, 0, 0)]; +} + +[pixel shader] +sampler s; +Texture2D t; + +float4 main() : sv_target +{ + return t[uint2(0, 0)]; +} + +[test] +draw quad +probe all rgba (1.0, 0.0, 1.0, 0.0)
From: Zebediah Figura zfigura@codeweavers.com
--- Makefile.am | 1 + tests/sample-level.shader_test | 36 ++++++++++++++++++++++++++++++++++ tests/shader_runner.c | 2 ++ tests/shader_runner.h | 1 + tests/shader_runner_d3d11.c | 1 + tests/shader_runner_d3d12.c | 1 + tests/shader_runner_d3d9.c | 14 ++++++++++--- tests/shader_runner_vulkan.c | 1 + 8 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 tests/sample-level.shader_test
diff --git a/Makefile.am b/Makefile.am index 64e65b06..d2f7556f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -153,6 +153,7 @@ vkd3d_shader_tests = \ tests/register-reservations.shader_test \ tests/return.shader_test \ tests/round.shader_test \ + tests/sample-level.shader_test \ tests/sampler.shader_test \ tests/sampler-offset.shader_test \ tests/saturate.shader_test \ diff --git a/tests/sample-level.shader_test b/tests/sample-level.shader_test new file mode 100644 index 00000000..564826d0 --- /dev/null +++ b/tests/sample-level.shader_test @@ -0,0 +1,36 @@ +[require] +shader model >= 3.0 + +[sampler 0] +filter linear linear linear +address clamp clamp clamp + +[texture 0] +size (2, 2) +levels 2 + +1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0 +1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0 + +0.0 0.0 1.0 0.0 + +[pixel shader todo] +sampler s; +Texture2D t; +uniform float level; + +float4 main() : sv_target +{ + return t.SampleLevel(s, float2(0.5, 0.5), level); +} + +[test] +uniform 0 float4 0.0 0.0 0.0 0.0 +todo draw quad +probe all rgba (1.0, 0.0, 1.0, 0.0) +uniform 0 float4 0.5 0.0 0.0 0.0 +todo draw quad +probe all rgba (0.5, 0.0, 1.0, 0.0) +uniform 0 float4 1.0 0.0 0.0 0.0 +todo draw quad +probe all rgba (0.0, 0.0, 1.0, 0.0) diff --git a/tests/shader_runner.c b/tests/shader_runner.c index 8c0f59dc..b51145c7 100644 --- a/tests/shader_runner.c +++ b/tests/shader_runner.c @@ -116,6 +116,7 @@ static void parse_require_directive(struct shader_runner *runner, const char *li static const char *const model_strings[] = { [SHADER_MODEL_2_0] = "2.0", + [SHADER_MODEL_3_0] = "3.0", [SHADER_MODEL_4_0] = "4.0", [SHADER_MODEL_4_1] = "4.1", [SHADER_MODEL_5_0] = "5.0", @@ -747,6 +748,7 @@ static void compile_shader(struct shader_runner *runner, const char *source, siz static const char *const shader_models[] = { [SHADER_MODEL_2_0] = "4_0", + [SHADER_MODEL_3_0] = "4_0", [SHADER_MODEL_4_0] = "4_0", [SHADER_MODEL_4_1] = "4_1", [SHADER_MODEL_5_0] = "5_0", diff --git a/tests/shader_runner.h b/tests/shader_runner.h index b3333ac4..b10fcb1e 100644 --- a/tests/shader_runner.h +++ b/tests/shader_runner.h @@ -31,6 +31,7 @@ enum shader_model { SHADER_MODEL_2_0, + SHADER_MODEL_3_0, SHADER_MODEL_4_0, SHADER_MODEL_4_1, SHADER_MODEL_5_0, diff --git a/tests/shader_runner_d3d11.c b/tests/shader_runner_d3d11.c index b9d782b2..42a91335 100644 --- a/tests/shader_runner_d3d11.c +++ b/tests/shader_runner_d3d11.c @@ -80,6 +80,7 @@ static ID3D10Blob *compile_shader(const char *source, const char *type, enum sha static const char *const shader_models[] = { [SHADER_MODEL_2_0] = "4_0", + [SHADER_MODEL_3_0] = "4_0", [SHADER_MODEL_4_0] = "4_0", [SHADER_MODEL_4_1] = "4_1", [SHADER_MODEL_5_0] = "5_0", diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c index 07cc5b7b..330c6701 100644 --- a/tests/shader_runner_d3d12.c +++ b/tests/shader_runner_d3d12.c @@ -65,6 +65,7 @@ static ID3D10Blob *compile_shader(const struct d3d12_shader_runner *runner, cons static const char *const shader_models[] = { [SHADER_MODEL_2_0] = "4_0", + [SHADER_MODEL_3_0] = "4_0", [SHADER_MODEL_4_0] = "4_0", [SHADER_MODEL_4_1] = "4_1", [SHADER_MODEL_5_0] = "5_0", diff --git a/tests/shader_runner_d3d9.c b/tests/shader_runner_d3d9.c index 7d31f228..5a81dfb2 100644 --- a/tests/shader_runner_d3d9.c +++ b/tests/shader_runner_d3d9.c @@ -56,11 +56,19 @@ static struct d3d9_shader_runner *d3d9_shader_runner(struct shader_runner *r)
static IDirect3D9 *(WINAPI *pDirect3DCreate9)(UINT sdk_version);
-static ID3D10Blob *compile_shader(const char *source, const char *profile) +static ID3D10Blob *compile_shader(const char *source, const char *type, enum shader_model shader_model) { ID3D10Blob *blob = NULL, *errors = NULL; + char profile[7]; HRESULT hr;
+ static const char *const shader_models[] = + { + [SHADER_MODEL_2_0] = "2_0", + [SHADER_MODEL_3_0] = "3_0", + }; + + sprintf(profile, "%s_%s", type, shader_models[shader_model]); hr = D3DCompile(source, strlen(source), NULL, NULL, NULL, "main", profile, 0, 0, &blob, &errors); ok(hr == S_OK, "Failed to compile shader, hr %#lx.\n", hr); if (errors) @@ -325,10 +333,10 @@ static bool d3d9_runner_draw(struct shader_runner *r, unsigned int i, j; HRESULT hr;
- if (!(vs_code = compile_shader(runner->r.vs_source, "vs_2_0"))) + if (!(vs_code = compile_shader(runner->r.vs_source, "vs", runner->r.minimum_shader_model))) return false;
- if (!(ps_code = compile_shader(runner->r.ps_source, "ps_2_0"))) + if (!(ps_code = compile_shader(runner->r.ps_source, "ps", runner->r.minimum_shader_model))) { ID3D10Blob_Release(vs_code); return false; diff --git a/tests/shader_runner_vulkan.c b/tests/shader_runner_vulkan.c index 1e8d79bd..979e7b4a 100644 --- a/tests/shader_runner_vulkan.c +++ b/tests/shader_runner_vulkan.c @@ -362,6 +362,7 @@ static bool compile_shader(const struct vulkan_shader_runner *runner, const char static const char *const shader_models[] = { [SHADER_MODEL_2_0] = "4_0", + [SHADER_MODEL_3_0] = "4_0", [SHADER_MODEL_4_0] = "4_0", [SHADER_MODEL_4_1] = "4_1", [SHADER_MODEL_5_0] = "5_0",
From: Zebediah Figura zfigura@codeweavers.com
--- Makefile.am | 1 + tests/sample-bias.shader_test | 41 +++++++++++++++++++++++++++++++++++ tests/sampler.shader_test | 14 ------------ 3 files changed, 42 insertions(+), 14 deletions(-) create mode 100644 tests/sample-bias.shader_test
diff --git a/Makefile.am b/Makefile.am index d2f7556f..7a59134e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -153,6 +153,7 @@ vkd3d_shader_tests = \ tests/register-reservations.shader_test \ tests/return.shader_test \ tests/round.shader_test \ + tests/sample-bias.shader_test \ tests/sample-level.shader_test \ tests/sampler.shader_test \ tests/sampler-offset.shader_test \ diff --git a/tests/sample-bias.shader_test b/tests/sample-bias.shader_test new file mode 100644 index 00000000..bd0d47e5 --- /dev/null +++ b/tests/sample-bias.shader_test @@ -0,0 +1,41 @@ +[sampler 0] +filter linear linear linear +address clamp clamp clamp + +[texture 0] +size (2, 2) +levels 2 + +1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0 +1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0 + +0.0 0.0 1.0 0.0 + +[vertex shader] +void main(out float2 tex : texcoord, inout float4 pos : sv_position) +{ + tex = pos.xy; +} + +[pixel shader] +sampler s; +Texture2D t; +uniform float bias; + +float4 main(float2 coord : texcoord) : sv_target +{ + return t.SampleBias(s, coord, bias); +} + +[test] +uniform 0 float4 6.5 0.0 0.0 0.0 +draw quad +probe all rgba (1.0, 0.0, 1.0, 0.0) + +uniform 0 float4 7.5 0.0 0.0 0.0 +draw quad +probe all rgba (0.41015625, 0.0, 1.0, 0.0) + +uniform 0 float4 8.5 0.0 0.0 0.0 +draw quad +probe all rgba (0.0, 0.0, 1.0, 0.0) diff --git a/tests/sampler.shader_test b/tests/sampler.shader_test index 23741a35..9ab75a18 100644 --- a/tests/sampler.shader_test +++ b/tests/sampler.shader_test @@ -33,20 +33,6 @@ float4 main() : sv_target draw quad probe all rgba (0.25, 0, 0.25, 0)
-[pixel shader] -SamplerState s; -Texture2D t; - -float4 main() : sv_target -{ - return t.SampleBias(s, float2(0.5, 0.5), 0.0); -} - -[test] -draw quad -probe all rgba (0.25, 0, 0.25, 0) - - [pixel shader fail] sampler2D s;
From: Ethan Lee flibitijibibo@gmail.com
Signed-off-by: Ethan Lee flibitijibibo@gmail.com --- Makefile.am | 1 + tests/sample-grad.shader_test | 36 +++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 tests/sample-grad.shader_test
diff --git a/Makefile.am b/Makefile.am index 7a59134e..a41a3a43 100644 --- a/Makefile.am +++ b/Makefile.am @@ -154,6 +154,7 @@ vkd3d_shader_tests = \ tests/return.shader_test \ tests/round.shader_test \ tests/sample-bias.shader_test \ + tests/sample-grad.shader_test \ tests/sample-level.shader_test \ tests/sampler.shader_test \ tests/sampler-offset.shader_test \ diff --git a/tests/sample-grad.shader_test b/tests/sample-grad.shader_test new file mode 100644 index 00000000..db509730 --- /dev/null +++ b/tests/sample-grad.shader_test @@ -0,0 +1,36 @@ +[require] +shader model >= 4.0 + +[sampler 0] +filter linear linear linear +address clamp clamp clamp + +[texture 0] +size (2, 2) +levels 2 + +1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0 +1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0 + +0.0 0.0 1.0 0.0 + +[pixel shader todo] +sampler s; +Texture2D t; +uniform float4 grad; + +float4 main() : sv_target +{ + return t.SampleGrad(s, float2(0.5, 0.5), grad.xy, grad.zw); +} + +[test] +uniform 0 float4 0.0 0.0 0.0 0.0 +todo draw quad +todo probe all rgba (1.0, 0.0, 1.0, 0.0) +uniform 0 float4 1.0 1.0 1.0 1.0 +todo draw quad +todo probe all rgba (0.0, 0.0, 1.0, 0.0) +uniform 0 float4 2.0 2.0 2.0 2.0 +todo draw quad +todo probe all rgba (0.0, 0.0, 1.0, 0.0)
From: Ethan Lee flibitijibibo@gmail.com
Signed-off-by: Ethan Lee flibitijibibo@gmail.com --- libs/vkd3d-shader/hlsl.c | 17 ++++++++ libs/vkd3d-shader/hlsl.h | 5 ++- libs/vkd3d-shader/hlsl.y | 71 ++++++++++++++++++++++++++++++++ libs/vkd3d-shader/hlsl_codegen.c | 4 ++ libs/vkd3d-shader/tpf.c | 13 +++++- tests/sample-grad.shader_test | 14 +++---- 6 files changed, 114 insertions(+), 10 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index fbe555c9..3bfdb454 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -1327,6 +1327,8 @@ struct hlsl_ir_resource_load *hlsl_new_resource_load(struct hlsl_ctx *ctx, hlsl_src_from_node(&load->coords, params->coords); hlsl_src_from_node(&load->texel_offset, params->texel_offset); hlsl_src_from_node(&load->lod, params->lod); + hlsl_src_from_node(&load->ddx, params->ddx); + hlsl_src_from_node(&load->ddy, params->ddy); return load; }
@@ -1605,6 +1607,8 @@ static struct hlsl_ir_node *clone_resource_load(struct hlsl_ctx *ctx, } clone_src(map, &dst->coords, &src->coords); clone_src(map, &dst->lod, &src->lod); + clone_src(map, &dst->ddx, &src->ddx); + clone_src(map, &dst->ddy, &src->ddy); clone_src(map, &dst->texel_offset, &src->texel_offset); return &dst->node; } @@ -2392,6 +2396,7 @@ static void dump_ir_resource_load(struct vkd3d_string_buffer *buffer, const stru [HLSL_RESOURCE_SAMPLE] = "sample", [HLSL_RESOURCE_SAMPLE_LOD] = "sample_lod", [HLSL_RESOURCE_SAMPLE_LOD_BIAS] = "sample_biased", + [HLSL_RESOURCE_SAMPLE_GRAD] = "sample_grad", [HLSL_RESOURCE_GATHER_RED] = "gather_red", [HLSL_RESOURCE_GATHER_GREEN] = "gather_green", [HLSL_RESOURCE_GATHER_BLUE] = "gather_blue", @@ -2415,6 +2420,16 @@ static void dump_ir_resource_load(struct vkd3d_string_buffer *buffer, const stru vkd3d_string_buffer_printf(buffer, ", lod = "); dump_src(buffer, &load->lod); } + if (load->ddx.node) + { + vkd3d_string_buffer_printf(buffer, ", ddx = "); + dump_src(buffer, &load->ddx); + } + if (load->ddy.node) + { + vkd3d_string_buffer_printf(buffer, ", ddy = "); + dump_src(buffer, &load->ddy); + } vkd3d_string_buffer_printf(buffer, ")"); }
@@ -2650,6 +2665,8 @@ static void free_ir_resource_load(struct hlsl_ir_resource_load *load) hlsl_cleanup_deref(&load->resource); hlsl_src_remove(&load->coords); hlsl_src_remove(&load->lod); + hlsl_src_remove(&load->ddx); + hlsl_src_remove(&load->ddy); hlsl_src_remove(&load->texel_offset); vkd3d_free(load); } diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 0256339c..882ab278 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -600,6 +600,7 @@ enum hlsl_resource_load_type HLSL_RESOURCE_SAMPLE, HLSL_RESOURCE_SAMPLE_LOD, HLSL_RESOURCE_SAMPLE_LOD_BIAS, + HLSL_RESOURCE_SAMPLE_GRAD, HLSL_RESOURCE_GATHER_RED, HLSL_RESOURCE_GATHER_GREEN, HLSL_RESOURCE_GATHER_BLUE, @@ -611,7 +612,7 @@ struct hlsl_ir_resource_load struct hlsl_ir_node node; enum hlsl_resource_load_type load_type; struct hlsl_deref resource, sampler; - struct hlsl_src coords, lod, texel_offset; + struct hlsl_src coords, lod, ddx, ddy, texel_offset; };
struct hlsl_ir_resource_store @@ -812,7 +813,7 @@ struct hlsl_resource_load_params struct hlsl_type *format; enum hlsl_resource_load_type type; struct hlsl_ir_node *resource, *sampler; - struct hlsl_ir_node *coords, *lod, *texel_offset; + struct hlsl_ir_node *coords, *lod, *ddx, *ddy, *texel_offset; };
static inline struct hlsl_ir_call *hlsl_ir_call(const struct hlsl_ir_node *node) diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index ab0b3f65..f7d41742 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -3999,6 +3999,71 @@ static bool add_sample_lod_method_call(struct hlsl_ctx *ctx, struct list *instrs return true; }
+static bool add_sample_grad_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *object, + const char *name, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) +{ + const struct hlsl_type *object_type = object->data_type; + struct hlsl_resource_load_params load_params = { 0 }; + const unsigned int sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); + const unsigned int offset_dim = hlsl_offset_dim_count(object_type->sampler_dim); + const struct hlsl_type *sampler_type; + struct hlsl_ir_resource_load *load; + + load_params.type = HLSL_RESOURCE_SAMPLE_GRAD; + + if (params->args_count < 4 || params->args_count > 5 + !!offset_dim) + { + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT, + "Wrong number of arguments to method '%s': expected from 4 to %u, but got %u.", + name, 5 + !!offset_dim, params->args_count); + return false; + } + + sampler_type = params->args[0]->data_type; + if (sampler_type->class != HLSL_CLASS_OBJECT || sampler_type->base_type != HLSL_TYPE_SAMPLER + || sampler_type->sampler_dim != HLSL_SAMPLER_DIM_GENERIC) + { + struct vkd3d_string_buffer *string; + + if ((string = hlsl_type_to_string(ctx, sampler_type))) + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Wrong type for argument 0 of %s(): expected 'sampler', but got '%s'.", name, string->buffer); + hlsl_release_string_buffer(ctx, string); + return false; + } + + if (!(load_params.coords = add_implicit_conversion(ctx, instrs, params->args[1], + hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc))) + load_params.coords = params->args[1]; + + if (!(load_params.ddx = add_implicit_conversion(ctx, instrs, params->args[2], + hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc))) + load_params.ddx = params->args[2]; + + if (!(load_params.ddy = add_implicit_conversion(ctx, instrs, params->args[3], + hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc))) + load_params.ddy = params->args[3]; + + if (offset_dim && params->args_count > 4) + { + if (!(load_params.texel_offset = add_implicit_conversion(ctx, instrs, params->args[4], + hlsl_get_vector_type(ctx, HLSL_TYPE_INT, offset_dim), loc))) + return false; + } + + if (params->args_count > 4 + !!offset_dim) + hlsl_fixme(ctx, loc, "Tiled resource status argument."); + + load_params.format = object_type->e.resource_format; + load_params.resource = object; + load_params.sampler = params->args[0]; + + if (!(load = hlsl_new_resource_load(ctx, &load_params, loc))) + return false; + list_add_tail(instrs, &load->node.entry); + return true; +} + static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *object, const char *name, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) { @@ -4049,6 +4114,12 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl { return add_sample_lod_method_call(ctx, instrs, object, name, params, loc); } + else if (!strcmp(name, "SampleGrad") + && object_type->sampler_dim != HLSL_SAMPLER_DIM_2DMS + && object_type->sampler_dim != HLSL_SAMPLER_DIM_2DMSARRAY) + { + return add_sample_grad_method_call(ctx, instrs, object, name, params, loc); + } else { struct vkd3d_string_buffer *string; diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 78c94341..f9f069e5 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -2619,6 +2619,10 @@ static void compute_liveness_recurse(struct hlsl_block *block, unsigned int loop load->texel_offset.node->last_read = instr->index; if (load->lod.node) load->lod.node->last_read = instr->index; + if (load->ddx.node) + load->ddx.node->last_read = instr->index; + if (load->ddy.node) + load->ddy.node->last_read = instr->index; break; } case HLSL_IR_RESOURCE_STORE: diff --git a/libs/vkd3d-shader/tpf.c b/libs/vkd3d-shader/tpf.c index 38d5c180..b91adc5e 100644 --- a/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d-shader/tpf.c @@ -3022,7 +3022,7 @@ struct sm4_instruction struct sm4_register reg; enum vkd3d_sm4_swizzle_type swizzle_type; unsigned int swizzle; - } srcs[4]; + } srcs[5]; unsigned int src_count;
uint32_t idx[3]; @@ -3712,6 +3712,10 @@ static void write_sm4_sample(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer instr.opcode = VKD3D_SM4_OP_SAMPLE_B; break;
+ case HLSL_RESOURCE_SAMPLE_GRAD: + instr.opcode = VKD3D_SM4_OP_SAMPLE_GRAD; + break; + default: vkd3d_unreachable(); } @@ -3739,6 +3743,12 @@ static void write_sm4_sample(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer sm4_src_from_node(&instr.srcs[3], load->lod.node, VKD3DSP_WRITEMASK_ALL); ++instr.src_count; } + else if (load->load_type == HLSL_RESOURCE_SAMPLE_GRAD) + { + sm4_src_from_node(&instr.srcs[3], load->ddx.node, VKD3DSP_WRITEMASK_ALL); + sm4_src_from_node(&instr.srcs[4], load->ddy.node, VKD3DSP_WRITEMASK_ALL); + instr.src_count += 2; + }
write_sm4_instruction(buffer, &instr); } @@ -4541,6 +4551,7 @@ static void write_sm4_resource_load(struct hlsl_ctx *ctx,
case HLSL_RESOURCE_SAMPLE: case HLSL_RESOURCE_SAMPLE_LOD_BIAS: + case HLSL_RESOURCE_SAMPLE_GRAD: if (!load->sampler.var) { hlsl_fixme(ctx, &load->node.loc, "SM4 combined sample expression."); diff --git a/tests/sample-grad.shader_test b/tests/sample-grad.shader_test index db509730..c37da299 100644 --- a/tests/sample-grad.shader_test +++ b/tests/sample-grad.shader_test @@ -14,7 +14,7 @@ levels 2
0.0 0.0 1.0 0.0
-[pixel shader todo] +[pixel shader] sampler s; Texture2D t; uniform float4 grad; @@ -26,11 +26,11 @@ float4 main() : sv_target
[test] uniform 0 float4 0.0 0.0 0.0 0.0 -todo draw quad -todo probe all rgba (1.0, 0.0, 1.0, 0.0) +draw quad +probe all rgba (1.0, 0.0, 1.0, 0.0) uniform 0 float4 1.0 1.0 1.0 1.0 -todo draw quad -todo probe all rgba (0.0, 0.0, 1.0, 0.0) +draw quad +probe all rgba (0.0, 0.0, 1.0, 0.0) uniform 0 float4 2.0 2.0 2.0 2.0 -todo draw quad -todo probe all rgba (0.0, 0.0, 1.0, 0.0) +draw quad +probe all rgba (0.0, 0.0, 1.0, 0.0)
Rebased, but instead of rebasing on main I rebased on Zebediah's patchset - !191 should be prioritized before this MR!
On Wed May 3 01:33:50 2023 +0000, Ethan Lee wrote:
changed this line in [version 8 of the diff](/wine/vkd3d/-/merge_requests/184/diffs?diff_id=45230&start_sha=2e0d0b6e67a4d1866fd3b678284bb3f2e1fcbbf5#633db2627f198fcb8cdc95359357447fca090d21_55_36)
Latest push tries to make some more interesting tests - there might be some more complex tests that could be added, definitely open to ideas! I can throw any additional inputs into the next rebase.
On Wed May 3 01:35:22 2023 +0000, Ethan Lee wrote:
Latest push tries to make some more interesting tests - there might be some more complex tests that could be added, definitely open to ideas! I can throw any additional inputs into the next rebase.
Yes, that's much better. Once !191 is accepted I think this is ready to go.