~~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!
-- v9: 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 | 7 ++++++ tests/shader_runner_d3d11.c | 24 +++++++++++++++------ tests/shader_runner_d3d12.c | 34 +++++++++++++++++++++--------- tests/shader_runner_d3d9.c | 31 +++++++++++++++++++-------- tests/shader_runner_vulkan.c | 41 ++++++++++++++++++++++++------------ 6 files changed, 111 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..8f8cf979 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; }; @@ -134,6 +136,11 @@ struct shader_runner_ops void (*release_readback)(struct shader_runner *runner, struct resource_readback *rb); };
+static inline unsigned int get_level_dimension(unsigned int dimension, unsigned int level) +{ + return max(1, dimension >> level); +} + void fatal_error(const char *format, ...) VKD3D_NORETURN VKD3D_PRINTF_FUNC(1, 2);
unsigned int get_vb_stride(const struct shader_runner *runner, unsigned int slot); diff --git a/tests/shader_runner_d3d11.c b/tests/shader_runner_d3d11.c index 2954cab8..12d00bf8 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,19 @@ 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) + { + unsigned int level_width = get_level_dimension(params->width, level); + unsigned int level_height = get_level_dimension(params->height, level); + + resource_data[level].pSysMem = ¶ms->data[buffer_offset]; + resource_data[level].SysMemPitch = level_width * params->texel_size; + resource_data[level].SysMemSlicePitch = level_height * 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..7c4da691 100644 --- a/tests/shader_runner_d3d12.c +++ b/tests/shader_runner_d3d12.c @@ -90,12 +90,27 @@ 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) + { + unsigned int level_width = get_level_dimension(params->width, level); + unsigned int level_height = get_level_dimension(params->height, level); + + resource_data[level].pData = ¶ms->data[buffer_offset]; + resource_data[level].RowPitch = level_width * params->texel_size; + resource_data[level].SlicePitch = level_height * resource_data[level].RowPitch; + buffer_offset += resource_data[level].SlicePitch; + } + switch (params->type) { case RESOURCE_TYPE_RENDER_TARGET: @@ -106,7 +121,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 +132,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 +148,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 +249,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..26b8cb8f 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, 0, format, D3DPOOL_MANAGED, &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 = get_level_dimension(params->width, level); + unsigned int level_height = get_level_dimension(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, 0); + 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], + ¶ms->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..43b7b265 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,24 @@ 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) + { + unsigned int level_width = get_level_dimension(params->width, level); + unsigned int level_height = get_level_dimension(params->height, 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 = level_width; + region.imageExtent.height = level_height; + region.imageExtent.depth = 1; + VK_CALL(vkCmdCopyBufferToImage(runner->cmd_buffer, staging_buffer, resource->image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion)); + + buffer_offset += level_width * level_height * params->texel_size; + }
transition_image_layout(runner, resource->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, layout);
@@ -739,6 +751,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 f7c5c9a1..49390021 100644 --- a/Makefile.am +++ b/Makefile.am @@ -132,6 +132,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 49390021..093ab968 100644 --- a/Makefile.am +++ b/Makefile.am @@ -155,6 +155,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 8f8cf979..8962a8fc 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 12d00bf8..a6b9c693 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 7c4da691..11d58ecc 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 26b8cb8f..973b2342 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 43b7b265..670a454d 100644 --- a/tests/shader_runner_vulkan.c +++ b/tests/shader_runner_vulkan.c @@ -364,6 +364,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 | 43 +++++++++++++++++++++++++++++++++++ tests/sampler.shader_test | 14 ------------ 3 files changed, 44 insertions(+), 14 deletions(-) create mode 100644 tests/sample-bias.shader_test
diff --git a/Makefile.am b/Makefile.am index 093ab968..8db92309 100644 --- a/Makefile.am +++ b/Makefile.am @@ -155,6 +155,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..08e50696 --- /dev/null +++ b/tests/sample-bias.shader_test @@ -0,0 +1,43 @@ +[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 +{ + /* Choice of initial mipmap level is hardware-dependent, and in practice + * varies too much to be reasonably covered by ULPS. Quantize instead. */ + return floor(t.SampleBias(s, coord, bias) * 10); +} + +[test] +uniform 0 float4 6.5 0.0 0.0 0.0 +draw quad +probe all rgba (10.0, 0.0, 10.0, 0.0) + +uniform 0 float4 7.5 0.0 0.0 0.0 +draw quad +probe all rgba (4.0, 0.0, 10.0, 0.0) + +uniform 0 float4 8.5 0.0 0.0 0.0 +draw quad +probe all rgba (0.0, 0.0, 10.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 8db92309..123cbb27 100644 --- a/Makefile.am +++ b/Makefile.am @@ -156,6 +156,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 9de37a93..02f54984 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -1327,6 +1327,8 @@ struct hlsl_ir_node *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->node; }
@@ -1614,6 +1616,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; } @@ -2401,6 +2405,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", @@ -2424,6 +2429,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, ")"); }
@@ -2659,6 +2674,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 45c17717..517765a4 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 75c0e421..0e594e72 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -3956,6 +3956,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_node *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->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) { @@ -4006,6 +4071,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 ff0d1a18..fa52dc4f 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -2682,6 +2682,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 fcd7cf93..62879817 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)
One more rebase, this rebases both !191 and this MR against latest master, so if !191's current revision is merged, the 2 patches on top should also apply cleanly!