From what I can tell, the recent work on SampleBias/SampleLevel did all of the work for us, we just need to take the same framework and include the case for the `sample_l` instruction.
Tested with some shaders from the native Linux version of Little Racers STREET.
-- v10: vkd3d-shader/tpf: For sample_l/sample_b, set lod swizzle to SCALAR.
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)
From: Ethan Lee flibitijibibo@gmail.com
Signed-off-by: Ethan Lee flibitijibibo@gmail.com --- libs/vkd3d-shader/tpf.c | 12 +++++++----- tests/sample-level.shader_test | 8 ++++---- 2 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/libs/vkd3d-shader/tpf.c b/libs/vkd3d-shader/tpf.c index 62879817..e83ee936 100644 --- a/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d-shader/tpf.c @@ -3708,6 +3708,10 @@ static void write_sm4_sample(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer instr.opcode = VKD3D_SM4_OP_SAMPLE; break;
+ case HLSL_RESOURCE_SAMPLE_LOD: + instr.opcode = VKD3D_SM4_OP_SAMPLE_LOD; + break; + case HLSL_RESOURCE_SAMPLE_LOD_BIAS: instr.opcode = VKD3D_SM4_OP_SAMPLE_B; break; @@ -3738,7 +3742,8 @@ static void write_sm4_sample(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer sm4_src_from_deref(ctx, &instr.srcs[2], sampler, sampler->var->data_type, VKD3DSP_WRITEMASK_ALL); instr.src_count = 3;
- if (load->load_type == HLSL_RESOURCE_SAMPLE_LOD_BIAS) + if (load->load_type == HLSL_RESOURCE_SAMPLE_LOD + || load->load_type == HLSL_RESOURCE_SAMPLE_LOD_BIAS) { sm4_src_from_node(&instr.srcs[3], load->lod.node, VKD3DSP_WRITEMASK_ALL); ++instr.src_count; @@ -4550,6 +4555,7 @@ static void write_sm4_resource_load(struct hlsl_ctx *ctx, break;
case HLSL_RESOURCE_SAMPLE: + case HLSL_RESOURCE_SAMPLE_LOD: case HLSL_RESOURCE_SAMPLE_LOD_BIAS: case HLSL_RESOURCE_SAMPLE_GRAD: if (!load->sampler.var) @@ -4579,10 +4585,6 @@ static void write_sm4_resource_load(struct hlsl_ctx *ctx, write_sm4_gather(ctx, buffer, resource_type, &load->node, &load->resource, &load->sampler, coords, HLSL_SWIZZLE(W, W, W, W), texel_offset); break; - - case HLSL_RESOURCE_SAMPLE_LOD: - hlsl_fixme(ctx, &load->node.loc, "SM4 sample-LOD expression."); - break; } }
diff --git a/tests/sample-level.shader_test b/tests/sample-level.shader_test index 564826d0..ec7c7e2a 100644 --- a/tests/sample-level.shader_test +++ b/tests/sample-level.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 float level; @@ -26,11 +26,11 @@ float4 main() : sv_target
[test] uniform 0 float4 0.0 0.0 0.0 0.0 -todo draw quad +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 +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 +draw quad probe all rgba (0.0, 0.0, 1.0, 0.0)
From: Ethan Lee flibitijibibo@gmail.com
Per Francisco Casas fcasas@codeweavers.com:
I just realized one more thing. I think we are not properly following the specification for both sample_l and sample_b.
In the Restrictions section of the documentation for sample_b it is mentioned that the last src register must use a single component selector if it is not a scalar immediate. This "select_component" is also ilustrated in the sample_l format:
sample_l[_aoffimmi(u,v,w)] dest[.mask], srcAddress[.swizzle], srcResource[.swizzle], srcSampler, srcLOD.select_component
Currently, we are not respecting that since sm4_src_from_node() sets
src->swizzle_type = VKD3D_SM4_SWIZZLE_VEC4;
by default.
It should be VKD3D_SM4_SWIZZLE_SCALAR in this case... The disassembly should show a single component in the swizzle of the last src register.
Signed-off-by: Ethan Lee flibitijibibo@gmail.com --- libs/vkd3d-shader/tpf.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/libs/vkd3d-shader/tpf.c b/libs/vkd3d-shader/tpf.c index e83ee936..5814b838 100644 --- a/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d-shader/tpf.c @@ -3746,6 +3746,7 @@ static void write_sm4_sample(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer || load->load_type == HLSL_RESOURCE_SAMPLE_LOD_BIAS) { sm4_src_from_node(&instr.srcs[3], load->lod.node, VKD3DSP_WRITEMASK_ALL); + instr.srcs[3].swizzle_type = VKD3D_SM4_SWIZZLE_SCALAR; ++instr.src_count; } else if (load->load_type == HLSL_RESOURCE_SAMPLE_GRAD)