Skip to content

Commit

Permalink
lightmap binding working, need to get color meshes working (extra ver…
Browse files Browse the repository at this point in the history
…tex attribute streams tacked on after vertex buffer creation)
  • Loading branch information
PazerOP committed Jun 15, 2019
1 parent b46204a commit caee81e
Show file tree
Hide file tree
Showing 15 changed files with 335 additions and 71 deletions.
1 change: 1 addition & 0 deletions TF2VulkanUtil/TF2VulkanUtil.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
<ClInclude Include="include\TF2Vulkan\Util\ScopeFunc.h" />
<ClInclude Include="include\TF2Vulkan\Util\shaderapi_ishaderdynamic.h" />
<ClInclude Include="include\TF2Vulkan\Util\StackArray.h" />
<ClInclude Include="include\TF2Vulkan\Util\std_iterator.h" />
<ClInclude Include="include\TF2Vulkan\Util\std_memory.h" />
<ClInclude Include="include\TF2Vulkan\Util\std_stack.h" />
<ClInclude Include="include\TF2Vulkan\Util\std_algorithm.h" />
Expand Down
11 changes: 11 additions & 0 deletions TF2VulkanUtil/include/TF2Vulkan/Util/std_algorithm.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,15 @@ namespace Util{ namespace algorithm
using CT = std::common_type_t<T1, T2>;
return std::min<CT>(Util::SafeConvert<CT>(t1), Util::SafeConvert<CT>(t2));
}

template<typename TIter>
inline bool all_of(TIter begin, TIter end)
{
return std::all_of(begin, end, [](const auto& v) { return !!v; });
}
template<typename TContainer>
inline bool all_of(const TContainer& container)
{
return all_of(std::begin(container), std::end(container));
}
} }
20 changes: 20 additions & 0 deletions TF2VulkanUtil/include/TF2Vulkan/Util/std_iterator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#pragma once

#include <iterator>

namespace Util{ namespace iterator
{
template<typename TIter>
struct IterRangeWrapper
{
constexpr IterRangeWrapper(TIter begin, TIter end) : m_Begin(begin), m_End(end) {}

auto begin() { return m_Begin; }
auto end() { return m_End; }
auto begin() const { return m_Begin; }
auto end() const { return m_End; }

TIter m_Begin;
TIter m_End;
};
} }
41 changes: 35 additions & 6 deletions shaderapivulkan/include/TF2Vulkan/IShaderDynamicNext.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,29 @@ namespace TF2Vulkan
virtual int GetCurrentNumBones() const = 0;
virtual void LoadBoneMatrices(Shaders::VSModelMatrices& bones) const = 0;

virtual void BindSamplers(const SamplerSettings* begin, const SamplerSettings* end, bool merge, uint32_t first) = 0;
virtual void BindTextures(const ITexture* const* begin, const ITexture* const* end, bool merge, uint32_t first) = 0;
template<typename T> struct ResourceRange
{
/// <summary>
/// If this is nullptr, then this range of resources is left unmodified.
/// </summary>
const T* m_Resources = nullptr;
size_t m_Count = 0;
size_t m_Offset = 0;
};
using SamplerRange = ResourceRange<SamplerSettings>;
using TextureRange = ResourceRange<const ITexture*>;

/// <summary>
/// Binds multiple contiguous ranges of SamplerSettings.
/// </summary>
/// <param name="merge">False to unbind any samplers not included in the ranges.</param>
virtual void BindSamplerRanges(const SamplerRange* begin, const SamplerRange* end, bool merge) = 0;

/// <summary>
/// Binds multiple contiguous ranges of ITextures.
/// </summary>
/// <param name="merge">False to unbind any textures not included in the ranges.</param>
virtual void BindTextureRanges(const TextureRange* begin, const TextureRange* end, bool merge) = 0;

// Helpers
void SetPixelShader(const IShaderInstance* instance) { SetShaderInstance(ShaderType::Pixel, instance); }
Expand All @@ -66,14 +87,22 @@ namespace TF2Vulkan

void BindSamplers(const SamplerSettings* begin, const SamplerSettings* end)
{
return BindSamplers(begin, end, false, 0);
const SamplerRange range
{
.m_Resources = begin,
.m_Count = size_t(end - begin),
};
return BindSamplerRanges(&range, &range + 1, false);
}
void BindTextures(const ITexture* const* begin, const ITexture* const* end)
{
return BindTextures(begin, end, false, 0);
const TextureRange range
{
.m_Resources = begin,
.m_Count = size_t(end - begin),
};
return BindTextureRanges(&range, &range + 1, false);
}

