diff --git a/dlls/d3dcompiler_43/tests/hlsl_d3d11.c b/dlls/d3dcompiler_43/tests/hlsl_d3d11.c index aff75a5eafa..7a1243b9ccf 100644 --- a/dlls/d3dcompiler_43/tests/hlsl_d3d11.c +++ b/dlls/d3dcompiler_43/tests/hlsl_d3d11.c @@ -524,6 +524,126 @@ static void test_trig(void) release_test_context(&test_context); } +static void test_sampling(void) +{ + struct test_context test_context; + ID3D11ShaderResourceView *srv; + ID3D11SamplerState *sampler; + ID3D10Blob *ps_code = NULL; + ID3D11Texture2D *texture; + unsigned int i; + struct vec4 v; + HRESULT hr; + + static const char *tests[] = + { + "sampler s;\n" + "float4 main() : COLOR\n" + "{\n" + " return tex2D(s, float2(0.5, 0.5));\n" + "}", + + "SamplerState s;\n" + "float4 main() : COLOR\n" + "{\n" + " return tex2D(s, float2(0.5, 0.5));\n" + "}", + + "sampler2D s;\n" + "float4 main() : COLOR\n" + "{\n" + " return tex2D(s, float2(0.5, 0.5));\n" + "}", + + "sampler s;\n" + "Texture2D t;\n" + "float4 main() : COLOR\n" + "{\n" + " return t.Sample(s, float2(0.5, 0.5));\n" + "}", + + "SamplerState s;\n" + "Texture2D t;\n" + "float4 main() : COLOR\n" + "{\n" + " return t.Sample(s, float2(0.5, 0.5));\n" + "}", + }; + + static const D3D11_TEXTURE2D_DESC texture_desc = + { + .Width = 2, + .Height = 2, + .MipLevels = 1, + .ArraySize = 1, + .Format = DXGI_FORMAT_R32G32B32A32_FLOAT, + .SampleDesc.Count = 1, + .Usage = D3D11_USAGE_DEFAULT, + .BindFlags = D3D11_BIND_SHADER_RESOURCE, + }; + + static const float texture_data[] = + { + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 1.0f, 0.0f, + }; + + static const D3D11_SUBRESOURCE_DATA resource_data = {&texture_data, sizeof(texture_data) / 2}; + + static const D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc = + { + .Format = DXGI_FORMAT_R32G32B32A32_FLOAT, + .ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D, + .Texture2D.MipLevels = 1, + }; + + static const D3D11_SAMPLER_DESC sampler_desc = + { + .Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR, + .AddressU = D3D11_TEXTURE_ADDRESS_WRAP, + .AddressV = D3D11_TEXTURE_ADDRESS_WRAP, + .AddressW = D3D11_TEXTURE_ADDRESS_WRAP, + }; + + static const float red[] = {1.0f, 0.0f, 0.0f, 1.0f}; + + if (!init_test_context(&test_context)) + return; + + hr = ID3D11Device_CreateTexture2D(test_context.device, &texture_desc, &resource_data, &texture); + ok(hr == S_OK, "Failed to create texture, hr %#x.\n", hr); + hr = ID3D11Device_CreateShaderResourceView(test_context.device, (ID3D11Resource *)texture, &srv_desc, &srv); + ok(hr == S_OK, "Failed to create SRV, hr %#x.\n", hr); + ID3D11DeviceContext_PSSetShaderResources(test_context.immediate_context, 0, 1, &srv); + + hr = ID3D11Device_CreateSamplerState(test_context.device, &sampler_desc, &sampler); + ok(hr == S_OK, "Failed to create sampler, hr %#x.\n", hr); + ID3D11DeviceContext_PSSetSamplers(test_context.immediate_context, 0, 1, &sampler); + + for (i = 0; i < ARRAY_SIZE(tests); ++i) + { + ID3D11DeviceContext_ClearRenderTargetView(test_context.immediate_context, test_context.rtv, red); + todo_wine ps_code = compile_shader_flags(tests[i], "ps_4_0", D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY); + if (ps_code) + { + draw_quad(&test_context, ps_code); + + v = get_color_vec4(&test_context, 0, 0); + todo_wine ok(compare_vec4(&v, 0.25f, 0.0f, 0.25f, 0.0f, 0), + "Test %u: Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", i, v.x, v.y, v.z, v.w); + + ID3D10Blob_Release(ps_code); + } + } + + ID3D11Texture2D_Release(texture); + ID3D11SamplerState_Release(sampler); + ID3D11ShaderResourceView_Release(srv); + release_test_context(&test_context); +} + static void check_type_desc(const char *prefix, const D3D11_SHADER_TYPE_DESC *type, const D3D11_SHADER_TYPE_DESC *expect) { @@ -537,6 +657,19 @@ static void check_type_desc(const char *prefix, const D3D11_SHADER_TYPE_DESC *ty ok(!strcmp(type->Name, expect->Name), "%s: got name %s.\n", prefix, debugstr_a(type->Name)); } +static void check_resource_binding(const char *prefix, const D3D11_SHADER_INPUT_BIND_DESC *desc, + const D3D11_SHADER_INPUT_BIND_DESC *expect) +{ + ok(!strcmp(desc->Name, expect->Name), "%s: got name %s.\n", prefix, debugstr_a(desc->Name)); + ok(desc->Type == expect->Type, "%s: got type %#x.\n", prefix, desc->Type); + ok(desc->BindPoint == expect->BindPoint, "%s: got bind point %u.\n", prefix, desc->BindPoint); + ok(desc->BindCount == expect->BindCount, "%s: got bind count %u.\n", prefix, desc->BindCount); + ok(desc->uFlags == expect->uFlags, "%s: got flags %#x.\n", prefix, desc->uFlags); + ok(desc->ReturnType == expect->ReturnType, "%s: got return type %#x.\n", prefix, desc->ReturnType); + ok(desc->Dimension == expect->Dimension, "%s: got dimension %#x.\n", prefix, desc->Dimension); + ok(desc->NumSamples == expect->NumSamples, "%s: got multisample count %u.\n", prefix, desc->NumSamples); +} + static void test_reflection(void) { ID3D11ShaderReflectionConstantBuffer *cbuffer; @@ -546,8 +679,10 @@ static void test_reflection(void) D3D11_SHADER_VARIABLE_DESC var_desc; ID3D11ShaderReflection *reflection; D3D11_SHADER_TYPE_DESC type_desc; - ID3D10Blob *vs_code = NULL; + D3D11_SHADER_DESC shader_desc; + ID3D10Blob *code = NULL; unsigned int i, j, k; + char prefix[40]; ULONG refcount; HRESULT hr; @@ -658,14 +793,55 @@ static void test_reflection(void) {"b5", D3D_SIT_CBUFFER, 5, 1, D3D_SIF_USERPACKED}, }; - todo_wine vs_code = compile_shader(vs_source, "vs_5_0"); - if (!vs_code) + static const char ps_source[] = + "texture2D a;\n" + "sampler c {};\n" + "SamplerState d {};\n" + "sampler e\n" + "{\n" + " Texture = a;\n" + " foo = bar + 2;\n" + "};\n" + "SamplerState f\n" + "{\n" + " Texture = a;\n" + " foo = bar + 2;\n" + "};\n" + "sampler2D g;\n" + "sampler b : register(s5);\n" + "float4 main(float2 pos : texcoord) : SV_TARGET\n" + "{\n" + " return a.Sample(b, pos) + a.Sample(c, pos) + a.Sample(d, pos) + tex2D(f, pos) + tex2D(e, pos)" + " + tex2D(g, pos);\n" + "}"; + + static const D3D11_SHADER_INPUT_BIND_DESC ps_bindings[] = + { + {"c", D3D_SIT_SAMPLER, 0, 1}, + {"d", D3D_SIT_SAMPLER, 1, 1}, + {"e", D3D_SIT_SAMPLER, 2, 1}, + {"f", D3D_SIT_SAMPLER, 3, 1}, + {"g", D3D_SIT_SAMPLER, 4, 1}, + {"b", D3D_SIT_SAMPLER, 5, 1, D3D_SIF_USERPACKED}, + {"f", D3D_SIT_TEXTURE, 0, 1, D3D_SIF_TEXTURE_COMPONENTS, D3D_RETURN_TYPE_FLOAT, D3D_SRV_DIMENSION_TEXTURE2D, ~0u}, + {"e", D3D_SIT_TEXTURE, 1, 1, D3D_SIF_TEXTURE_COMPONENTS, D3D_RETURN_TYPE_FLOAT, D3D_SRV_DIMENSION_TEXTURE2D, ~0u}, + {"g", D3D_SIT_TEXTURE, 2, 1, D3D_SIF_TEXTURE_COMPONENTS, D3D_RETURN_TYPE_FLOAT, D3D_SRV_DIMENSION_TEXTURE2D, ~0u}, + {"a", D3D_SIT_TEXTURE, 3, 1, D3D_SIF_TEXTURE_COMPONENTS, D3D_RETURN_TYPE_FLOAT, D3D_SRV_DIMENSION_TEXTURE2D, ~0u}, + }; + + todo_wine code = compile_shader(vs_source, "vs_5_0"); + if (!code) return; - hr = pD3DReflect(ID3D10Blob_GetBufferPointer(vs_code), ID3D10Blob_GetBufferSize(vs_code), + hr = pD3DReflect(ID3D10Blob_GetBufferPointer(code), ID3D10Blob_GetBufferSize(code), &IID_ID3D11ShaderReflection, (void **)&reflection); ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = reflection->lpVtbl->GetDesc(reflection, &shader_desc); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(shader_desc.ConstantBuffers == ARRAY_SIZE(vs_buffers), "Got %u buffers.\n", shader_desc.ConstantBuffers); + ok(shader_desc.BoundResources == ARRAY_SIZE(vs_bindings), "Got %u resources.\n", shader_desc.BoundResources); + for (i = 0; i < ARRAY_SIZE(vs_buffers); ++i) { cbuffer = reflection->lpVtbl->GetConstantBufferByIndex(reflection, i); @@ -682,7 +858,6 @@ static void test_reflection(void) for (j = 0; j < buffer_desc.Variables; ++j) { const struct shader_variable *expect = &vs_buffers[i].vars[j]; - char prefix[40]; var = cbuffer->lpVtbl->GetVariableByIndex(cbuffer, j); hr = var->lpVtbl->GetDesc(var, &var_desc); @@ -717,20 +892,36 @@ static void test_reflection(void) D3D11_SHADER_INPUT_BIND_DESC desc; hr = reflection->lpVtbl->GetResourceBindingDesc(reflection, i, &desc); - todo_wine ok(hr == S_OK, "Test %u: got hr %#x.\n", i, hr); - if (hr != S_OK) - break; - ok(!strcmp(desc.Name, vs_bindings[i].Name), "Test %u: got name %s.\n", i, debugstr_a(desc.Name)); - ok(desc.Type == vs_bindings[i].Type, "Test %u: got type %#x.\n", i, desc.Type); - ok(desc.BindPoint == vs_bindings[i].BindPoint, "Test %u: got bind point %u.\n", i, desc.BindPoint); - ok(desc.BindCount == vs_bindings[i].BindCount, "Test %u: got bind count %u.\n", i, desc.BindCount); - ok(desc.uFlags == vs_bindings[i].uFlags, "Test %u: got flags %#x.\n", i, desc.uFlags); - ok(desc.ReturnType == vs_bindings[i].ReturnType, "Test %u: got return type %#x.\n", i, desc.ReturnType); - ok(desc.Dimension == vs_bindings[i].Dimension, "Test %u: got dimension %#x.\n", i, desc.Dimension); - ok(desc.NumSamples == vs_bindings[i].NumSamples, "Test %u: got multisample count %u.\n", i, desc.NumSamples); + ok(hr == S_OK, "Test %u: got hr %#x.\n", i, hr); + sprintf(prefix, "Test %u", i); + check_resource_binding(prefix, &desc, &vs_bindings[i]); } - ID3D10Blob_Release(vs_code); + ID3D10Blob_Release(code); + refcount = reflection->lpVtbl->Release(reflection); + ok(!refcount, "Got unexpected refcount %u.\n", refcount); + + code = compile_shader_flags(ps_source, "ps_4_0", D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY); + hr = pD3DReflect(ID3D10Blob_GetBufferPointer(code), ID3D10Blob_GetBufferSize(code), + &IID_ID3D11ShaderReflection, (void **)&reflection); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = reflection->lpVtbl->GetDesc(reflection, &shader_desc); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(!shader_desc.ConstantBuffers, "Got %u buffers.\n", shader_desc.ConstantBuffers); + ok(shader_desc.BoundResources == ARRAY_SIZE(ps_bindings), "Got %u resources.\n", shader_desc.BoundResources); + + for (i = 0; i < shader_desc.BoundResources; ++i) + { + D3D11_SHADER_INPUT_BIND_DESC desc; + + hr = reflection->lpVtbl->GetResourceBindingDesc(reflection, i, &desc); + ok(hr == S_OK, "Test %u: got hr %#x.\n", i, hr); + sprintf(prefix, "Test %u", i); + check_resource_binding(prefix, &desc, &ps_bindings[i]); + } + + ID3D10Blob_Release(code); refcount = reflection->lpVtbl->Release(reflection); ok(!refcount, "Got unexpected refcount %u.\n", refcount); } @@ -1006,4 +1197,5 @@ START_TEST(hlsl_d3d11) test_math(); test_conditionals(); test_trig(); + test_sampling(); } diff --git a/dlls/d3dcompiler_43/tests/hlsl_d3d9.c b/dlls/d3dcompiler_43/tests/hlsl_d3d9.c index 8443406402e..87f63023c58 100644 --- a/dlls/d3dcompiler_43/tests/hlsl_d3d9.c +++ b/dlls/d3dcompiler_43/tests/hlsl_d3d9.c @@ -1054,11 +1054,98 @@ static void test_global_initializer(void) release_test_context(&test_context); } +static void test_samplers(void) +{ + struct test_context test_context; + IDirect3DTexture9 *texture; + ID3D10Blob *ps_code = NULL; + D3DLOCKED_RECT map_desc; + unsigned int i; + struct vec4 v; + HRESULT hr; + + static const char *tests[] = + { + "sampler s;\n" + "float4 main() : COLOR\n" + "{\n" + " return tex2D(s, float2(0.5, 0.5));\n" + "}", + + "SamplerState s;\n" + "float4 main() : COLOR\n" + "{\n" + " return tex2D(s, float2(0.5, 0.5));\n" + "}", + + "sampler2D s;\n" + "float4 main() : COLOR\n" + "{\n" + " return tex2D(s, float2(0.5, 0.5));\n" + "}", + + "sampler s;\n" + "Texture2D t;\n" + "float4 main() : COLOR\n" + "{\n" + " return t.Sample(s, float2(0.5, 0.5));\n" + "}", + + "SamplerState s;\n" + "Texture2D t;\n" + "float4 main() : COLOR\n" + "{\n" + " return t.Sample(s, float2(0.5, 0.5));\n" + "}", + }; + + if (!init_test_context(&test_context)) + return; + + hr = IDirect3DDevice9_CreateTexture(test_context.device, 2, 2, 1, D3DUSAGE_DYNAMIC, + D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL); + ok(hr == D3D_OK, "Failed to create texture, hr %#x.\n", hr); + + hr = IDirect3DTexture9_LockRect(texture, 0, &map_desc, NULL, D3DLOCK_DISCARD); + ok(hr == D3D_OK, "Failed to map texture, hr %#x.\n", hr); + memset(map_desc.pBits, 0, 2 * map_desc.Pitch); + ((DWORD *)map_desc.pBits)[1] = 0x00ff00ff; + hr = IDirect3DTexture9_UnlockRect(texture, 0); + ok(hr == D3D_OK, "Failed to unmap texture, hr %#x.\n", hr); + + hr = IDirect3DDevice9_SetTexture(test_context.device, 0, (IDirect3DBaseTexture9 *)texture); + ok(hr == D3D_OK, "Failed to set texture, hr %#x.\n", hr); + hr = IDirect3DDevice9_SetSamplerState(test_context.device, 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); + ok(hr == D3D_OK, "Failed to set sampler state, hr %#x.\n", hr); + + for (i = 0; i < ARRAY_SIZE(tests); ++i) + { + hr = IDirect3DDevice9_Clear(test_context.device, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(255, 0, 0), 1.0f, 0); + ok(hr == D3D_OK, "Test %u: Failed to clear, hr %#x.\n", i, hr); + todo_wine ps_code = compile_shader(tests[i], "ps_2_0"); + if (ps_code) + { + draw_quad(test_context.device, ps_code); + + v = get_color_vec4(test_context.device, 0, 0); + todo_wine ok(compare_vec4(&v, 0.25f, 0.0f, 0.25f, 0.0f, 128), + "Test %u: Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", i, v.x, v.y, v.z, v.w); + + ID3D10Blob_Release(ps_code); + } + } + + IDirect3DTexture9_Release(texture); + release_test_context(&test_context); +} + static void check_constant_desc(const char *prefix, const D3DXCONSTANT_DESC *desc, const D3DXCONSTANT_DESC *expect, BOOL nonzero_defaultvalue) { ok(!strcmp(desc->Name, expect->Name), "%s: got Name %s.\n", prefix, debugstr_a(desc->Name)); ok(desc->RegisterSet == expect->RegisterSet, "%s: got RegisterSet %#x.\n", prefix, desc->RegisterSet); + if (desc->RegisterSet == D3DXRS_SAMPLER) + ok(desc->RegisterIndex == expect->RegisterIndex, "%s: got RegisterIndex %u.\n", prefix, desc->RegisterIndex); ok(desc->RegisterCount == expect->RegisterCount, "%s: got RegisterCount %u.\n", prefix, desc->RegisterCount); ok(desc->Class == expect->Class, "%s: got Class %#x.\n", prefix, desc->Class); ok(desc->Type == expect->Type, "%s: got Type %#x.\n", prefix, desc->Type); @@ -1093,9 +1180,28 @@ static void test_constant_table(void) "uniform matrix_t i;\n" "uniform struct matrix_record j;\n" "uniform matrix k;\n" - "float4 main(uniform float4 h) : COLOR\n" + "sampler l : register(s5);\n" + "sampler m {};\n" + "texture dummy_texture;\n" + "sampler n\n" "{\n" - " return a + b + c._31 + d._31 + f.d._22 + g[e].x + h + i._33 + j.a._33 + k._31;\n" + " Texture = dummy_texture;\n" + " foo = bar + 2;\n" + "};\n" + "SamplerState o\n" + "{\n" + " Texture = dummy_texture;\n" + " foo = bar + 2;\n" + "};\n" + "texture2D p;\n" + "sampler q : register(s7);\n" + "SamplerState r : register(s8);\n" + "sampler2D s;\n" + "float4 main(uniform float4 h, sampler t, uniform sampler u) : COLOR\n" + "{\n" + " return b + c._31 + d._31 + f.d._22 + tex2D(l, g[e]) + tex3D(m, h.xyz) + i._33 + j.a._33 + k._31\n" + " + tex2D(n, a.xy) + tex2D(o, a.xy) + p.Sample(r, a.xy) + p.Sample(q, a.xy) + tex2D(s, a.xy)\n" + " + tex2D(t, a.xy) + tex2D(u, a.xy);\n" "}"; D3DXCONSTANTTABLE_DESC table_desc; @@ -1110,6 +1216,7 @@ static void test_constant_table(void) static const D3DXCONSTANT_DESC expect_constants[] = { {"$h", D3DXRS_FLOAT4, 0, 1, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 4, 1, 0, 16}, + {"$u", D3DXRS_SAMPLER, 10, 1, D3DXPC_OBJECT, D3DXPT_SAMPLER2D, 1, 1, 1, 0, 4}, {"a", D3DXRS_FLOAT4, 0, 1, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 4, 1, 0, 16}, {"b", D3DXRS_FLOAT4, 0, 1, D3DXPC_SCALAR, D3DXPT_FLOAT, 1, 1, 1, 0, 4}, {"c", D3DXRS_FLOAT4, 0, 1, D3DXPC_MATRIX_COLUMNS, D3DXPT_FLOAT, 3, 1, 1, 0, 12}, @@ -1120,6 +1227,14 @@ static void test_constant_table(void) {"i", D3DXRS_FLOAT4, 0, 3, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 3, 3, 1, 0, 36}, {"j", D3DXRS_FLOAT4, 0, 3, D3DXPC_STRUCT, D3DXPT_VOID, 1, 9, 1, 1, 36}, {"k", D3DXRS_FLOAT4, 0, 3, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 3, 1, 1, 0, 12}, + {"l", D3DXRS_SAMPLER, 5, 1, D3DXPC_OBJECT, D3DXPT_SAMPLER2D, 1, 1, 1, 0, 4}, + {"m", D3DXRS_SAMPLER, 2, 1, D3DXPC_OBJECT, D3DXPT_SAMPLER3D, 1, 1, 1, 0, 4}, + {"n", D3DXRS_SAMPLER, 3, 1, D3DXPC_OBJECT, D3DXPT_SAMPLER2D, 1, 1, 1, 0, 4}, + {"o", D3DXRS_SAMPLER, 4, 1, D3DXPC_OBJECT, D3DXPT_SAMPLER2D, 1, 1, 1, 0, 4}, + {"q+p", D3DXRS_SAMPLER, 0, 1, D3DXPC_OBJECT, D3DXPT_TEXTURE2D, 1, 4, 1, 0, 16}, + {"r+p", D3DXRS_SAMPLER, 1, 1, D3DXPC_OBJECT, D3DXPT_TEXTURE2D, 1, 4, 1, 0, 16}, + {"s", D3DXRS_SAMPLER, 6, 1, D3DXPC_OBJECT, D3DXPT_SAMPLER2D, 1, 1, 1, 0, 4}, + {"t", D3DXRS_SAMPLER, 9, 1, D3DXPC_OBJECT, D3DXPT_SAMPLER2D, 1, 1, 1, 0, 4}, }; static const D3DXCONSTANT_DESC expect_fields_f[] = @@ -1604,6 +1719,7 @@ START_TEST(hlsl_d3d9) test_struct_assignment(); test_struct_semantics(); test_global_initializer(); + test_samplers(); test_constant_table(); test_fail();