Skip to content

Commit e59aee1

Browse files
csyongheTim Foley
and
Tim Foley
authored
Add SampleGrad overload for lod clamp. (shader-slang#1711)
* Add `SampleGrad` overload for lod clamp. * Fix gfx to run the test on vulkan. * Whitespace change to trigger CI build * remove presentFrame call in render-test Co-authored-by: Yong He <yhe@nvidia.com> Co-authored-by: Tim Foley <tfoleyNV@users.noreply.github.com>
1 parent 39975b2 commit e59aee1

7 files changed

+208
-24
lines changed

source/slang/core.meta.slang

+10
Original file line numberDiff line numberDiff line change
@@ -1358,6 +1358,16 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
13581358
sb << "float" << kBaseTextureTypes[tt].coordCount << " gradX, ";
13591359
sb << "float" << kBaseTextureTypes[tt].coordCount << " gradY, ";
13601360
sb << "constexpr int" << kBaseTextureTypes[tt].coordCount << " offset);\n";
1361+
1362+
sb << "__glsl_extension(GL_ARB_sparse_texture_clamp)";
1363+
sb << "__target_intrinsic(glsl, \"$ctextureGradOffsetClampARB($p, $2, $3, $4, $5, $6)$z\")\n";
1364+
sb << "T SampleGrad(SamplerState s, ";
1365+
sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, ";
1366+
sb << "float" << kBaseTextureTypes[tt].coordCount << " gradX, ";
1367+
sb << "float" << kBaseTextureTypes[tt].coordCount << " gradY, ";
1368+
sb << "constexpr int" << kBaseTextureTypes[tt].coordCount << " offset, ";
1369+
sb << "float lodClamp);\n";
1370+
13611371
}
13621372

13631373
// `SampleLevel`

source/slang/slang-reflection-api.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -1148,6 +1148,10 @@ namespace Slang
11481148
{
11491149
return SLANG_BINDING_TYPE_CONSTANT_BUFFER;
11501150
}
1151+
else if( as<SamplerStateType>(type) )
1152+
{
1153+
return SLANG_BINDING_TYPE_SAMPLER;
1154+
}
11511155
else
11521156
{
11531157
return SLANG_BINDING_TYPE_UNKNOWN;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
//TEST(compute, vulkan):COMPARE_RENDER_COMPUTE:-vk -shaderobj
2+
//TEST(compute):COMPARE_RENDER_COMPUTE:-shaderobj
3+
4+
//TEST_INPUT: Texture2D(size=4, content = one):name=t2D
5+
//TEST_INPUT: Sampler:name=samplerState
6+
//TEST_INPUT: ubuffer(data=[0], stride=4):out,name=outputBuffer
7+
8+
Texture2D t2D;
9+
SamplerState samplerState;
10+
RWStructuredBuffer<float> outputBuffer;
11+
12+
cbuffer Uniforms
13+
{
14+
float4x4 modelViewProjection;
15+
}
16+
17+
struct AssembledVertex
18+
{
19+
float3 position;
20+
float3 color;
21+
float2 uv;
22+
};
23+
24+
struct CoarseVertex
25+
{
26+
float3 color;
27+
float2 uv;
28+
};
29+
30+
struct Fragment
31+
{
32+
float4 color;
33+
};
34+
35+
36+
// Vertex Shader
37+
38+
struct VertexStageInput
39+
{
40+
AssembledVertex assembledVertex : A;
41+
};
42+
43+
struct VertexStageOutput
44+
{
45+
CoarseVertex coarseVertex : CoarseVertex;
46+
float4 sv_position : SV_Position;
47+
};
48+
49+
VertexStageOutput vertexMain(VertexStageInput input)
50+
{
51+
VertexStageOutput output;
52+
53+
float3 position = input.assembledVertex.position;
54+
float3 color = input.assembledVertex.color;
55+
56+
output.coarseVertex.color = color;
57+
output.sv_position = mul(modelViewProjection, float4(position, 1.0));
58+
output.coarseVertex.uv = input.assembledVertex.uv;
59+
return output;
60+
}
61+
62+
// Fragment Shader
63+
64+
struct FragmentStageInput
65+
{
66+
CoarseVertex coarseVertex : CoarseVertex;
67+
};
68+
69+
struct FragmentStageOutput
70+
{
71+
Fragment fragment : SV_Target;
72+
};
73+
74+
FragmentStageOutput fragmentMain(FragmentStageInput input)
75+
{
76+
FragmentStageOutput output;
77+
78+
float3 color = input.coarseVertex.color;
79+
float2 uv = input.coarseVertex.uv;
80+
output.fragment.color = float4(color, 1.0);
81+
82+
float4 val = t2D.SampleGrad(samplerState, uv, float2(0,0), float2(0,0), 0, 0.5f);
83+
outputBuffer[0] = val.x;
84+
return output;
85+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3F800000

tools/gfx/render.h

-2
Original file line numberDiff line numberDiff line change
@@ -1039,8 +1039,6 @@ struct GraphicsPipelineStateDesc
10391039
IPipelineLayout* pipelineLayout = nullptr;
10401040

10411041
IInputLayout* inputLayout;
1042-
UInt framebufferWidth;
1043-
UInt framebufferHeight;
10441042
UInt renderTargetCount = 0; // Only used if `pipelineLayout` is non-null
10451043
DepthStencilDesc depthStencil;
10461044
RasterizerDesc rasterizer;

tools/gfx/vulkan/render-vk.cpp

+107-22
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,14 @@ class VKRenderer : public GraphicsAPIRenderer
249249
}
250250
public:
251251
VkSampler m_sampler;
252+
const VulkanApi* m_api;
253+
SamplerStateImpl(const VulkanApi* api)
254+
: m_api(api)
255+
{}
256+
~SamplerStateImpl()
257+
{
258+
m_api->vkDestroySampler(m_api->m_device, m_sampler, nullptr);
259+
}
252260
};
253261