protected:
};

#define SHADERDYNAMICNEXT_INTERFACE_VERSION "TF2Vulkan_IShaderDynamicNext001"
Expand Down
10 changes: 10 additions & 0 deletions shaderapivulkan/include/TF2Vulkan/ShaderResourceBinder.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ namespace TF2Vulkan
public:
void AddBinding(ITexture& texture, int32_t& texLocationSpecConst, uint32_t& smpLocationSpecConst,
const SamplerSettings* sampler = nullptr);
void AddDummyBinding(int32_t& texLocationSpecConst, uint32_t& smpLocationSpecConst,
const SamplerSettings* sampler = nullptr);

const auto& GetTextures() const { return m_Textures; }
const auto& GetSamplers() const { return m_Samplers; }
Expand All @@ -30,6 +32,14 @@ namespace TF2Vulkan
Util::InPlaceVector<SamplerSettings, MAX_SHADER_RESOURCE_BINDINGS> m_Samplers;
};

inline void ShaderTextureBinder::AddDummyBinding(int32_t& texLocationSpecConst,
uint32_t& smpLocationSpecConst, const SamplerSettings* sampler)
{
texLocationSpecConst = m_Textures.size();
m_Textures.push_back(nullptr);
smpLocationSpecConst = FindOrInsertSampler(sampler ? *sampler : SamplerSettings{});
}

inline void ShaderTextureBinder::AddBinding(ITexture& texture, int32_t& texLocationSpecConst,
uint32_t& smpLocationSpecConst, const SamplerSettings* sampler)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
#include <TF2Vulkan/Util/Color.h>
#include <TF2Vulkan/Util/DirtyVar.h>
#include <TF2Vulkan/Util/platform.h>
#include <TF2Vulkan/Util/std_iterator.h>

#include <materialsystem/IShader.h>
#include <materialsystem/imaterialvar.h>
#include <shaderapi/ishaderutil.h>

#undef min
#undef max
Expand Down Expand Up @@ -177,7 +179,16 @@ void IShaderAPI_StateManagerDynamic::Bind(IMaterial* material)
void IShaderAPI_StateManagerDynamic::BindTexture(Sampler_t sampler, ShaderAPITextureHandle_t textureHandle)
{
LOG_FUNC();
return BindTextures(&textureHandle, &textureHandle + 1, true, sampler - SHADER_SAMPLER0);

assert(sampler >= SHADER_SAMPLER0);
const ShaderAPITextureRange range
{
.m_Resources = &textureHandle,
.m_Count = 1,
.m_Offset = size_t(sampler - SHADER_SAMPLER0),
};

return BindTextureRanges(&range, &range + 1, true);
}

IShaderAPI_StateManagerDynamic::IShaderAPI_StateManagerDynamic()
Expand Down Expand Up @@ -336,75 +347,140 @@ void IShaderAPI_StateManagerDynamic::BindUniformBuffer(const BufferPoolEntry& bu
Util::SetDirtyVar(m_State.m_UniformBuffers, index, buf, m_Dirty);
}

void IShaderAPI_StateManagerDynamic::BindSamplers(const SamplerSettings* begin, const SamplerSettings* end, bool merge, uint32_t first)
template<typename T, typename TOnBindFunc = void*>
static void BindRanges(const IShaderDynamicNext::ResourceRange<T>* begin, const IShaderDynamicNext::ResourceRange<T>* end,
bool merge, Util::InPlaceVector<T, MAX_SHADER_RESOURCE_BINDINGS>& bindsVec, bool& dirty, const T& defaultVal,
const TOnBindFunc& onBindFunc = nullptr)
{
LOG_FUNC();
const size_t count = end - begin;

if (!merge)
uint32_t assignedCount = 0;
uint32_t unassignedSlots = std::numeric_limits<uint32_t>::max();
static_assert(MAX_SHADER_RESOURCE_BINDINGS <= sizeof(unassignedSlots) * CHAR_BIT);

for (const auto& range : Util::iterator::IterRangeWrapper(begin, end))
{
if (m_State.m_BoundSamplers.size() != count)
for (size_t i = 0; i < range.m_Count; i++)
{
m_Dirty = true;
m_State.m_BoundSamplers.resize(count);
}
const uint32_t bindIndex = range.m_Offset + i;

if (bindIndex >= assignedCount)
assignedCount = bindIndex + 1;

if (range.m_Resources)
{
if (bindsVec.size() <= bindIndex)
bindsVec.resize(bindIndex + 1);

if constexpr (!std::is_same_v<TOnBindFunc, void*>)
onBindFunc(bindIndex, range.m_Resources[i]);

Util::SetDirtyVar(bindsVec.at(bindIndex), range.m_Resources[i], dirty);
}
else
{
assert(unassignedSlots & (1 << bindIndex)); // Check for overlapping ranges
}

for (size_t i = 0; i < count; i++)
Util::SetDirtyVar(m_State.m_BoundSamplers[i], begin[i], m_Dirty);
unassignedSlots &= ~(1 << bindIndex);
}
}
else

if (!merge)
{
NOT_IMPLEMENTED_FUNC();
// Shrink to fit
if (bindsVec.size() != assignedCount)
{
dirty = true;
bindsVec.resize(assignedCount);
}

for (size_t i = 0; i < assignedCount; i++)
{
if (unassignedSlots & (1 << i))
bindsVec[i] = defaultVal;
}
}
}

void IShaderAPI_StateManagerDynamic::BindTextures(
const ITexture* const* begin, const ITexture* const* end, bool merge, uint32_t first)
void IShaderAPI_StateManagerDynamic::BindSamplerRanges(const SamplerRange* begin, const SamplerRange* end, bool merge)
{
LOG_FUNC();
const size_t count = end - begin;
return BindRanges(begin, end, merge, m_State.m_BoundSamplers, m_Dirty, SamplerSettings{});
}

auto handles = (ShaderAPITextureHandle_t*)_alloca(sizeof(ShaderAPITextureHandle_t) * count);
void IShaderAPI_StateManagerDynamic::BindTextureRanges(
const ShaderAPITextureRange* begin, const ShaderAPITextureRange* end, bool merge)
{
LOG_FUNC();
return BindRanges(begin, end, merge, m_State.m_BoundTextures, m_Dirty, INVALID_SHADERAPI_TEXTURE_HANDLE,
[&](uint32_t index, ShaderAPITextureHandle_t texID)
{
auto texDbgName = texID ? GetTexture(texID).GetDebugName() : "<NULL>";
TF2VULKAN_PIX_MARKER("BindTexture%s %.*s @ g_Textures2D[%zu]",
merge ? "(merge)" : "", PRINTF_SV(texDbgName), index);
});
}

auto test0 = &ITextureInternal::SetErrorTexture;
#pragma warning(suppress : 4996)
auto test1 = static_cast<void(ITextureInternal::*)(Sampler_t)>(&ITextureInternal::Bind);
auto test2 = &ITextureInternal::GetTextureHandle;
void IShaderAPI_StateManagerDynamic::BindStandardTexture(Sampler_t sampler, StandardTextureId_t id)
{
LOG_FUNC();

for (size_t i = 0; i < count; i++)
if (auto handle = GetStdTextureHandle(id); handle != INVALID_SHADERAPI_TEXTURE_HANDLE)
{
auto texInternal = assert_cast<const ITextureInternal*>(begin[i]);
handles[i] = texInternal->GetTextureHandle(0);
BindTexture(sampler, GetStdTextureHandle(id));
}
else
{
g_ShaderUtil->BindStandardTexture(sampler, id);
}

return BindTextures(handles, handles + count, merge, first);
}