254262
class ResourceViewImpl : public IResourceView, public RefObject
@@ -268,17 +276,26 @@ class VKRenderer : public GraphicsAPIRenderer
268276
TexelBuffer,
269277
PlainBuffer,
270278
};
279+
public:
280+
ResourceViewImpl(ViewType viewType, const VulkanApi* api)
281+
: m_type(viewType), m_api(api)
282+
{
283+
}
271284
ViewType m_type;
285+
const VulkanApi* m_api;
272286
};
273287

274288
class TextureResourceViewImpl : public ResourceViewImpl
275289
{
276290
public:
277-
TextureResourceViewImpl()
291+
TextureResourceViewImpl(const VulkanApi* api)
292+
: ResourceViewImpl(ViewType::Texture, api)
278293
{
279-
m_type = ViewType::Texture;
280294
}
281-
295+
~TextureResourceViewImpl()
296+
{
297+
m_api->vkDestroyImageView(m_api->m_device, m_view, nullptr);
298+
}
282299
RefPtr<TextureResourceImpl> m_texture;
283300
VkImageView m_view;
284301
VkImageLayout m_layout;
@@ -287,23 +304,25 @@ class VKRenderer : public GraphicsAPIRenderer
287304
class TexelBufferResourceViewImpl : public ResourceViewImpl
288305
{
289306
public:
290-
TexelBufferResourceViewImpl()
307+
TexelBufferResourceViewImpl(const VulkanApi* api)
308+
: ResourceViewImpl(ViewType::TexelBuffer, api)
291309
{
292-
m_type = ViewType::TexelBuffer;
293310
}
294-
311+
~TexelBufferResourceViewImpl()
312+
{
313+
m_api->vkDestroyBufferView(m_api->m_device, m_view, nullptr);
314+
}
295315
RefPtr<BufferResourceImpl> m_buffer;
296316
VkBufferView m_view;
297317
};
298318

299319
class PlainBufferResourceViewImpl : public ResourceViewImpl
300320
{
301321
public:
302-
PlainBufferResourceViewImpl()
322+
PlainBufferResourceViewImpl(const VulkanApi* api)
323+
: ResourceViewImpl(ViewType::PlainBuffer, api)
303324
{
304-
m_type = ViewType::PlainBuffer;
305325
}
306-
307326
RefPtr<BufferResourceImpl> m_buffer;
308327
VkDeviceSize offset;
309328
VkDeviceSize size;
@@ -1989,16 +2008,68 @@ Result VKRenderer::createSamplerState(ISamplerState::Desc const& desc, ISamplerS
19892008
VkSampler sampler;
19902009
SLANG_VK_RETURN_ON_FAIL(m_api.vkCreateSampler(m_device, &samplerInfo, nullptr, &sampler));
19912010

1992-
RefPtr<SamplerStateImpl> samplerImpl = new SamplerStateImpl();
2011+
RefPtr<SamplerStateImpl> samplerImpl = new SamplerStateImpl(&m_api);
19932012
samplerImpl->m_sampler = sampler;
19942013
*outSampler = samplerImpl.detach();
19952014
return SLANG_OK;
19962015
}
19972016

19982017
Result VKRenderer::createTextureView(ITextureResource* texture, IResourceView::Desc const& desc, IResourceView** outView)
19992018
{
2000-
assert(!"unimplemented");
2001-
return SLANG_FAIL;
2019+
auto resourceImpl = static_cast<TextureResourceImpl*>(texture);
2020+
RefPtr<TextureResourceViewImpl> view = new TextureResourceViewImpl(&m_api);
2021+
view->m_texture = resourceImpl;
2022+
VkImageViewCreateInfo createInfo = {};
2023+
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
2024+
createInfo.flags = 0;
2025+
createInfo.format = VulkanUtil::getVkFormat(desc.format);
2026+
createInfo.image = resourceImpl->m_image;
2027+
createInfo.components = VkComponentMapping{ VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,VK_COMPONENT_SWIZZLE_B,VK_COMPONENT_SWIZZLE_A };
2028+
switch (resourceImpl->getType())
2029+
{
2030+
case IResource::Type::Texture1D:
2031+
createInfo.viewType = VK_IMAGE_VIEW_TYPE_1D;
2032+
break;
2033+
case IResource::Type::Texture2D:
2034+
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
2035+
break;
2036+
case IResource::Type::Texture3D:
2037+
createInfo.viewType = VK_IMAGE_VIEW_TYPE_3D;
2038+
break;
2039+
case IResource::Type::TextureCube:
2040+
createInfo.viewType = VK_IMAGE_VIEW_TYPE_CUBE;
2041+
break;
2042+
default:
2043+
SLANG_UNIMPLEMENTED_X("Unknown Texture type.");
2044+
break;
2045+
}
2046+
createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
2047+
createInfo.subresourceRange.baseArrayLayer = 0;
2048+
createInfo.subresourceRange.baseMipLevel = 0;
2049+
createInfo.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
2050+
createInfo.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
2051+
switch (desc.type)
2052+
{
2053+
case IResourceView::Type::DepthStencil:
2054+
view->m_layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
2055+
createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
2056+
break;
2057+
case IResourceView::Type::RenderTarget:
2058+
view->m_layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
2059+
break;
2060+
case IResourceView::Type::ShaderResource:
2061+
view->m_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
2062+
break;
2063+
case IResourceView::Type::UnorderedAccess:
2064+
view->m_layout = VK_IMAGE_LAYOUT_GENERAL;
2065+
break;
2066+
default:
2067+
SLANG_UNIMPLEMENTED_X("Unknown TextureViewDesc type.");
2068+
break;
2069+
}
2070+
m_api.vkCreateImageView(m_device, &createInfo, nullptr, &view->m_view);
2071+
*outView = view.detach();
2072+
return SLANG_OK;
20022073
}
20032074

20042075
Result VKRenderer::createBufferView(IBufferResource* buffer, IResourceView::Desc const& desc, IResourceView** outView)
@@ -2041,7 +2112,7 @@ Result VKRenderer::createBufferView(IBufferResource* buffer, IResourceView::Desc
20412112
{
20422113
// Buffer usage that doesn't involve formatting doesn't
20432114
// require a view in Vulkan.
2044-
RefPtr<PlainBufferResourceViewImpl> viewImpl = new PlainBufferResourceViewImpl();
2115+
RefPtr<PlainBufferResourceViewImpl> viewImpl = new PlainBufferResourceViewImpl(&m_api);
20452116
viewImpl->m_buffer = resourceImpl;
20462117
viewImpl->offset = 0;
20472118
viewImpl->size = size;
@@ -2065,7 +2136,7 @@ Result VKRenderer::createBufferView(IBufferResource* buffer, IResourceView::Desc
20652136
VkBufferView view;
20662137
SLANG_VK_RETURN_ON_FAIL(m_api.vkCreateBufferView(m_device, &info, nullptr, &view));
20672138

2068-
RefPtr<TexelBufferResourceViewImpl> viewImpl = new TexelBufferResourceViewImpl();
2139+
RefPtr<TexelBufferResourceViewImpl> viewImpl = new TexelBufferResourceViewImpl(&m_api);
20692140
viewImpl->m_buffer = resourceImpl;
20702141
viewImpl->m_view = view;
20712142
*outView = viewImpl.detach();
@@ -2698,7 +2769,6 @@ void VKRenderer::DescriptorSetImpl::setResource(UInt range, UInt index, IResourc
26982769
VkDescriptorImageInfo imageInfo = {};
26992770
imageInfo.imageView = textureViewImpl->m_view;
27002771
imageInfo.imageLayout = textureViewImpl->m_layout;
2701-
// imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
27022772

27032773
VkWriteDescriptorSet writeInfo = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
27042774
writeInfo.dstSet = m_descriptorSet;
@@ -2762,7 +2832,16 @@ void VKRenderer::DescriptorSetImpl::setSampler(UInt range, UInt index, ISamplerS
27622832
auto boundObjectIndex = rangeInfo.arrayIndex + index;
27632833
auto descriptorType = rangeInfo.vkDescriptorType;
27642834

2765-
// TODO: Actually bind it!
2835+
VkWriteDescriptorSet writeInfo = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
2836+
writeInfo.dstSet = m_descriptorSet;
2837+
writeInfo.dstBinding = uint32_t(bindingIndex);
2838+
writeInfo.dstArrayElement = uint32_t(index);
2839+
writeInfo.descriptorCount = 1;
2840+
writeInfo.descriptorType = descriptorType;
2841+
VkDescriptorImageInfo imageInfo = {};
2842+
imageInfo.sampler = static_cast<SamplerStateImpl*>(sampler)->m_sampler;
2843+
writeInfo.pImageInfo = &imageInfo;
2844+
m_renderer->m_api.vkUpdateDescriptorSets(m_renderer->m_device, 1, &writeInfo, 0, nullptr);
27662845

27672846
m_boundObjects[boundObjectIndex] = dynamic_cast<RefObject*>(sampler);
27682847
}
@@ -2885,9 +2964,6 @@ Result VKRenderer::createGraphicsPipelineState(const GraphicsPipelineStateDesc&
28852964
auto pipelineLayoutImpl = (PipelineLayoutImpl*) desc.pipelineLayout;
28862965
auto inputLayoutImpl = (InputLayoutImpl*) desc.inputLayout;
28872966

2888-
const int width = int(desc.framebufferWidth);
2889-
const int height = int(desc.framebufferHeight);
2890-
28912967
// Shader Stages
28922968
//
28932969
// Currently only handles vertex/fragment.
@@ -2932,14 +3008,16 @@ Result VKRenderer::createGraphicsPipelineState(const GraphicsPipelineStateDesc&
29323008
VkViewport viewport = {};
29333009
viewport.x = 0.0f;
29343010
viewport.y = 0.0f;
2935-
viewport.width = (float)width;
2936-
viewport.height = (float)height;
3011+
// We are using dynamic viewport and scissor state.
3012+
// Here we specify an arbitrary size, actual viewport will be set at `beginRenderPass` time.
3013+
viewport.width = 16.0f;
3014+
viewport.height = 16.0f;
29373015
viewport.minDepth = 0.0f;
29383016
viewport.maxDepth = 1.0f;
29393017

29403018
VkRect2D scissor = {};
29413019
scissor.offset = { 0, 0 };
2942-
scissor.extent = { uint32_t(width), uint32_t(height) };
3020+
scissor.extent = { uint32_t(16), uint32_t(16) };
29433021

29443022
VkPipelineViewportStateCreateInfo viewportState = {};
29453023
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
@@ -2978,6 +3056,12 @@ Result VKRenderer::createGraphicsPipelineState(const GraphicsPipelineStateDesc&
29783056
colorBlending.blendConstants[2] = 0.0f;
29793057
colorBlending.blendConstants[3] = 0.0f;
29803058

3059+
VkPipelineDynamicStateCreateInfo dynamicStateInfo = {};
3060+
dynamicStateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
3061+
dynamicStateInfo.dynamicStateCount = 2;
3062+
VkDynamicState dynamicStates[] = { VK_DYNAMIC_STATE_VIEWPORT , VK_DYNAMIC_STATE_SCISSOR};
3063+
dynamicStateInfo.pDynamicStates = dynamicStates;
3064+
29813065
VkGraphicsPipelineCreateInfo pipelineInfo = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO };
29823066

29833067
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
@@ -2993,6 +3077,7 @@ Result VKRenderer::createGraphicsPipelineState(const GraphicsPipelineStateDesc&
29933077
pipelineInfo.renderPass = m_renderPass;
29943078
pipelineInfo.subpass = 0;
29953079
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
3080+
pipelineInfo.pDynamicState = &dynamicStateInfo;
29963081

29973082
VkPipeline pipeline = VK_NULL_HANDLE;
29983083
SLANG_VK_CHECK(m_api.vkCreateGraphicsPipelines(m_device, pipelineCache, 1, &pipelineInfo, nullptr, &pipeline));

tools/render-test/render-test-main.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,7 @@ SlangResult _assignVarsFromLayout(
357357

358358
IResourceView::Desc viewDesc;
359359
viewDesc.type = IResourceView::Type::ShaderResource;
360+
viewDesc.format = texture->getDesc()->format;
360361
auto textureView = renderer->createTextureView(
361362
texture,
362363
viewDesc);

0 commit comments

Comments
 (0)