void IShaderAPI_StateManagerDynamic::BindTextures(
const ShaderAPITextureHandle_t* begin, const ShaderAPITextureHandle_t* end, bool merge, uint32_t first)
void IShaderAPI_StateManagerDynamic::BindTextureRanges(
const TextureRange* begin, const TextureRange* end, bool merge)
{
LOG_FUNC();
const size_t count = end - begin;
const size_t rangesCount = end - begin;

if (!merge)
auto outputRanges = (ShaderAPITextureRange*)_alloca(sizeof(ShaderAPITextureRange) * rangesCount);

size_t texCount = 0;
// Count the number of ITexture* pointers inside all of the ranges
for (auto& inputRange : Util::iterator::IterRangeWrapper{ begin, end })
{
if (inputRange.m_Resources)
texCount += inputRange.m_Count;
}

// Stack allocate a single buffer for all of the ShaderAPITextureHandle_t inside our output ranges
auto texturePointers = (ShaderAPITextureHandle_t*)_alloca(sizeof(ShaderAPITextureHandle_t) * texCount);
texCount = 0;

// Create all of our output ranges
for (size_t rangeIndex = 0; rangeIndex < rangesCount; rangeIndex++)
{
if (m_State.m_BoundTextures.size() != count)
const auto& inputRange = begin[rangeIndex];
auto& outputRange = outputRanges[rangeIndex];
outputRange.m_Count = inputRange.m_Count;
outputRange.m_Offset = inputRange.m_Offset;

if (inputRange.m_Resources)
{
m_Dirty = true;
m_State.m_BoundTextures.resize(count);
auto* outHandles = &texturePointers[texCount];
outputRange.m_Resources = outHandles;
for (size_t i = 0; i < inputRange.m_Count; i++)
{
auto texInternal = assert_cast<const ITextureInternal*>(inputRange.m_Resources[i]);
outHandles[i] = texInternal->GetTextureHandle(0);
}
}

for (size_t i = 0; i < count; i++)
else
{
auto texDbgName = begin[i] ? GetTexture(begin[i]).GetDebugName() : "<NULL>";
TF2VULKAN_PIX_MARKER("BindTexture %.*s @ g_Textures2D[%zu]", PRINTF_SV(texDbgName), i);
Util::SetDirtyVar(m_State.m_BoundTextures[i], begin[i], m_Dirty);
outputRange.m_Resources = nullptr;
}
}
else
{
NOT_IMPLEMENTED_FUNC();
}

return BindTextureRanges(outputRanges, outputRanges + rangesCount, merge);
}

void IShaderAPI_StateManagerDynamic::SetOverbright(float overbright)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,11 +154,14 @@ namespace TF2Vulkan
void SetSkinningMatrices() override final;

// IShaderDynamicNext
using ShaderAPITextureRange = ResourceRange<ShaderAPITextureHandle_t>;
void SetShaderInstance(ShaderType type, const IShaderInstance* instance) override final;
void BindUniformBuffer(const BufferPoolEntry& buf, UniformBufferIndex index) override final;
void BindSamplers(const SamplerSettings* begin, const SamplerSettings* end, bool merge, uint32_t first) override final;
void BindTextures(const ITexture* const* begin, const ITexture* const* end, bool merge, uint32_t first) override final;
void BindTextures(const ShaderAPITextureHandle_t* begin, const ShaderAPITextureHandle_t* end, bool merge, uint32_t first);
void BindSamplerRanges(const SamplerRange* begin, const SamplerRange* end, bool merge) override final;
void BindTextureRanges(const TextureRange* begin, const TextureRange* end, bool merge) override final;
void BindTextureRanges(const ShaderAPITextureRange* begin, const ShaderAPITextureRange* end, bool merge);
void BindStandardTexture(Sampler_t sampler, StandardTextureId_t id) override final;
void BindStandardVertexTexture(VertexTextureSampler_t sampler, StandardTextureId_t id) override final { NOT_IMPLEMENTED_FUNC(); }

// Helpers
void SetOverbright(float overbright);
Expand Down
10 changes: 0 additions & 10 deletions shaderapivulkan/src/TF2Vulkan/IShaderAPI/ShaderAPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,9 +226,6 @@ namespace
void OverrideAlphaWriteEnable(bool enable, bool alphaWriteEnable) override { NOT_IMPLEMENTED_FUNC(); }
void OverrideColorWriteEnable(bool overrideEnable, bool colorWriteEnable) override { NOT_IMPLEMENTED_FUNC(); }

void BindStandardTexture(Sampler_t sampler, StandardTextureId_t id) override;
void BindStandardVertexTexture(VertexTextureSampler_t sampler, StandardTextureId_t id) override { NOT_IMPLEMENTED_FUNC(); }

ITexture* GetRenderTargetEx(int renderTargetID) override;

void GetDXLevelDefaults(uint& dxLevelMax, uint& dxLevelRecommended) override { NOT_IMPLEMENTED_FUNC(); }
Expand Down Expand Up @@ -925,13 +922,6 @@ void ShaderAPI::EndFrame()
m_IsInFrame = false;
}

void ShaderAPI::BindStandardTexture(Sampler_t sampler, StandardTextureId_t id)
{
// TODO: Move to IShaderAPI_StateManagerDynamic
LOG_FUNC();
BindTexture(sampler, GetStdTextureHandle(id));
}

void ShaderAPI::InvalidateDelayedShaderConstants()
{
// We don't use this functionality (dynamic uniform buffers are used instead)
Expand Down
Loading

0 comments on commit caee81e

Please sign in to comment.